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:
Thu May 10 05:15:52 2018 +0100
Revision:
69:ffefb2e2d149
Parent:
66:ce8709d9912c
Child:
76:b8c07be20122
Merge pull request #165 from ARMmbed/feature-platform-init

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