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:
Mon Oct 08 17:00:19 2018 +0100
Revision:
83:6dbd4cae4527
Parent:
81:1b9acc423bfc
Child:
86:e1ceb1075f1a
Merge pull request #126 from andresag01/line-endings

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