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 Jul 19 09:00:06 2018 +0100
Revision:
76:b8c07be20122
Parent:
69:ffefb2e2d149
Child:
86:e1ceb1075f1a
Merge pull request #174 from RonEld/seperate_server_name

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