Hello world example of a TLS client: fetch an HTTPS page. The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-tls

HTTPS File Download Example for TLS Client on mbed OS

This application downloads a file from an HTTPS server (developer.mbed.org) and looks for a specific string in that file.

Getting started

Building with mbed CLI

If you'd like to use mbed CLI to build this, then you should set up your environment if you have not done so already. For instructions, refer to the main readme. The instructions here relate to using the developer.mbed.org Online Compiler

Import the program in to the Online Compiler, select your board from the drop down in the top right hand corner and then compile the application. Once it has built, you can drag and drop the binary onto your device.

Required hardware

This example also requires an Ethernet cable an connection to the internet additional to the hardware requirements in the main readme.

Monitoring the application

NOTE: Make sure that the Ethernet cable is plugged in correctly before running the application.

The output in the terminal window should be similar to this:

terminal output

Using Ethernet LWIP
Client IP Address is 10.2.203.43
Connecting with developer.mbed.org
Starting the TLS handshake...
TLS connection to developer.mbed.org established
Server certificate:
    cert. version     : 3
    serial number     : 11:21:B8:47:9B:21:6C:B1:C6:AF:BC:5D:0C:19:52:DC:D7:C3
    issuer name       : C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA - SHA256 - G2
    subject name      : C=GB, ST=Cambridgeshire, L=Cambridge, O=ARM Ltd, CN=*.mbed.com
    issued  on        : 2016-03-03 12:26:08
    expires on        : 2017-04-05 10:31:02
    signed using      : RSA with SHA-256
    RSA key size      : 2048 bits
    basic constraints : CA=false
    subject alt name  : *.mbed.com, mbed.org, *.mbed.org, mbed.com
    key usage         : Digital Signature, Key Encipherment
    ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
Certificate verification passed

HTTPS: Received 439 chars from server
HTTPS: Received 200 OK status ... [OK]
HTTPS: Received 'Hello world!' status ... [OK]
HTTPS: Received message:

HTTP/1.1 200 OK
Server: nginx/1.7.10
Date: Wed, 20 Jul 2016 10:00:35 GMT
Content-Type: text/plain
Content-Length: 14
Connection: keep-alive
Last-Modified: Fri, 27 Jul 2012 13:30:34 GMT
Accept-Ranges: bytes
Cache-Control: max-age=36000
Expires: Wed, 20 Jul 2016 20:00:35 GMT
X-Upstream-L3: 172.17.0.3:80
X-Upstream-L2: developer-sjc-indigo-1-nginx
Strict-Transport-Security: max-age=31536000; includeSubdomains

Hello world!

Debugging the TLS connection

To print out more debug information about the TLS connection, edit the file `main.cpp` and change the definition of `DEBUG_LEVEL` (near the top of the file) from 0 to a positive number:

  • Level 1 only prints non-zero return codes from SSL functions and information about the full certificate chain being verified.
  • Level 2 prints more information about internal state updates.
  • Level 3 is intermediate.
  • Level 4 (the maximum) includes full binary dumps of the packets.

The TLS connection can fail with an error similar to:

error message

    mbedtls_ssl_write() failed: -0x2700 (-9984): X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
    Failed to fetch /media/uploads/mbed_official/hello.txt from developer.mbed.org:443

This probably means you need to update the contents of the SSL_CA_PEM constant (this can happen if you modify HTTPS_SERVER_NAME, or when developer.mbed.org switches to a new CA when updating its certificate).

Another possible reason for this error is a proxy providing a different certificate. Proxies can be used in some network configurations or for performing man-in-the-middle attacks. If you choose to ignore this error and proceed with the connection anyway, you can change the definition of UNSAFE near the top of the file from 0 to 1.

Warning: this removes all security against a possible active attacker, so use at your own risk or for debugging only!

Committer:
mbed_official
Date:
Fri May 04 12:30:06 2018 +0100
Revision:
66:ce8709d9912c
Child:
69:ffefb2e2d149
Merge pull request #87 from andresag01/iotssl-1247-tls-client-refactoring

