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 Nov 21 09:45:17 2018 +0000
Revision:
89:75bc6e025eaa
Parent:
88:9a774920414b
Merge pull request #215 from cmonr/master

Updating mbed-os to mbed-os-5.10.4
The failing tests are tracked as known issues
.
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 88:9a774920414b 44 "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n"
mbed_official 88:9a774920414b 45 "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n"
mbed_official 88:9a774920414b 46 "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n"
mbed_official 88:9a774920414b 47 "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n"
mbed_official 88:9a774920414b 48 "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n"
mbed_official 88:9a774920414b 49 "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n"
mbed_official 88:9a774920414b 50 "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n"
mbed_official 88:9a774920414b 51 "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n"
mbed_official 88:9a774920414b 52 "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n"
mbed_official 88:9a774920414b 53 "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n"
mbed_official 88:9a774920414b 54 "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
mbed_official 88:9a774920414b 55 "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n"
mbed_official 88:9a774920414b 56 "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n"
mbed_official 88:9a774920414b 57 "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n"
mbed_official 88:9a774920414b 58 "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n"
mbed_official 88:9a774920414b 59 "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n"
mbed_official 88:9a774920414b 60 "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n"
mbed_official 88:9a774920414b 61 "rqXRfboQnoZsG4q5WTP468SQvvG5\n"
mbed_official 66:ce8709d9912c 62 "-----END CERTIFICATE-----\n";
mbed_official 66:ce8709d9912c 63
mbed_official 66:ce8709d9912c 64 const char *HelloHttpsClient::HTTP_REQUEST_FILE_PATH =
mbed_official 66:ce8709d9912c 65 "/media/uploads/mbed_official/hello.txt";
mbed_official 66:ce8709d9912c 66
mbed_official 66:ce8709d9912c 67 const char *HelloHttpsClient::HTTP_HELLO_STR = "Hello world!";
mbed_official 66:ce8709d9912c 68
mbed_official 66:ce8709d9912c 69 const char *HelloHttpsClient::HTTP_OK_STR = "200 OK";
mbed_official 66:ce8709d9912c 70
mbed_official 66:ce8709d9912c 71 HelloHttpsClient::HelloHttpsClient(const char *in_server_name,
mbed_official 76:b8c07be20122 72 const char *in_server_addr,
mbed_official 86:e1ceb1075f1a 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 76:b8c07be20122 76 server_addr(in_server_addr),
mbed_official 86:e1ceb1075f1a 77 server_port(in_server_port)
mbed_official 66:ce8709d9912c 78 {
mbed_official 66:ce8709d9912c 79 mbedtls_entropy_init(&entropy);
mbed_official 66:ce8709d9912c 80 mbedtls_ctr_drbg_init(&ctr_drbg);
mbed_official 66:ce8709d9912c 81 mbedtls_x509_crt_init(&cacert);
mbed_official 66:ce8709d9912c 82 mbedtls_ssl_init(&ssl);
mbed_official 66:ce8709d9912c 83 mbedtls_ssl_config_init(&ssl_conf);
mbed_official 66:ce8709d9912c 84 }
mbed_official 66:ce8709d9912c 85
mbed_official 66:ce8709d9912c 86 HelloHttpsClient::~HelloHttpsClient()
mbed_official 66:ce8709d9912c 87 {
mbed_official 66:ce8709d9912c 88 mbedtls_entropy_free(&entropy);
mbed_official 66:ce8709d9912c 89 mbedtls_ctr_drbg_free(&ctr_drbg);
mbed_official 66:ce8709d9912c 90 mbedtls_x509_crt_free(&cacert);
mbed_official 66:ce8709d9912c 91 mbedtls_ssl_free(&ssl);
mbed_official 66:ce8709d9912c 92 mbedtls_ssl_config_free(&ssl_conf);
mbed_official 66:ce8709d9912c 93
mbed_official 66:ce8709d9912c 94 socket.close();
mbed_official 66:ce8709d9912c 95 }
mbed_official 66:ce8709d9912c 96
mbed_official 66:ce8709d9912c 97 int HelloHttpsClient::run()
mbed_official 66:ce8709d9912c 98 {
mbed_official 66:ce8709d9912c 99 int ret;
mbed_official 66:ce8709d9912c 100 size_t req_len, req_offset, resp_offset;
mbed_official 66:ce8709d9912c 101 uint32_t flags;
mbed_official 66:ce8709d9912c 102 bool resp_200, resp_hello;
mbed_official 66:ce8709d9912c 103
mbed_official 66:ce8709d9912c 104 /* Configure the TCPSocket */
mbed_official 66:ce8709d9912c 105 if ((ret = configureTCPSocket()) != 0)
mbed_official 66:ce8709d9912c 106 return ret;
mbed_official 66:ce8709d9912c 107
mbed_official 66:ce8709d9912c 108 /* Configure already initialized Mbed TLS structures */
mbed_official 66:ce8709d9912c 109 if ((ret = configureTlsContexts()) != 0)
mbed_official 66:ce8709d9912c 110 return ret;
mbed_official 66:ce8709d9912c 111
mbed_official 66:ce8709d9912c 112 /* Start a connection to the server */
mbed_official 76:b8c07be20122 113 if ((ret = socket.connect(server_addr, server_port)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 114 mbedtls_printf("socket.connect() returned %d\n", ret);
mbed_official 66:ce8709d9912c 115 return ret;
mbed_official 66:ce8709d9912c 116 }
mbed_official 66:ce8709d9912c 117 mbedtls_printf("Successfully connected to %s at port %u\n",
mbed_official 76:b8c07be20122 118 server_addr, server_port);
mbed_official 66:ce8709d9912c 119
mbed_official 66:ce8709d9912c 120 /* Start the TLS handshake */
mbed_official 66:ce8709d9912c 121 mbedtls_printf("Starting the TLS handshake...\n");
mbed_official 66:ce8709d9912c 122 do {
mbed_official 66:ce8709d9912c 123 ret = mbedtls_ssl_handshake(&ssl);
mbed_official 66:ce8709d9912c 124 } while(ret != 0 &&
mbed_official 66:ce8709d9912c 125 (ret == MBEDTLS_ERR_SSL_WANT_READ ||
mbed_official 66:ce8709d9912c 126 ret == MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 127 if (ret < 0) {
mbed_official 66:ce8709d9912c 128 mbedtls_printf("mbedtls_ssl_handshake() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 129 return ret;
mbed_official 66:ce8709d9912c 130 }
mbed_official 66:ce8709d9912c 131 mbedtls_printf("Successfully completed the TLS handshake\n");
mbed_official 66:ce8709d9912c 132
mbed_official 66:ce8709d9912c 133 /* Fill the request buffer */
mbed_official 66:ce8709d9912c 134 ret = snprintf(gp_buf, sizeof(gp_buf),
mbed_official 88:9a774920414b 135 "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", HTTP_REQUEST_FILE_PATH,
mbed_official 66:ce8709d9912c 136 server_name);
mbed_official 66:ce8709d9912c 137 req_len = static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 138 if (ret < 0 || req_len >= sizeof(gp_buf)) {
mbed_official 66:ce8709d9912c 139 mbedtls_printf("Failed to compose HTTP request using snprintf: %d\n",
mbed_official 66:ce8709d9912c 140 ret);
mbed_official 66:ce8709d9912c 141 return ret;
mbed_official 66:ce8709d9912c 142 }
mbed_official 66:ce8709d9912c 143
mbed_official 66:ce8709d9912c 144 /* Send the HTTP request to the server over TLS */
mbed_official 66:ce8709d9912c 145 req_offset = 0;
mbed_official 66:ce8709d9912c 146 do {
mbed_official 66:ce8709d9912c 147 ret = mbedtls_ssl_write(&ssl,
mbed_official 66:ce8709d9912c 148 reinterpret_cast<const unsigned char *>(gp_buf + req_offset),
mbed_official 66:ce8709d9912c 149 req_len - req_offset);
mbed_official 66:ce8709d9912c 150 if (ret > 0)
mbed_official 66:ce8709d9912c 151 req_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 152 }
mbed_official 66:ce8709d9912c 153 while(req_offset < req_len &&
mbed_official 66:ce8709d9912c 154 (ret > 0 ||
mbed_official 66:ce8709d9912c 155 ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
mbed_official 66:ce8709d9912c 156 ret == MBEDTLS_ERR_SSL_WANT_READ));
mbed_official 66:ce8709d9912c 157 if (ret < 0) {
mbed_official 66:ce8709d9912c 158 mbedtls_printf("mbedtls_ssl_write() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 159 return ret;
mbed_official 66:ce8709d9912c 160 }
mbed_official 66:ce8709d9912c 161
mbed_official 66:ce8709d9912c 162 /* Print information about the TLS connection */
mbed_official 66:ce8709d9912c 163 ret = mbedtls_x509_crt_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 164 "\r ", mbedtls_ssl_get_peer_cert(&ssl));
mbed_official 66:ce8709d9912c 165 if (ret < 0) {
mbed_official 66:ce8709d9912c 166 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 167 return ret;
mbed_official 66:ce8709d9912c 168 }
mbed_official 66:ce8709d9912c 169 mbedtls_printf("Server certificate:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 170
mbed_official 66:ce8709d9912c 171 /* Ensure certificate verification was successful */
mbed_official 66:ce8709d9912c 172 flags = mbedtls_ssl_get_verify_result(&ssl);
mbed_official 66:ce8709d9912c 173 if (flags != 0) {
mbed_official 66:ce8709d9912c 174 ret = mbedtls_x509_crt_verify_info(gp_buf, sizeof(gp_buf),
mbed_official 66:ce8709d9912c 175 "\r ! ", flags);
mbed_official 66:ce8709d9912c 176 if (ret < 0) {
mbed_official 66:ce8709d9912c 177 mbedtls_printf("mbedtls_x509_crt_verify_info() returned "
mbed_official 66:ce8709d9912c 178 "-0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 179 return ret;
mbed_official 66:ce8709d9912c 180 } else {
mbed_official 66:ce8709d9912c 181 mbedtls_printf("Certificate verification failed (flags %lu):"
mbed_official 66:ce8709d9912c 182 "\n%s\n", flags, gp_buf);
mbed_official 66:ce8709d9912c 183 return -1;
mbed_official 66:ce8709d9912c 184 }
mbed_official 66:ce8709d9912c 185 } else {
mbed_official 66:ce8709d9912c 186 mbedtls_printf("Certificate verification passed\n");
mbed_official 66:ce8709d9912c 187 }
mbed_official 66:ce8709d9912c 188
mbed_official 66:ce8709d9912c 189 mbedtls_printf("Established TLS connection to %s\n", server_name);
mbed_official 66:ce8709d9912c 190
mbed_official 66:ce8709d9912c 191 /* Read response from the server */
mbed_official 66:ce8709d9912c 192 resp_offset = 0;
mbed_official 66:ce8709d9912c 193 resp_200 = false;
mbed_official 66:ce8709d9912c 194 resp_hello = false;
mbed_official 66:ce8709d9912c 195 do {
mbed_official 66:ce8709d9912c 196 ret = mbedtls_ssl_read(&ssl,
mbed_official 66:ce8709d9912c 197 reinterpret_cast<unsigned char *>(gp_buf + resp_offset),
mbed_official 66:ce8709d9912c 198 sizeof(gp_buf) - resp_offset - 1);
mbed_official 66:ce8709d9912c 199 if (ret > 0)
mbed_official 66:ce8709d9912c 200 resp_offset += static_cast<size_t>(ret);
mbed_official 66:ce8709d9912c 201
mbed_official 66:ce8709d9912c 202 /* Ensure that the response string is null-terminated */
mbed_official 66:ce8709d9912c 203 gp_buf[resp_offset] = '\0';
mbed_official 66:ce8709d9912c 204
mbed_official 66:ce8709d9912c 205 /* Check if we received expected string */
mbed_official 66:ce8709d9912c 206 resp_200 = resp_200 || strstr(gp_buf, HTTP_OK_STR) != NULL;
mbed_official 66:ce8709d9912c 207 resp_hello = resp_hello || strstr(gp_buf, HTTP_HELLO_STR) != NULL;
mbed_official 66:ce8709d9912c 208 } while((!resp_200 || !resp_hello) &&
mbed_official 66:ce8709d9912c 209 (ret > 0 ||
mbed_official 66:ce8709d9912c 210 ret == MBEDTLS_ERR_SSL_WANT_READ || MBEDTLS_ERR_SSL_WANT_WRITE));
mbed_official 66:ce8709d9912c 211 if (ret < 0) {
mbed_official 66:ce8709d9912c 212 mbedtls_printf("mbedtls_ssl_read() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 213 return ret;
mbed_official 66:ce8709d9912c 214 }
mbed_official 66:ce8709d9912c 215
mbed_official 66:ce8709d9912c 216 /* Display response information */
mbed_official 66:ce8709d9912c 217 mbedtls_printf("HTTP: Received %u chars from server\n", resp_offset);
mbed_official 66:ce8709d9912c 218 mbedtls_printf("HTTP: Received '%s' status ... %s\n", HTTP_OK_STR,
mbed_official 66:ce8709d9912c 219 resp_200 ? "OK" : "FAIL");
mbed_official 66:ce8709d9912c 220 mbedtls_printf("HTTP: Received message:\n%s\n", gp_buf);
mbed_official 66:ce8709d9912c 221
mbed_official 66:ce8709d9912c 222 return 0;
mbed_official 66:ce8709d9912c 223 }
mbed_official 66:ce8709d9912c 224
mbed_official 66:ce8709d9912c 225 int HelloHttpsClient::configureTCPSocket()
mbed_official 66:ce8709d9912c 226 {
mbed_official 66:ce8709d9912c 227 int ret;
mbed_official 66:ce8709d9912c 228
mbed_official 81:1b9acc423bfc 229 NetworkInterface *network = NetworkInterface::get_default_instance();
mbed_official 66:ce8709d9912c 230 if(network == NULL) {
mbed_official 81:1b9acc423bfc 231 mbedtls_printf("ERROR: No network interface found!\n");
mbed_official 66:ce8709d9912c 232 return -1;
mbed_official 66:ce8709d9912c 233 }
mbed_official 81:1b9acc423bfc 234 ret = network->connect();
mbed_official 81:1b9acc423bfc 235 if (ret != 0) {
mbed_official 81:1b9acc423bfc 236 mbedtls_printf("Error! network->connect() returned: %d\n", ret);
mbed_official 81:1b9acc423bfc 237 return ret;
mbed_official 81:1b9acc423bfc 238 }
mbed_official 66:ce8709d9912c 239
mbed_official 66:ce8709d9912c 240 if ((ret = socket.open(network)) != NSAPI_ERROR_OK) {
mbed_official 66:ce8709d9912c 241 mbedtls_printf("socket.open() returned %d\n", ret);
mbed_official 66:ce8709d9912c 242 return ret;
mbed_official 66:ce8709d9912c 243 }
mbed_official 66:ce8709d9912c 244
mbed_official 66:ce8709d9912c 245 socket.set_blocking(false);
mbed_official 66:ce8709d9912c 246
mbed_official 66:ce8709d9912c 247 return 0;
mbed_official 66:ce8709d9912c 248 }
mbed_official 66:ce8709d9912c 249
mbed_official 66:ce8709d9912c 250 int HelloHttpsClient::configureTlsContexts()
mbed_official 66:ce8709d9912c 251 {
mbed_official 66:ce8709d9912c 252 int ret;
mbed_official 66:ce8709d9912c 253
mbed_official 66:ce8709d9912c 254 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
mbed_official 66:ce8709d9912c 255 reinterpret_cast<const unsigned char *>(DRBG_PERSONALIZED_STR),
mbed_official 66:ce8709d9912c 256 strlen(DRBG_PERSONALIZED_STR) + 1);
mbed_official 66:ce8709d9912c 257 if (ret != 0) {
mbed_official 66:ce8709d9912c 258 mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 259 return ret;
mbed_official 66:ce8709d9912c 260 }
mbed_official 66:ce8709d9912c 261
mbed_official 66:ce8709d9912c 262 ret = mbedtls_x509_crt_parse(&cacert,
mbed_official 66:ce8709d9912c 263 reinterpret_cast<const unsigned char *>(TLS_PEM_CA),
mbed_official 66:ce8709d9912c 264 strlen(TLS_PEM_CA) + 1);
mbed_official 66:ce8709d9912c 265 if (ret != 0) {
mbed_official 66:ce8709d9912c 266 mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 267 return ret;
mbed_official 66:ce8709d9912c 268 }
mbed_official 66:ce8709d9912c 269
mbed_official 66:ce8709d9912c 270 ret = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
mbed_official 66:ce8709d9912c 271 MBEDTLS_SSL_TRANSPORT_STREAM,
mbed_official 66:ce8709d9912c 272 MBEDTLS_SSL_PRESET_DEFAULT);
mbed_official 66:ce8709d9912c 273 if (ret != 0) {
mbed_official 66:ce8709d9912c 274 mbedtls_printf("mbedtls_ssl_config_defaults() returned -0x%04X\n",
mbed_official 66:ce8709d9912c 275 -ret);
mbed_official 66:ce8709d9912c 276 return ret;
mbed_official 66:ce8709d9912c 277 }
mbed_official 66:ce8709d9912c 278
mbed_official 66:ce8709d9912c 279 mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacert, NULL);
mbed_official 66:ce8709d9912c 280 mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbed_official 66:ce8709d9912c 281
mbed_official 66:ce8709d9912c 282 /*
mbed_official 66:ce8709d9912c 283 * It is possible to disable authentication by passing
mbed_official 66:ce8709d9912c 284 * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
mbed_official 66:ce8709d9912c 285 */
mbed_official 66:ce8709d9912c 286 mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbed_official 66:ce8709d9912c 287
mbed_official 83:6dbd4cae4527 288 /* Configure certificate verification function to clear time/date flags */
mbed_official 83:6dbd4cae4527 289 mbedtls_ssl_conf_verify(&ssl_conf, sslVerify, this);
mbed_official 83:6dbd4cae4527 290
mbed_official 66:ce8709d9912c 291 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
mbed_official 66:ce8709d9912c 292 mbedtls_ssl_conf_dbg(&ssl_conf, sslDebug, NULL);
mbed_official 66:ce8709d9912c 293 mbedtls_debug_set_threshold(HELLO_HTTPS_CLIENT_DEBUG_LEVEL);
mbed_official 66:ce8709d9912c 294 #endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
mbed_official 66:ce8709d9912c 295
mbed_official 66:ce8709d9912c 296 if ((ret = mbedtls_ssl_setup( &ssl, &ssl_conf)) != 0) {
mbed_official 66:ce8709d9912c 297 mbedtls_printf("mbedtls_ssl_setup() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 298 return ret;
mbed_official 66:ce8709d9912c 299 }
mbed_official 66:ce8709d9912c 300
mbed_official 66:ce8709d9912c 301 if ((ret = mbedtls_ssl_set_hostname( &ssl, server_name )) != 0) {
mbed_official 66:ce8709d9912c 302 mbedtls_printf("mbedtls_ssl_set_hostname() returned -0x%04X\n",
mbed_official 66:ce8709d9912c 303 -ret);
mbed_official 66:ce8709d9912c 304 return ret;
mbed_official 66:ce8709d9912c 305 }
mbed_official 66:ce8709d9912c 306
mbed_official 66:ce8709d9912c 307 mbedtls_ssl_set_bio(&ssl, static_cast<void *>(&socket), sslSend, sslRecv,
mbed_official 66:ce8709d9912c 308 NULL);
mbed_official 66:ce8709d9912c 309
mbed_official 66:ce8709d9912c 310 return 0;
mbed_official 66:ce8709d9912c 311 }
mbed_official 66:ce8709d9912c 312
mbed_official 66:ce8709d9912c 313 int HelloHttpsClient::sslRecv(void *ctx, unsigned char *buf, size_t len)
mbed_official 66:ce8709d9912c 314 {
mbed_official 66:ce8709d9912c 315 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
mbed_official 66:ce8709d9912c 316 int ret = socket->recv(buf, len);
mbed_official 66:ce8709d9912c 317
mbed_official 66:ce8709d9912c 318 if (ret == NSAPI_ERROR_WOULD_BLOCK)
mbed_official 66:ce8709d9912c 319 ret = MBEDTLS_ERR_SSL_WANT_READ;
mbed_official 66:ce8709d9912c 320 else if (ret < 0)
mbed_official 66:ce8709d9912c 321 mbedtls_printf("socket.recv() returned %d\n", ret);
mbed_official 66:ce8709d9912c 322
mbed_official 66:ce8709d9912c 323 return ret;
mbed_official 66:ce8709d9912c 324 }
mbed_official 66:ce8709d9912c 325
mbed_official 66:ce8709d9912c 326 int HelloHttpsClient::sslSend(void *ctx, const unsigned char *buf, size_t len)
mbed_official 66:ce8709d9912c 327 {
mbed_official 66:ce8709d9912c 328 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
mbed_official 66:ce8709d9912c 329 int ret = socket->send(buf, len);
mbed_official 66:ce8709d9912c 330
mbed_official 66:ce8709d9912c 331 if (ret == NSAPI_ERROR_WOULD_BLOCK)
mbed_official 66:ce8709d9912c 332 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
mbed_official 66:ce8709d9912c 333 else if (ret < 0)
mbed_official 66:ce8709d9912c 334 mbedtls_printf("socket.send() returned %d\n", ret);
mbed_official 66:ce8709d9912c 335
mbed_official 66:ce8709d9912c 336 return ret;
mbed_official 66:ce8709d9912c 337 }
mbed_official 66:ce8709d9912c 338
mbed_official 66:ce8709d9912c 339 void HelloHttpsClient::sslDebug(void *ctx, int level, const char *file,
mbed_official 66:ce8709d9912c 340 int line, const char *str)
mbed_official 66:ce8709d9912c 341 {
mbed_official 66:ce8709d9912c 342 (void)ctx;
mbed_official 66:ce8709d9912c 343
mbed_official 66:ce8709d9912c 344 const char *p, *basename;
mbed_official 66:ce8709d9912c 345
mbed_official 66:ce8709d9912c 346 /* Extract basename from file */
mbed_official 66:ce8709d9912c 347 for (p = basename = file; *p != '\0'; p++) {
mbed_official 66:ce8709d9912c 348 if (*p == '/' || *p == '\\')
mbed_official 66:ce8709d9912c 349 basename = p + 1;
mbed_official 66:ce8709d9912c 350 }
mbed_official 66:ce8709d9912c 351
mbed_official 66:ce8709d9912c 352 mbedtls_printf("%s:%d: |%d| %s\r", basename, line, level, str);
mbed_official 66:ce8709d9912c 353 }
mbed_official 66:ce8709d9912c 354
mbed_official 66:ce8709d9912c 355 int HelloHttpsClient::sslVerify(void *ctx, mbedtls_x509_crt *crt, int depth,
mbed_official 66:ce8709d9912c 356 uint32_t *flags)
mbed_official 66:ce8709d9912c 357 {
mbed_official 83:6dbd4cae4527 358 int ret = 0;
mbed_official 66:ce8709d9912c 359
mbed_official 83:6dbd4cae4527 360 /*
mbed_official 83:6dbd4cae4527 361 * If MBEDTLS_HAVE_TIME_DATE is defined, then the certificate date and time
mbed_official 83:6dbd4cae4527 362 * validity checks will probably fail because this application does not set
mbed_official 83:6dbd4cae4527 363 * up the clock correctly. We filter out date and time related failures
mbed_official 83:6dbd4cae4527 364 * instead
mbed_official 83:6dbd4cae4527 365 */
mbed_official 83:6dbd4cae4527 366 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE & ~MBEDTLS_X509_BADCERT_EXPIRED;
mbed_official 83:6dbd4cae4527 367
mbed_official 83:6dbd4cae4527 368 #if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
mbed_official 83:6dbd4cae4527 369 HelloHttpsClient *client = static_cast<HelloHttpsClient *>(ctx);
mbed_official 66:ce8709d9912c 370
mbed_official 66:ce8709d9912c 371 ret = mbedtls_x509_crt_info(client->gp_buf, sizeof(gp_buf), "\r ", crt);
mbed_official 66:ce8709d9912c 372 if (ret < 0) {
mbed_official 66:ce8709d9912c 373 mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
mbed_official 66:ce8709d9912c 374 } else {
mbed_official 66:ce8709d9912c 375 ret = 0;
mbed_official 66:ce8709d9912c 376 mbedtls_printf("Verifying certificate at depth %d:\n%s\n",
mbed_official 66:ce8709d9912c 377 depth, client->gp_buf);
mbed_official 66:ce8709d9912c 378 }
mbed_official 83:6dbd4cae4527 379 #endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
mbed_official 66:ce8709d9912c 380
mbed_official 66:ce8709d9912c 381 return ret;
mbed_official 66:ce8709d9912c 382 }