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:
Wed Oct 31 16:00:17 2018 +0000
Revision:
86:e1ceb1075f1a
Parent:
83:6dbd4cae4527
Child:
88:9a774920414b
Merge pull request #199 from RonEld/set_NULL_as_platform_context

Change mbedtls_platform_context parameter to NULL
.
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 "mbedtls/platform.h"
mbed_official 66:ce8709d9912c 25 #include "mbedtls/config.h"
mbed_official 66:ce8709d9912c 26 #include "mbedtls/ssl.h"
mbed_official 66:ce8709d9912c 27 #include "mbedtls/entropy.h"
mbed_official 66:ce8709d9912c 28 #include "mbedtls/ctr_drbg.h"
mbed_official 66:ce8709d9912c 29 #include "mbedtls/error.h"
mbed_official 66:ce8709d9912c 30 #include "mbedtls/debug.h"
mbed_official 83:6dbd4cae4527 31 #include "mbedtls/x509.h"
mbed_official 66:ce8709d9912c 32
mbed_official 66:ce8709d9912c 33 #include <stdint.h>
mbed_official 66:ce8709d9912c 34 #include <string.h>
mbed_official 81:1b9acc423bfc 35 #include "mbed.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 76:b8c07be20122 73 const char *in_server_addr,
mbed_official 86:e1ceb1075f1a 74 const uint16_t in_server_port) :
mbed_official 66:ce8709d9912c 75 socket(),
mbed_official 66:ce8709d9912c 76 server_name(in_server_name),
mbed_official 76:b8c07be20122 77 server_addr(in_server_addr),
mbed_official 86:e1ceb1075f1a 78 server_port(in_server_port)
mbed_official 66:ce8709d9912c 79 {
mbed_official 66:ce8709d9912c 80 mbedtls_entropy_init(&entropy);
mbed_official 66:ce8709d9912c 81 mbedtls_ctr_drbg_init(&ctr_drbg);
mbed_official 66:ce8709d9912c 82 mbedtls_x509_crt_init(&cacert);
mbed_official 66:ce8709d9912c 83 mbedtls_ssl_init(&ssl);
mbed_official 66:ce8709d9912c 84 mbedtls_ssl_config_init(&ssl_conf);
mbed_official 66:ce8709d9912c 85 }
mbed_official 66:ce8709d9912c 86
mbed_official 66:ce8709d9912c 87 HelloHttpsClient::~HelloHttpsClient()
mbed_official 66:ce8709d9912c 88 {
mbed_official 66:ce8709d9912c 89 mbedtls_entropy_free(&entropy);
mbed_official 66:ce8709d9912c 90 mbedtls_ctr_drbg_free(&ctr_drbg);
mbed_official 66:ce8709d9912c 91 mbedtls_x509_crt_free(&cacert);
mbed_official 66:ce8709d9912c 92 mbedtls_ssl_free(&ssl);
mbed_official 66:ce8709d9912c 93 mbedtls_ssl_config_free(&ssl_conf);
mbed_official 66:ce8709d9912c 94
mbed_official 66:ce8709d9912c 95 socket.close();
mbed_official 66:ce8709d9912c 96 }
mbed_official 66:ce8709d9912c 97
mbed_official 66:ce8709d9912c 98 int HelloHttpsClient::run()
mbed_official 66:ce8709d9912c 99 {
mbed_official 66:ce8709d9912c 100 int ret;
mbed_official 66:ce8709d9912c 101 size_t req_len, req_offset, resp_offset;
mbed_official 66:ce8709d9912c 102 uint32_t flags;
mbed_official 66:ce8709d9912c 103 bool resp_200, resp_hello;
mbed_official 66:ce8709d9912c 104
mbed_official 66:ce8709d9912c 105 /* Configure the TCPSocket */
mbed_official 66:ce8709d9912c 106 if ((ret = configureTCPSocket()) != 0)
mbed_official 66:ce8709d9912c 107 return ret;
mbed_official 66:ce8709d9912c 108
mbed_official 66:ce8709d9912c 109 /* Configure already initialized Mbed TLS structures */
mbed_official 66:ce8709d9912c 110 if ((ret = configureTlsContexts()) != 0)
mbed_official 66:ce8709d9912c 111 return ret;
mbed_official 66:ce8709d9912c 112
mbed_official 66:ce8709d9912c 113 /* Start a connection to the server */
mbed_official 76:b8c07be20122 114 if ((ret = socket.connect(server_addr, server_port)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 115 mbedtls_printf("socket.connect() returned %d\n", ret);
mbed_official 66:ce8709d9912c 116 return ret;
mbed_official 66:ce8709d9912c 117 }
mbed_official 66:ce8709d9912c 118 mbedtls_printf("Successfully connected to %s at port %u\n",
mbed_official 76:b8c07be20122 119 server_addr, server_port);
mbed_official 66:ce8709d9912c 120
mbed_official 66:ce8709d9912c 121 /* Start the TLS handshake */
mbed_official 66:ce8709d9912c 122 mbedtls_printf("Starting the TLS handshake...\n");
mbed_official 66:ce8709d9912c 123 do {
mbed_official 66:ce8709d9912c 124 ret = mbedtls_ssl_handshake(&ssl);
mbed_official 66:ce8709d9912c 125 } while(ret != 0 &&
mbed_official 66:ce8709d9912c 126 (ret == MBEDTLS_ERR_SSL_WANT_READ ||
mbed_official 66:ce8709d9912c 127 ret == MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 128 if (ret < 0) {
mbed_official 66:ce8709d9912c 129 mbedtls_printf("mbedtls_ssl_handshake() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 130 return ret;
mbed_official 66:ce8709d9912c 131 }
mbed_official 66:ce8709d9912c 132 mbedtls_printf("Successfully completed the TLS handshake\n");
mbed_official 66:ce8709d9912c 133
mbed_official 66:ce8709d9912c 134 /* Fill the request buffer */
mbed_official 66:ce8709d9912c 135 ret = snprintf(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 136 "GET %s HTTP/1.1\nHost: %s\n\n", HTTP_REQUEST_FILE_PATH,
mbed_official 66:ce8709d9912c 137 server_name);
mbed_official 66:ce8709d9912c 138 req_len = static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 139 if (ret < 0 || req_len >= sizeof(gp_buf)) {
mbed_official 66:ce8709d9912c 140 mbedtls_printf("Failed to compose HTTP request using snprintf: %d\n",
mbed_official 66:ce8709d9912c 141 ret);
mbed_official 66:ce8709d9912c 142 return ret;
mbed_official 66:ce8709d9912c 143 }
mbed_official 66:ce8709d9912c 144
mbed_official 66:ce8709d9912c 145 /* Send the HTTP request to the server over TLS */
mbed_official 66:ce8709d9912c 146 req_offset = 0;
mbed_official 66:ce8709d9912c 147 do {
mbed_official 66:ce8709d9912c 148 ret = mbedtls_ssl_write(&ssl,
mbed_official 66:ce8709d9912c 149 reinterpret_cast<const unsigned char *>(gp_buf + req_offset),
mbed_official 66:ce8709d9912c 150 req_len - req_offset);
mbed_official 66:ce8709d9912c 151 if (ret > 0)
mbed_official 66:ce8709d9912c 152 req_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 153 }
mbed_official 66:ce8709d9912c 154 while(req_offset < req_len &&
mbed_official 66:ce8709d9912c 155 (ret > 0 ||
mbed_official 66:ce8709d9912c 156 ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
mbed_official 66:ce8709d9912c 157 ret == MBEDTLS_ERR_SSL_WANT_READ));
mbed_official 66:ce8709d9912c 158 if (ret < 0) {
mbed_official 66:ce8709d9912c 159 mbedtls_printf("mbedtls_ssl_write() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 160 return ret;
mbed_official 66:ce8709d9912c 161 }
mbed_official 66:ce8709d9912c 162
mbed_official 66:ce8709d9912c 163 /* Print information about the TLS connection */
mbed_official 66:ce8709d9912c 164 ret = mbedtls_x509_crt_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 165 "\r ", mbedtls_ssl_get_peer_cert(&ssl));
mbed_official 66:ce8709d9912c 166 if (ret < 0) {
mbed_official 66:ce8709d9912c 167 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 168 return ret;
mbed_official 66:ce8709d9912c 169 }
mbed_official 66:ce8709d9912c 170 mbedtls_printf("Server certificate:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 171
mbed_official 66:ce8709d9912c 172 /* Ensure certificate verification was successful */
mbed_official 66:ce8709d9912c 173 flags = mbedtls_ssl_get_verify_result(&ssl);
mbed_official 66:ce8709d9912c 174 if (flags != 0) {
mbed_official 66:ce8709d9912c 175 ret = mbedtls_x509_crt_verify_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 176 "\r ! ", flags);
mbed_official 66:ce8709d9912c 177 if (ret < 0) {
mbed_official 66:ce8709d9912c 178 mbedtls_printf("mbedtls_x509_crt_verify_info() returned "
mbed_official 66:ce8709d9912c 179 "-0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 180 return ret;
mbed_official 66:ce8709d9912c 181 } else {
mbed_official 66:ce8709d9912c 182 mbedtls_printf("Certificate verification failed (flags %lu):"
mbed_official 66:ce8709d9912c 183 "\n%s\n", flags, gp_buf);
mbed_official 66:ce8709d9912c 184 return -1;
mbed_official 66:ce8709d9912c 185 }
mbed_official 66:ce8709d9912c 186 } else {
mbed_official 66:ce8709d9912c 187 mbedtls_printf("Certificate verification passed\n");
mbed_official 66:ce8709d9912c 188 }
mbed_official 66:ce8709d9912c 189
mbed_official 66:ce8709d9912c 190 mbedtls_printf("Established TLS connection to %s\n", server_name);
mbed_official 66:ce8709d9912c 191
mbed_official 66:ce8709d9912c 192 /* Read response from the server */
mbed_official 66:ce8709d9912c 193 resp_offset = 0;
mbed_official 66:ce8709d9912c 194 resp_200 = false;
mbed_official 66:ce8709d9912c 195 resp_hello = false;
mbed_official 66:ce8709d9912c 196 do {
mbed_official 66:ce8709d9912c 197 ret = mbedtls_ssl_read(&ssl,
mbed_official 66:ce8709d9912c 198 reinterpret_cast<unsigned char *>(gp_buf + resp_offset),
mbed_official 66:ce8709d9912c 199 sizeof(gp_buf) - resp_offset - 1);
mbed_official 66:ce8709d9912c 200 if (ret > 0)
mbed_official 66:ce8709d9912c 201 resp_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 202
mbed_official 66:ce8709d9912c 203 /* Ensure that the response string is null-terminated */
mbed_official 66:ce8709d9912c 204 gp_buf[resp_offset] = '\0';
mbed_official 66:ce8709d9912c 205
mbed_official 66:ce8709d9912c 206 /* Check if we received expected string */
mbed_official 66:ce8709d9912c 207 resp_200 = resp_200 || strstr(gp_buf, HTTP_OK_STR) != NULL;
mbed_official 66:ce8709d9912c 208 resp_hello = resp_hello || strstr(gp_buf, HTTP_HELLO_STR) != NULL;
mbed_official 66:ce8709d9912c 209 } while((!resp_200 || !resp_hello) &&
mbed_official 66:ce8709d9912c 210 (ret > 0 ||
mbed_official 66:ce8709d9912c 211 ret == MBEDTLS_ERR_SSL_WANT_READ || MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 212 if (ret < 0) {
mbed_official 66:ce8709d9912c 213 mbedtls_printf("mbedtls_ssl_read() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 214 return ret;
mbed_official 66:ce8709d9912c 215 }
mbed_official 66:ce8709d9912c 216
mbed_official 66:ce8709d9912c 217 /* Display response information */
mbed_official 66:ce8709d9912c 218 mbedtls_printf("HTTP: Received %u chars from server\n", resp_offset);
mbed_official 66:ce8709d9912c 219 mbedtls_printf("HTTP: Received '%s' status ... %s\n", HTTP_OK_STR,
mbed_official 66:ce8709d9912c 220 resp_200 ? "OK" : "FAIL");
mbed_official 66:ce8709d9912c 221 mbedtls_printf("HTTP: Received message:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 222
mbed_official 66:ce8709d9912c 223 return 0;
mbed_official 66:ce8709d9912c 224 }
mbed_official 66:ce8709d9912c 225
mbed_official 66:ce8709d9912c 226 int HelloHttpsClient::configureTCPSocket()
mbed_official 66:ce8709d9912c 227 {
mbed_official 66:ce8709d9912c 228 int ret;
mbed_official 66:ce8709d9912c 229
mbed_official 81:1b9acc423bfc 230 NetworkInterface *network = NetworkInterface::get_default_instance();
mbed_official 66:ce8709d9912c 231 if(network == NULL) {
mbed_official 81:1b9acc423bfc 232 mbedtls_printf("ERROR: No network interface found!\n");
mbed_official 66:ce8709d9912c 233 return -1;
mbed_official 66:ce8709d9912c 234 }
mbed_official 81:1b9acc423bfc 235 ret = network->connect();
mbed_official 81:1b9acc423bfc 236 if (ret != 0) {
mbed_official 81:1b9acc423bfc 237 mbedtls_printf("Error! network->connect() returned: %d\n", ret);
mbed_official 81:1b9acc423bfc 238 return ret;
mbed_official 81:1b9acc423bfc 239 }
mbed_official 66:ce8709d9912c 240
mbed_official 66:ce8709d9912c 241 if ((ret = socket.open(network)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 242 mbedtls_printf("socket.open() returned %d\n", ret);
mbed_official 66:ce8709d9912c 243 return ret;
mbed_official 66:ce8709d9912c 244 }
mbed_official 66:ce8709d9912c 245
mbed_official 66:ce8709d9912c 246 socket.set_blocking(false);
mbed_official 66:ce8709d9912c 247
mbed_official 66:ce8709d9912c 248 return 0;
mbed_official 66:ce8709d9912c 249 }
mbed_official 66:ce8709d9912c 250
mbed_official 66:ce8709d9912c 251 int HelloHttpsClient::configureTlsContexts()
mbed_official 66:ce8709d9912c 252 {
mbed_official 66:ce8709d9912c 253 int ret;
mbed_official 66:ce8709d9912c 254
mbed_official 66:ce8709d9912c 255 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
mbed_official 66:ce8709d9912c 256 reinterpret_cast<const unsigned char *>(DRBG_PERSONALIZED_STR),
mbed_official 66:ce8709d9912c 257 strlen(DRBG_PERSONALIZED_STR) + 1);
mbed_official 66:ce8709d9912c 258 if (ret != 0) {
mbed_official 66:ce8709d9912c 259 mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 260 return ret;
mbed_official 66:ce8709d9912c 261 }
mbed_official 66:ce8709d9912c 262
mbed_official 66:ce8709d9912c 263 ret = mbedtls_x509_crt_parse(&cacert,
mbed_official 66:ce8709d9912c 264 reinterpret_cast<const unsigned char *>(TLS_PEM_CA),
mbed_official 66:ce8709d9912c 265 strlen(TLS_PEM_CA) + 1);
mbed_official 66:ce8709d9912c 266 if (ret != 0) {
mbed_official 66:ce8709d9912c 267 mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 268 return ret;
mbed_official 66:ce8709d9912c 269 }
mbed_official 66:ce8709d9912c 270
mbed_official 66:ce8709d9912c 271 ret = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
mbed_official 66:ce8709d9912c 272 MBEDTLS_SSL_TRANSPORT_STREAM,
mbed_official 66:ce8709d9912c 273 MBEDTLS_SSL_PRESET_DEFAULT);
mbed_official 66:ce8709d9912c 274 if (ret != 0) {
mbed_official 66:ce8709d9912c 275 mbedtls_printf("mbedtls_ssl_config_defaults() returned -0x%04X\n",
mbed_official 66:ce8709d9912c 276 -ret);
mbed_official 66:ce8709d9912c 277 return ret;
mbed_official 66:ce8709d9912c 278 }
mbed_official 66:ce8709d9912c 279
mbed_official 66:ce8709d9912c 280 mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacert, NULL);
mbed_official 66:ce8709d9912c 281 mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbed_official 66:ce8709d9912c 282
mbed_official 66:ce8709d9912c 283 /*
mbed_official 66:ce8709d9912c 284 * It is possible to disable authentication by passing
mbed_official 66:ce8709d9912c 285 * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
mbed_official 66:ce8709d9912c 286 */
mbed_official 66:ce8709d9912c 287 mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbed_official 66:ce8709d9912c 288
mbed_official 83:6dbd4cae4527 289 /* Configure certificate verification function to clear time/date flags */
mbed_official 83:6dbd4cae4527 290 mbedtls_ssl_conf_verify(&ssl_conf, sslVerify, this);
mbed_official 83:6dbd4cae4527 291
mbed_official 66:ce8709d9912c 292 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
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 83:6dbd4cae4527 359 int ret = 0;
mbed_official 66:ce8709d9912c 360
mbed_official 83:6dbd4cae4527 361 /*
mbed_official 83:6dbd4cae4527 362 * If MBEDTLS_HAVE_TIME_DATE is defined, then the certificate date and time
mbed_official 83:6dbd4cae4527 363 * validity checks will probably fail because this application does not set
mbed_official 83:6dbd4cae4527 364 * up the clock correctly. We filter out date and time related failures
mbed_official 83:6dbd4cae4527 365 * instead
mbed_official 83:6dbd4cae4527 366 */
mbed_official 83:6dbd4cae4527 367 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE & ~MBEDTLS_X509_BADCERT_EXPIRED;
mbed_official 83:6dbd4cae4527 368
mbed_official 83:6dbd4cae4527 369 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
mbed_official 83:6dbd4cae4527 370 HelloHttpsClient *client = static_cast<HelloHttpsClient *>(ctx);
mbed_official 66:ce8709d9912c 371
mbed_official 66:ce8709d9912c 372 ret = mbedtls_x509_crt_info(client->gp_buf, sizeof(gp_buf), "\r ", crt);
mbed_official 66:ce8709d9912c 373 if (ret < 0) {
mbed_official 66:ce8709d9912c 374 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 375 } else {
mbed_official 66:ce8709d9912c 376 ret = 0;
mbed_official 66:ce8709d9912c 377 mbedtls_printf("Verifying certificate at depth %d:\n%s\n",
mbed_official 66:ce8709d9912c 378 depth, client->gp_buf);
mbed_official 66:ce8709d9912c 379 }
mbed_official 83:6dbd4cae4527 380 #endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
mbed_official 66:ce8709d9912c 381
mbed_official 66:ce8709d9912c 382 return ret;
mbed_official 66:ce8709d9912c 383 }
mbed_official 66:ce8709d9912c 384