Refactor tls-client example to improve readability
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-tls

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 66:ce8709d9912c 1 /*
mbed_official 66:ce8709d9912c 2 * Hello world example of a TLS client: fetch an HTTPS page
mbed_official 66:ce8709d9912c 3 *
mbed_official 66:ce8709d9912c 4 * Copyright (C) 2006-2018, Arm Limited, All Rights Reserved
mbed_official 66:ce8709d9912c 5 * SPDX-License-Identifier: Apache-2.0
mbed_official 66:ce8709d9912c 6 *
mbed_official 66:ce8709d9912c 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
mbed_official 66:ce8709d9912c 8 * not use this file except in compliance with the License.
mbed_official 66:ce8709d9912c 9 * You may obtain a copy of the License at
mbed_official 66:ce8709d9912c 10 *
mbed_official 66:ce8709d9912c 11 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 66:ce8709d9912c 12 *
mbed_official 66:ce8709d9912c 13 * Unless required by applicable law or agreed to in writing, software
mbed_official 66:ce8709d9912c 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
mbed_official 66:ce8709d9912c 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 66:ce8709d9912c 16 * See the License for the specific language governing permissions and
mbed_official 66:ce8709d9912c 17 * limitations under the License.
mbed_official 66:ce8709d9912c 18 *
mbed_official 66:ce8709d9912c 19 * This file is part of Mbed TLS (https://tls.mbed.org)
mbed_official 66:ce8709d9912c 20 */
mbed_official 66:ce8709d9912c 21
mbed_official 66:ce8709d9912c 22 #include "HelloHttpsClient.h"
mbed_official 66:ce8709d9912c 23
mbed_official 66:ce8709d9912c 24 #include "easy-connect.h"
mbed_official 66:ce8709d9912c 25
mbed_official 66:ce8709d9912c 26 #include "mbedtls/platform.h"
mbed_official 66:ce8709d9912c 27 #include "mbedtls/config.h"
mbed_official 66:ce8709d9912c 28 #include "mbedtls/ssl.h"
mbed_official 66:ce8709d9912c 29 #include "mbedtls/entropy.h"
mbed_official 66:ce8709d9912c 30 #include "mbedtls/ctr_drbg.h"
mbed_official 66:ce8709d9912c 31 #include "mbedtls/error.h"
mbed_official 66:ce8709d9912c 32 #include "mbedtls/debug.h"
mbed_official 66:ce8709d9912c 33
mbed_official 66:ce8709d9912c 34 #include <stdint.h>
mbed_official 66:ce8709d9912c 35 #include <string.h>
mbed_official 66:ce8709d9912c 36
mbed_official 66:ce8709d9912c 37 const char *HelloHttpsClient::DRBG_PERSONALIZED_STR =
mbed_official 66:ce8709d9912c 38 "Mbed TLS helloword client";
mbed_official 66:ce8709d9912c 39
mbed_official 66:ce8709d9912c 40 const size_t HelloHttpsClient::ERROR_LOG_BUFFER_LENGTH = 128;
mbed_official 66:ce8709d9912c 41
mbed_official 66:ce8709d9912c 42 const char *HelloHttpsClient::TLS_PEM_CA =
mbed_official 66:ce8709d9912c 43 "-----BEGIN CERTIFICATE-----\n"
mbed_official 66:ce8709d9912c 44 "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n"
mbed_official 66:ce8709d9912c 45 "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n"
mbed_official 66:ce8709d9912c 46 "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n"
mbed_official 66:ce8709d9912c 47 "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n"
mbed_official 66:ce8709d9912c 48 "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n"
mbed_official 66:ce8709d9912c 49 "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n"
mbed_official 66:ce8709d9912c 50 "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n"
mbed_official 66:ce8709d9912c 51 "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n"
mbed_official 66:ce8709d9912c 52 "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n"
mbed_official 66:ce8709d9912c 53 "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n"
mbed_official 66:ce8709d9912c 54 "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n"
mbed_official 66:ce8709d9912c 55 "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n"
mbed_official 66:ce8709d9912c 56 "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n"
mbed_official 66:ce8709d9912c 57 "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n"
mbed_official 66:ce8709d9912c 58 "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n"
mbed_official 66:ce8709d9912c 59 "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n"
mbed_official 66:ce8709d9912c 60 "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n"
mbed_official 66:ce8709d9912c 61 "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n"
mbed_official 66:ce8709d9912c 62 "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n"
mbed_official 66:ce8709d9912c 63 "-----END CERTIFICATE-----\n";
mbed_official 66:ce8709d9912c 64
mbed_official 66:ce8709d9912c 65 const char *HelloHttpsClient::HTTP_REQUEST_FILE_PATH =
mbed_official 66:ce8709d9912c 66 "/media/uploads/mbed_official/hello.txt";
mbed_official 66:ce8709d9912c 67
mbed_official 66:ce8709d9912c 68 const char *HelloHttpsClient::HTTP_HELLO_STR = "Hello world!";
mbed_official 66:ce8709d9912c 69
mbed_official 66:ce8709d9912c 70 const char *HelloHttpsClient::HTTP_OK_STR = "200 OK";
mbed_official 66:ce8709d9912c 71
mbed_official 66:ce8709d9912c 72 HelloHttpsClient::HelloHttpsClient(const char *in_server_name,
mbed_official 66:ce8709d9912c 73 const uint16_t in_server_port) :
mbed_official 66:ce8709d9912c 74 socket(),
mbed_official 66:ce8709d9912c 75 server_name(in_server_name),
mbed_official 66:ce8709d9912c 76 server_port(in_server_port)
mbed_official 66:ce8709d9912c 77 {
mbed_official 66:ce8709d9912c 78 mbedtls_entropy_init(&entropy);
mbed_official 66:ce8709d9912c 79 mbedtls_ctr_drbg_init(&ctr_drbg);
mbed_official 66:ce8709d9912c 80 mbedtls_x509_crt_init(&cacert);
mbed_official 66:ce8709d9912c 81 mbedtls_ssl_init(&ssl);
mbed_official 66:ce8709d9912c 82 mbedtls_ssl_config_init(&ssl_conf);
mbed_official 66:ce8709d9912c 83 }
mbed_official 66:ce8709d9912c 84
mbed_official 66:ce8709d9912c 85 HelloHttpsClient::~HelloHttpsClient()
mbed_official 66:ce8709d9912c 86 {
mbed_official 66:ce8709d9912c 87 mbedtls_entropy_free(&entropy);
mbed_official 66:ce8709d9912c 88 mbedtls_ctr_drbg_free(&ctr_drbg);
mbed_official 66:ce8709d9912c 89 mbedtls_x509_crt_free(&cacert);
mbed_official 66:ce8709d9912c 90 mbedtls_ssl_free(&ssl);
mbed_official 66:ce8709d9912c 91 mbedtls_ssl_config_free(&ssl_conf);
mbed_official 66:ce8709d9912c 92
mbed_official 66:ce8709d9912c 93 socket.close();
mbed_official 66:ce8709d9912c 94 }
mbed_official 66:ce8709d9912c 95
mbed_official 66:ce8709d9912c 96 int HelloHttpsClient::run()
mbed_official 66:ce8709d9912c 97 {
mbed_official 66:ce8709d9912c 98 int ret;
mbed_official 66:ce8709d9912c 99 size_t req_len, req_offset, resp_offset;
mbed_official 66:ce8709d9912c 100 uint32_t flags;
mbed_official 66:ce8709d9912c 101 bool resp_200, resp_hello;
mbed_official 66:ce8709d9912c 102
mbed_official 66:ce8709d9912c 103 /* Configure the TCPSocket */
mbed_official 66:ce8709d9912c 104 if ((ret = configureTCPSocket()) != 0)
mbed_official 66:ce8709d9912c 105 return ret;
mbed_official 66:ce8709d9912c 106
mbed_official 66:ce8709d9912c 107 /* Configure already initialized Mbed TLS structures */
mbed_official 66:ce8709d9912c 108 if ((ret = configureTlsContexts()) != 0)
mbed_official 66:ce8709d9912c 109 return ret;
mbed_official 66:ce8709d9912c 110
mbed_official 66:ce8709d9912c 111 /* Start a connection to the server */
mbed_official 66:ce8709d9912c 112 if ((ret = socket.connect(server_name, server_port)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 113 mbedtls_printf("socket.connect() returned %d\n", ret);
mbed_official 66:ce8709d9912c 114 return ret;
mbed_official 66:ce8709d9912c 115 }
mbed_official 66:ce8709d9912c 116 mbedtls_printf("Successfully connected to %s at port %u\n",
mbed_official 66:ce8709d9912c 117 server_name, server_port);
mbed_official 66:ce8709d9912c 118
mbed_official 66:ce8709d9912c 119 /* Start the TLS handshake */
mbed_official 66:ce8709d9912c 120 mbedtls_printf("Starting the TLS handshake...\n");
mbed_official 66:ce8709d9912c 121 do {
mbed_official 66:ce8709d9912c 122 ret = mbedtls_ssl_handshake(&ssl);
mbed_official 66:ce8709d9912c 123 } while(ret != 0 &&
mbed_official 66:ce8709d9912c 124 (ret == MBEDTLS_ERR_SSL_WANT_READ ||
mbed_official 66:ce8709d9912c 125 ret == MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 126 if (ret < 0) {
mbed_official 66:ce8709d9912c 127 mbedtls_printf("mbedtls_ssl_handshake() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 128 return ret;
mbed_official 66:ce8709d9912c 129 }
mbed_official 66:ce8709d9912c 130 mbedtls_printf("Successfully completed the TLS handshake\n");
mbed_official 66:ce8709d9912c 131
mbed_official 66:ce8709d9912c 132 /* Fill the request buffer */
mbed_official 66:ce8709d9912c 133 ret = snprintf(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 134 "GET %s HTTP/1.1\nHost: %s\n\n", HTTP_REQUEST_FILE_PATH,
mbed_official 66:ce8709d9912c 135 server_name);
mbed_official 66:ce8709d9912c 136 req_len = static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 137 if (ret < 0 || req_len >= sizeof(gp_buf)) {
mbed_official 66:ce8709d9912c 138 mbedtls_printf("Failed to compose HTTP request using snprintf: %d\n",
mbed_official 66:ce8709d9912c 139 ret);
mbed_official 66:ce8709d9912c 140 return ret;
mbed_official 66:ce8709d9912c 141 }
mbed_official 66:ce8709d9912c 142
mbed_official 66:ce8709d9912c 143 /* Send the HTTP request to the server over TLS */
mbed_official 66:ce8709d9912c 144 req_offset = 0;
mbed_official 66:ce8709d9912c 145 do {
mbed_official 66:ce8709d9912c 146 ret = mbedtls_ssl_write(&ssl,
mbed_official 66:ce8709d9912c 147 reinterpret_cast<const unsigned char *>(gp_buf + req_offset),
mbed_official 66:ce8709d9912c 148 req_len - req_offset);
mbed_official 66:ce8709d9912c 149 if (ret > 0)
mbed_official 66:ce8709d9912c 150 req_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 151 }
mbed_official 66:ce8709d9912c 152 while(req_offset < req_len &&
mbed_official 66:ce8709d9912c 153 (ret > 0 ||
mbed_official 66:ce8709d9912c 154 ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
mbed_official 66:ce8709d9912c 155 ret == MBEDTLS_ERR_SSL_WANT_READ));
mbed_official 66:ce8709d9912c 156 if (ret < 0) {
mbed_official 66:ce8709d9912c 157 mbedtls_printf("mbedtls_ssl_write() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 158 return ret;
mbed_official 66:ce8709d9912c 159 }
mbed_official 66:ce8709d9912c 160
mbed_official 66:ce8709d9912c 161 /* Print information about the TLS connection */
mbed_official 66:ce8709d9912c 162 ret = mbedtls_x509_crt_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 163 "\r ", mbedtls_ssl_get_peer_cert(&ssl));
mbed_official 66:ce8709d9912c 164 if (ret < 0) {
mbed_official 66:ce8709d9912c 165 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 166 return ret;
mbed_official 66:ce8709d9912c 167 }
mbed_official 66:ce8709d9912c 168 mbedtls_printf("Server certificate:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 169
mbed_official 66:ce8709d9912c 170 /* Ensure certificate verification was successful */
mbed_official 66:ce8709d9912c 171 flags = mbedtls_ssl_get_verify_result(&ssl);
mbed_official 66:ce8709d9912c 172 if (flags != 0) {
mbed_official 66:ce8709d9912c 173 ret = mbedtls_x509_crt_verify_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 174 "\r ! ", flags);
mbed_official 66:ce8709d9912c 175 if (ret < 0) {
mbed_official 66:ce8709d9912c 176 mbedtls_printf("mbedtls_x509_crt_verify_info() returned "
mbed_official 66:ce8709d9912c 177 "-0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 178 return ret;
mbed_official 66:ce8709d9912c 179 } else {
mbed_official 66:ce8709d9912c 180 mbedtls_printf("Certificate verification failed (flags %lu):"
mbed_official 66:ce8709d9912c 181 "\n%s\n", flags, gp_buf);
mbed_official 66:ce8709d9912c 182 return -1;
mbed_official 66:ce8709d9912c 183 }
mbed_official 66:ce8709d9912c 184 } else {
mbed_official 66:ce8709d9912c 185 mbedtls_printf("Certificate verification passed\n");
mbed_official 66:ce8709d9912c 186 }
mbed_official 66:ce8709d9912c 187
mbed_official 66:ce8709d9912c 188 mbedtls_printf("Established TLS connection to %s\n", server_name);
mbed_official 66:ce8709d9912c 189
mbed_official 66:ce8709d9912c 190 /* Read response from the server */
mbed_official 66:ce8709d9912c 191 resp_offset = 0;
mbed_official 66:ce8709d9912c 192 resp_200 = false;
mbed_official 66:ce8709d9912c 193 resp_hello = false;
mbed_official 66:ce8709d9912c 194 do {
mbed_official 66:ce8709d9912c 195 ret = mbedtls_ssl_read(&ssl,
mbed_official 66:ce8709d9912c 196 reinterpret_cast<unsigned char *>(gp_buf + resp_offset),
mbed_official 66:ce8709d9912c 197 sizeof(gp_buf) - resp_offset - 1);
mbed_official 66:ce8709d9912c 198 if (ret > 0)
mbed_official 66:ce8709d9912c 199 resp_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 200
mbed_official 66:ce8709d9912c 201 /* Ensure that the response string is null-terminated */
mbed_official 66:ce8709d9912c 202 gp_buf[resp_offset] = '\0';
mbed_official 66:ce8709d9912c 203
mbed_official 66:ce8709d9912c 204 /* Check if we received expected string */
mbed_official 66:ce8709d9912c 205 resp_200 = resp_200 || strstr(gp_buf, HTTP_OK_STR) != NULL;
mbed_official 66:ce8709d9912c 206 resp_hello = resp_hello || strstr(gp_buf, HTTP_HELLO_STR) != NULL;
mbed_official 66:ce8709d9912c 207 } while((!resp_200 || !resp_hello) &&
mbed_official 66:ce8709d9912c 208 (ret > 0 ||
mbed_official 66:ce8709d9912c 209 ret == MBEDTLS_ERR_SSL_WANT_READ || MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 210 if (ret < 0) {
mbed_official 66:ce8709d9912c 211 mbedtls_printf("mbedtls_ssl_read() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 212 return ret;
mbed_official 66:ce8709d9912c 213 }
mbed_official 66:ce8709d9912c 214
mbed_official 66:ce8709d9912c 215 /* Display response information */
mbed_official 66:ce8709d9912c 216 mbedtls_printf("HTTP: Received %u chars from server\n", resp_offset);
mbed_official 66:ce8709d9912c 217 mbedtls_printf("HTTP: Received '%s' status ... %s\n", HTTP_OK_STR,
mbed_official 66:ce8709d9912c 218 resp_200 ? "OK" : "FAIL");
mbed_official 66:ce8709d9912c 219 mbedtls_printf("HTTP: Received message:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 220
mbed_official 66:ce8709d9912c 221 return 0;
mbed_official 66:ce8709d9912c 222 }
mbed_official 66:ce8709d9912c 223
mbed_official 66:ce8709d9912c 224 int HelloHttpsClient::configureTCPSocket()
mbed_official 66:ce8709d9912c 225 {
mbed_official 66:ce8709d9912c 226 int ret;
mbed_official 66:ce8709d9912c 227
mbed_official 66:ce8709d9912c 228 /*
mbed_official 66:ce8709d9912c 229 * Use easy-connect lib to support multiple network bearers. See
mbed_official 66:ce8709d9912c 230 * https://github.com/ARMmbed/easy-connect README.md for more information.
mbed_official 66:ce8709d9912c 231 */
mbed_official 66:ce8709d9912c 232 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
mbed_official 66:ce8709d9912c 233 NetworkInterface *network = easy_connect(true);
mbed_official 66:ce8709d9912c 234 #else
mbed_official 66:ce8709d9912c 235 NetworkInterface *network = easy_connect(false);
mbed_official 66:ce8709d9912c 236 #endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
mbed_official 66:ce8709d9912c 237 if(network == NULL) {
mbed_official 66:ce8709d9912c 238 mbedtls_printf("easy_connect() returned NULL\n"
mbed_official 66:ce8709d9912c 239 "Failed to connect to the network\n");
mbed_official 66:ce8709d9912c 240 return -1;
mbed_official 66:ce8709d9912c 241 }
mbed_official 66:ce8709d9912c 242
mbed_official 66:ce8709d9912c 243 if ((ret = socket.open(network)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 244 mbedtls_printf("socket.open() returned %d\n", ret);
mbed_official 66:ce8709d9912c 245 return ret;
mbed_official 66:ce8709d9912c 246 }
mbed_official 66:ce8709d9912c 247
mbed_official 66:ce8709d9912c 248 socket.set_blocking(false);
mbed_official 66:ce8709d9912c 249
mbed_official 66:ce8709d9912c 250 return 0;
mbed_official 66:ce8709d9912c 251 }
mbed_official 66:ce8709d9912c 252
mbed_official 66:ce8709d9912c 253 int HelloHttpsClient::configureTlsContexts()
mbed_official 66:ce8709d9912c 254 {
mbed_official 66:ce8709d9912c 255 int ret;
mbed_official 66:ce8709d9912c 256
mbed_official 66:ce8709d9912c 257 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
mbed_official 66:ce8709d9912c 258 reinterpret_cast<const unsigned char *>(DRBG_PERSONALIZED_STR),
mbed_official 66:ce8709d9912c 259 strlen(DRBG_PERSONALIZED_STR) + 1);
mbed_official 66:ce8709d9912c 260 if (ret != 0) {
mbed_official 66:ce8709d9912c 261 mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 262 return ret;
mbed_official 66:ce8709d9912c 263 }
mbed_official 66:ce8709d9912c 264
mbed_official 66:ce8709d9912c 265 ret = mbedtls_x509_crt_parse(&cacert,
mbed_official 66:ce8709d9912c 266 reinterpret_cast<const unsigned char *>(TLS_PEM_CA),
mbed_official 66:ce8709d9912c 267 strlen(TLS_PEM_CA) + 1);
mbed_official 66:ce8709d9912c 268 if (ret != 0) {
mbed_official 66:ce8709d9912c 269 mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 270 return ret;
mbed_official 66:ce8709d9912c 271 }
mbed_official 66:ce8709d9912c 272
mbed_official 66:ce8709d9912c 273 ret = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
mbed_official 66:ce8709d9912c 274 MBEDTLS_SSL_TRANSPORT_STREAM,
mbed_official 66:ce8709d9912c 275 MBEDTLS_SSL_PRESET_DEFAULT);
mbed_official 66:ce8709d9912c 276 if (ret != 0) {
mbed_official 66:ce8709d9912c 277 mbedtls_printf("mbedtls_ssl_config_defaults() returned -0x%04X\n",
mbed_official 66:ce8709d9912c 278 -ret);
mbed_official 66:ce8709d9912c 279 return ret;
mbed_official 66:ce8709d9912c 280 }
mbed_official 66:ce8709d9912c 281
mbed_official 66:ce8709d9912c 282 mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacert, NULL);
mbed_official 66:ce8709d9912c 283 mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbed_official 66:ce8709d9912c 284
mbed_official 66:ce8709d9912c 285 /*
mbed_official 66:ce8709d9912c 286 * It is possible to disable authentication by passing
mbed_official 66:ce8709d9912c 287 * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
mbed_official 66:ce8709d9912c 288 */
mbed_official 66:ce8709d9912c 289 mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbed_official 66:ce8709d9912c 290
mbed_official 66:ce8709d9912c 291 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
mbed_official 66:ce8709d9912c 292 mbedtls_ssl_conf_verify(&ssl_conf, sslVerify, this);
mbed_official 66:ce8709d9912c 293 mbedtls_ssl_conf_dbg(&ssl_conf, sslDebug, NULL);
mbed_official 66:ce8709d9912c 294 mbedtls_debug_set_threshold(HELLO_HTTPS_CLIENT_DEBUG_LEVEL);
mbed_official 66:ce8709d9912c 295 #endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
mbed_official 66:ce8709d9912c 296
mbed_official 66:ce8709d9912c 297 if ((ret = mbedtls_ssl_setup( &ssl, &ssl_conf)) != 0) {
mbed_official 66:ce8709d9912c 298 mbedtls_printf("mbedtls_ssl_setup() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 299 return ret;
mbed_official 66:ce8709d9912c 300 }
mbed_official 66:ce8709d9912c 301
mbed_official 66:ce8709d9912c 302 if ((ret = mbedtls_ssl_set_hostname( &ssl, server_name )) != 0) {
mbed_official 66:ce8709d9912c 303 mbedtls_printf("mbedtls_ssl_set_hostname() returned -0x%04X\n",
mbed_official 66:ce8709d9912c 304 -ret);
mbed_official 66:ce8709d9912c 305 return ret;
mbed_official 66:ce8709d9912c 306 }
mbed_official 66:ce8709d9912c 307
mbed_official 66:ce8709d9912c 308 mbedtls_ssl_set_bio(&ssl, static_cast<void *>(&socket), sslSend, sslRecv,
mbed_official 66:ce8709d9912c 309 NULL);
mbed_official 66:ce8709d9912c 310
mbed_official 66:ce8709d9912c 311 return 0;
mbed_official 66:ce8709d9912c 312 }
mbed_official 66:ce8709d9912c 313
mbed_official 66:ce8709d9912c 314 int HelloHttpsClient::sslRecv(void *ctx, unsigned char *buf, size_t len)
mbed_official 66:ce8709d9912c 315 {
mbed_official 66:ce8709d9912c 316 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
mbed_official 66:ce8709d9912c 317 int ret = socket->recv(buf, len);
mbed_official 66:ce8709d9912c 318
mbed_official 66:ce8709d9912c 319 if (ret == NSAPI_ERROR_WOULD_BLOCK)
mbed_official 66:ce8709d9912c 320 ret = MBEDTLS_ERR_SSL_WANT_READ;
mbed_official 66:ce8709d9912c 321 else if (ret < 0)
mbed_official 66:ce8709d9912c 322 mbedtls_printf("socket.recv() returned %d\n", ret);
mbed_official 66:ce8709d9912c 323
mbed_official 66:ce8709d9912c 324 return ret;
mbed_official 66:ce8709d9912c 325 }
mbed_official 66:ce8709d9912c 326
mbed_official 66:ce8709d9912c 327 int HelloHttpsClient::sslSend(void *ctx, const unsigned char *buf, size_t len)
mbed_official 66:ce8709d9912c 328 {
mbed_official 66:ce8709d9912c 329 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
mbed_official 66:ce8709d9912c 330 int ret = socket->send(buf, len);
mbed_official 66:ce8709d9912c 331
mbed_official 66:ce8709d9912c 332 if (ret == NSAPI_ERROR_WOULD_BLOCK)
mbed_official 66:ce8709d9912c 333 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
mbed_official 66:ce8709d9912c 334 else if (ret < 0)
mbed_official 66:ce8709d9912c 335 mbedtls_printf("socket.send() returned %d\n", ret);
mbed_official 66:ce8709d9912c 336
mbed_official 66:ce8709d9912c 337 return ret;
mbed_official 66:ce8709d9912c 338 }
mbed_official 66:ce8709d9912c 339
mbed_official 66:ce8709d9912c 340 void HelloHttpsClient::sslDebug(void *ctx, int level, const char *file,
mbed_official 66:ce8709d9912c 341 int line, const char *str)
mbed_official 66:ce8709d9912c 342 {
mbed_official 66:ce8709d9912c 343 (void)ctx;
mbed_official 66:ce8709d9912c 344
mbed_official 66:ce8709d9912c 345 const char *p, *basename;
mbed_official 66:ce8709d9912c 346
mbed_official 66:ce8709d9912c 347 /* Extract basename from file */
mbed_official 66:ce8709d9912c 348 for (p = basename = file; *p != '\0'; p++) {
mbed_official 66:ce8709d9912c 349 if (*p == '/' || *p == '\\')
mbed_official 66:ce8709d9912c 350 basename = p + 1;
mbed_official 66:ce8709d9912c 351 }
mbed_official 66:ce8709d9912c 352
mbed_official 66:ce8709d9912c 353 mbedtls_printf("%s:%d: |%d| %s\r", basename, line, level, str);
mbed_official 66:ce8709d9912c 354 }
mbed_official 66:ce8709d9912c 355
mbed_official 66:ce8709d9912c 356 int HelloHttpsClient::sslVerify(void *ctx, mbedtls_x509_crt *crt, int depth,
mbed_official 66:ce8709d9912c 357 uint32_t *flags)
mbed_official 66:ce8709d9912c 358 {
mbed_official 66:ce8709d9912c 359 HelloHttpsClient *client = static_cast<HelloHttpsClient *>(ctx);
mbed_official 66:ce8709d9912c 360
mbed_official 66:ce8709d9912c 361 int ret = -1;
mbed_official 66:ce8709d9912c 362
mbed_official 66:ce8709d9912c 363 ret = mbedtls_x509_crt_info(client->gp_buf, sizeof(gp_buf), "\r ", crt);
mbed_official 66:ce8709d9912c 364 if (ret < 0) {
mbed_official 66:ce8709d9912c 365 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 366 } else {
mbed_official 66:ce8709d9912c 367 ret = 0;
mbed_official 66:ce8709d9912c 368 mbedtls_printf("Verifying certificate at depth %d:\n%s\n",
mbed_official 66:ce8709d9912c 369 depth, client->gp_buf);
mbed_official 66:ce8709d9912c 370 }
mbed_official 66:ce8709d9912c 371
mbed_official 66:ce8709d9912c 372 return ret;
mbed_official 66:ce8709d9912c 373 }
mbed_official 66:ce8709d9912c 374