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 Feb 25 16:42:26 2019 +0000
Revision:
97:55368c4a101f
Parent:
86:e1ceb1075f1a
Merge pull request #235 from adbridge/master

All the CI tests have passed.
Updating mbed-os to mbed-os-5.11.5
.
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 #ifndef _HELLOHTTPSCLIENT_H_
mbed_official 66:ce8709d9912c 23 #define _HELLOHTTPSCLIENT_H_
mbed_official 66:ce8709d9912c 24
mbed_official 66:ce8709d9912c 25 #include "TCPSocket.h"
mbed_official 66:ce8709d9912c 26
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
mbed_official 66:ce8709d9912c 36 /**
mbed_official 66:ce8709d9912c 37 * Change to a number between 1 and 4 to debug the TLS connection
mbed_official 66:ce8709d9912c 38 */
mbed_official 66:ce8709d9912c 39 #define HELLO_HTTPS_CLIENT_DEBUG_LEVEL 0
mbed_official 66:ce8709d9912c 40
mbed_official 66:ce8709d9912c 41 /**
mbed_official 66:ce8709d9912c 42 * Length (in bytes) for generic buffers used to hold debug or HTTP
mbed_official 66:ce8709d9912c 43 * request/response strings
mbed_official 66:ce8709d9912c 44 */
mbed_official 66:ce8709d9912c 45 #define GENERAL_PURPOSE_BUFFER_LENGTH 1024
mbed_official 66:ce8709d9912c 46
mbed_official 66:ce8709d9912c 47 /**
mbed_official 66:ce8709d9912c 48 * This class implements the logic for fetching a file from a webserver using
mbed_official 66:ce8709d9912c 49 * a TCP socket and parsing the result.
mbed_official 66:ce8709d9912c 50 */
mbed_official 66:ce8709d9912c 51 class HelloHttpsClient
mbed_official 66:ce8709d9912c 52 {
mbed_official 66:ce8709d9912c 53 public:
mbed_official 66:ce8709d9912c 54 /**
mbed_official 66:ce8709d9912c 55 * Construct an HelloHttpsClient instance
mbed_official 66:ce8709d9912c 56 *
mbed_official 66:ce8709d9912c 57 * \param[in] in_server_name
mbed_official 76:b8c07be20122 58 * The server host name
mbed_official 76:b8c07be20122 59 * \param[in] in_server_addr
mbed_official 66:ce8709d9912c 60 * The server domain/IP address
mbed_official 66:ce8709d9912c 61 * \param[in] in_server_port
mbed_official 66:ce8709d9912c 62 * The server port
mbed_official 66:ce8709d9912c 63 */
mbed_official 66:ce8709d9912c 64 HelloHttpsClient(const char *in_server_name,
mbed_official 76:b8c07be20122 65 const char *in_server_addr,
mbed_official 86:e1ceb1075f1a 66 const uint16_t in_server_port);
mbed_official 66:ce8709d9912c 67
mbed_official 66:ce8709d9912c 68 /**
mbed_official 66:ce8709d9912c 69 * Free any allocated resources
mbed_official 66:ce8709d9912c 70 */
mbed_official 66:ce8709d9912c 71 ~HelloHttpsClient();
mbed_official 66:ce8709d9912c 72
mbed_official 66:ce8709d9912c 73 /**
mbed_official 66:ce8709d9912c 74 * Start the connection to the server and request to read the file at
mbed_official 66:ce8709d9912c 75 * HTTP_REQUEST_FILE_PATH
mbed_official 66:ce8709d9912c 76 *
mbed_official 66:ce8709d9912c 77 * \return 0 if successful
mbed_official 66:ce8709d9912c 78 */
mbed_official 66:ce8709d9912c 79 int run();
mbed_official 66:ce8709d9912c 80
mbed_official 66:ce8709d9912c 81 private:
mbed_official 66:ce8709d9912c 82 /**
mbed_official 66:ce8709d9912c 83 * Create a TCPSocket object that can be used to communicate with the server
mbed_official 66:ce8709d9912c 84 */
mbed_official 66:ce8709d9912c 85 int configureTCPSocket();
mbed_official 66:ce8709d9912c 86
mbed_official 66:ce8709d9912c 87 /**
mbed_official 66:ce8709d9912c 88 * Configure the Mbed TLS structures required to establish a TLS connection
mbed_official 66:ce8709d9912c 89 * with the server
mbed_official 66:ce8709d9912c 90 */
mbed_official 66:ce8709d9912c 91 int configureTlsContexts();
mbed_official 66:ce8709d9912c 92
mbed_official 66:ce8709d9912c 93 /**
mbed_official 66:ce8709d9912c 94 * Wrapper function around TCPSocket that gets called by Mbed TLS whenever
mbed_official 66:ce8709d9912c 95 * we call mbedtls_ssl_read()
mbed_official 66:ce8709d9912c 96 *
mbed_official 66:ce8709d9912c 97 * \param[in] ctx
mbed_official 66:ce8709d9912c 98 * The TCPSocket object
mbed_official 66:ce8709d9912c 99 * \param[in] buf
mbed_official 66:ce8709d9912c 100 * Buffer where data received will be stored
mbed_official 66:ce8709d9912c 101 * \param[in] len
mbed_official 66:ce8709d9912c 102 * The length (in bytes) of the buffer
mbed_official 66:ce8709d9912c 103 *
mbed_official 66:ce8709d9912c 104 * \return If successful, the number of bytes received, a negative value
mbed_official 66:ce8709d9912c 105 * otherwise.
mbed_official 66:ce8709d9912c 106 */
mbed_official 66:ce8709d9912c 107 static int sslRecv(void *ctx, unsigned char *buf, size_t len);
mbed_official 66:ce8709d9912c 108
mbed_official 66:ce8709d9912c 109 /**
mbed_official 66:ce8709d9912c 110 * Wrapper function around TCPSocket that gets called by Mbed TLS whenever
mbed_official 66:ce8709d9912c 111 * we call mbedtls_ssl_write()
mbed_official 66:ce8709d9912c 112 *
mbed_official 66:ce8709d9912c 113 * \param[in] ctx
mbed_official 66:ce8709d9912c 114 * The TCPSocket object
mbed_official 66:ce8709d9912c 115 * \param[in] buf
mbed_official 66:ce8709d9912c 116 * Buffer containing the data to be sent
mbed_official 66:ce8709d9912c 117 * \param[in] len
mbed_official 66:ce8709d9912c 118 * The number of bytes to send
mbed_official 66:ce8709d9912c 119 *
mbed_official 66:ce8709d9912c 120 * \return If successful, the number of bytes sent, a negative value
mbed_official 66:ce8709d9912c 121 * otherwise
mbed_official 66:ce8709d9912c 122 */
mbed_official 66:ce8709d9912c 123 static int sslSend(void *ctx, const unsigned char *buf, size_t len);
mbed_official 66:ce8709d9912c 124
mbed_official 66:ce8709d9912c 125 /**
mbed_official 66:ce8709d9912c 126 * Callback to handle debug prints to serial
mbed_official 66:ce8709d9912c 127 *
mbed_official 66:ce8709d9912c 128 * \param[in] ctx
mbed_official 66:ce8709d9912c 129 * The context (unused in this case)
mbed_official 66:ce8709d9912c 130 * \param[in] level
mbed_official 66:ce8709d9912c 131 * The current debug level
mbed_official 66:ce8709d9912c 132 * \param[in] file
mbed_official 66:ce8709d9912c 133 * The C file that is logging this message
mbed_official 66:ce8709d9912c 134 * \param[in] line
mbed_official 66:ce8709d9912c 135 * The line number in the file
mbed_official 66:ce8709d9912c 136 * \param[in] str
mbed_official 66:ce8709d9912c 137 * The string to log to serial
mbed_official 66:ce8709d9912c 138 */
mbed_official 66:ce8709d9912c 139 static void sslDebug(void *ctx, int level, const char *file, int line,
mbed_official 66:ce8709d9912c 140 const char *str);
mbed_official 66:ce8709d9912c 141
mbed_official 66:ce8709d9912c 142 /**
mbed_official 66:ce8709d9912c 143 * Callback to handle certificate verification
mbed_official 66:ce8709d9912c 144 *
mbed_official 66:ce8709d9912c 145 * /param[in] data
mbed_official 66:ce8709d9912c 146 * (unused)
mbed_official 66:ce8709d9912c 147 * /param[in] crt
mbed_official 66:ce8709d9912c 148 * The crt in the chain that we are verifying
mbed_official 66:ce8709d9912c 149 * /param[in] depth
mbed_official 66:ce8709d9912c 150 * The depth of the current certificate in the chain
mbed_official 66:ce8709d9912c 151 * /param[in/out] flags
mbed_official 66:ce8709d9912c 152 * The flags resulting from the verification
mbed_official 66:ce8709d9912c 153 *
mbed_official 66:ce8709d9912c 154 * /return 0 if successful
mbed_official 66:ce8709d9912c 155 */
mbed_official 66:ce8709d9912c 156 static int sslVerify(void *ctx, mbedtls_x509_crt *crt, int depth,
mbed_official 66:ce8709d9912c 157 uint32_t *flags);
mbed_official 66:ce8709d9912c 158
mbed_official 66:ce8709d9912c 159 private:
mbed_official 66:ce8709d9912c 160 /**
mbed_official 66:ce8709d9912c 161 * Personalization string for the drbg
mbed_official 66:ce8709d9912c 162 */
mbed_official 66:ce8709d9912c 163 static const char *DRBG_PERSONALIZED_STR;
mbed_official 66:ce8709d9912c 164
mbed_official 66:ce8709d9912c 165 /**
mbed_official 66:ce8709d9912c 166 * Length of error string buffer for logging failures related to Mbed TLS
mbed_official 66:ce8709d9912c 167 */
mbed_official 66:ce8709d9912c 168 static const size_t ERROR_LOG_BUFFER_LENGTH;
mbed_official 66:ce8709d9912c 169
mbed_official 66:ce8709d9912c 170 /**
mbed_official 66:ce8709d9912c 171 * Chain of trusted CAs in PEM format
mbed_official 66:ce8709d9912c 172 */
mbed_official 66:ce8709d9912c 173 static const char *TLS_PEM_CA;
mbed_official 66:ce8709d9912c 174
mbed_official 66:ce8709d9912c 175 /**
mbed_official 66:ce8709d9912c 176 * Path to the file that will be requested from the server
mbed_official 66:ce8709d9912c 177 */
mbed_official 66:ce8709d9912c 178 static const char *HTTP_REQUEST_FILE_PATH;
mbed_official 66:ce8709d9912c 179
mbed_official 66:ce8709d9912c 180 /**
mbed_official 66:ce8709d9912c 181 * Expected strings in the HTTP response from the server
mbed_official 66:ce8709d9912c 182 */
mbed_official 66:ce8709d9912c 183 static const char *HTTP_OK_STR;
mbed_official 66:ce8709d9912c 184
mbed_official 66:ce8709d9912c 185 /**
mbed_official 66:ce8709d9912c 186 * Expected strings in the HTTP response from the server
mbed_official 66:ce8709d9912c 187 */
mbed_official 66:ce8709d9912c 188 static const char *HTTP_HELLO_STR;
mbed_official 66:ce8709d9912c 189
mbed_official 66:ce8709d9912c 190 /**
mbed_official 66:ce8709d9912c 191 * Instance of TCPSocket used to communicate with the server
mbed_official 66:ce8709d9912c 192 */
mbed_official 66:ce8709d9912c 193 TCPSocket socket;
mbed_official 66:ce8709d9912c 194
mbed_official 66:ce8709d9912c 195 /**
mbed_official 76:b8c07be20122 196 * The server host name to contact
mbed_official 76:b8c07be20122 197 */
mbed_official 76:b8c07be20122 198 const char *server_name;
mbed_official 76:b8c07be20122 199
mbed_official 76:b8c07be20122 200 /**
mbed_official 66:ce8709d9912c 201 * The domain/IP address of the server to contact
mbed_official 66:ce8709d9912c 202 */
mbed_official 76:b8c07be20122 203 const char *server_addr;
mbed_official 66:ce8709d9912c 204 /**
mbed_official 66:ce8709d9912c 205 * The port number to use in the connection
mbed_official 66:ce8709d9912c 206 */
mbed_official 66:ce8709d9912c 207 const uint16_t server_port;
mbed_official 66:ce8709d9912c 208
mbed_official 66:ce8709d9912c 209 /**
mbed_official 66:ce8709d9912c 210 * A generic buffer used to hold debug or HTTP request/response strings
mbed_official 66:ce8709d9912c 211 */
mbed_official 66:ce8709d9912c 212 char gp_buf[GENERAL_PURPOSE_BUFFER_LENGTH];
mbed_official 66:ce8709d9912c 213
mbed_official 66:ce8709d9912c 214 /**
mbed_official 66:ce8709d9912c 215 * Entropy context used to seed the DRBG to use in the TLS connection
mbed_official 66:ce8709d9912c 216 */
mbed_official 66:ce8709d9912c 217 mbedtls_entropy_context entropy;
mbed_official 66:ce8709d9912c 218 /**
mbed_official 66:ce8709d9912c 219 * The DRBG used throughout the TLS connection
mbed_official 66:ce8709d9912c 220 */
mbed_official 66:ce8709d9912c 221 mbedtls_ctr_drbg_context ctr_drbg;
mbed_official 66:ce8709d9912c 222 /**
mbed_official 66:ce8709d9912c 223 * The parsed chain of trusted CAs
mbed_official 66:ce8709d9912c 224 */
mbed_official 66:ce8709d9912c 225 mbedtls_x509_crt cacert;
mbed_official 66:ce8709d9912c 226 /**
mbed_official 66:ce8709d9912c 227 * THe TLS context
mbed_official 66:ce8709d9912c 228 */
mbed_official 66:ce8709d9912c 229 mbedtls_ssl_context ssl;
mbed_official 66:ce8709d9912c 230 /**
mbed_official 66:ce8709d9912c 231 * The TLS configuration in use
mbed_official 66:ce8709d9912c 232 */
mbed_official 66:ce8709d9912c 233 mbedtls_ssl_config ssl_conf;
mbed_official 66:ce8709d9912c 234 };
mbed_official 66:ce8709d9912c 235
mbed_official 66:ce8709d9912c 236 #endif /* _HELLOHTTPSCLIENT_H_ */