Merge remote-tracking branch 'upstream/development' into iss309
This commit is contained in:
commit
8483e28e21
14 changed files with 61 additions and 685 deletions
|
@ -39,7 +39,7 @@ and build it with:
|
|||
|
||||
yotta build
|
||||
|
||||
If, on the other hand, you already have a copy of mbed TLS from a source other than the yotta registry, for example from cloning our github repository, or from downloading a tarball of the standalone edition, then you'll need first need to generate the yotta module by running:
|
||||
If, on the other hand, you already have a copy of mbed TLS from a source other than the yotta registry, for example from cloning our GitHub repository, or from downloading a tarball of the standalone edition, then you'll need first need to generate the yotta module by running:
|
||||
|
||||
yotta/create-module.sh
|
||||
|
||||
|
@ -50,7 +50,7 @@ from the mbed TLS root directory. This will create the yotta module in the `yott
|
|||
|
||||
In any case, you'll probably want to set the yotta target before building unless it's already set globally; for more information on using yotta, please consult the [yotta documentation](http://docs.yottabuild.org/).
|
||||
|
||||
The yotta edition of mbed TLS includes a few example programs, some of which demonstrate integration with mbed OS; for more details, please consult the [Readme at the root of the yotta module](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/README.md).
|
||||
For more details on the yotta/mbed OS edition of mbed TLS, including example programs, please consult the [Readme at the root of the yotta module](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/README.md).
|
||||
|
||||
### Make
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeou
|
|||
#endif /* MBEDTLS_HAVE_TIME */
|
||||
|
||||
/**
|
||||
* \brief Set the cache timeout
|
||||
* \brief Set the maximum number of cache entries
|
||||
* (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
|
||||
*
|
||||
* \param cache SSL cache context
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* This MPI implementation is based on:
|
||||
*
|
||||
* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
|
||||
* http://www.stillhq.com/extracted/gnupg-api/mbedtls_mpi/
|
||||
* http://www.stillhq.com/extracted/gnupg-api/mpi/
|
||||
* http://math.libtomcrypt.com/files/tommath.pdf
|
||||
*/
|
||||
|
||||
|
|
|
@ -5735,11 +5735,7 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
|
|||
mbedtls_free( ssl->handshake->psk );
|
||||
|
||||
if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
|
||||
{
|
||||
mbedtls_free( ssl->handshake->psk );
|
||||
ssl->handshake->psk = NULL;
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
}
|
||||
|
||||
ssl->handshake->psk_len = psk_len;
|
||||
memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len );
|
||||
|
|
|
@ -209,7 +209,7 @@ int main( int argc, char *argv[] )
|
|||
ret = 1;
|
||||
mbedtls_printf( USAGE );
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
mbedtls_printf( " availabled ec_curve values:\n" );
|
||||
mbedtls_printf( " available ec_curve values:\n" );
|
||||
curve_info = mbedtls_ecp_curve_list();
|
||||
mbedtls_printf( " %s (default)\n", curve_info->name );
|
||||
while( ( ++curve_info )->name != NULL )
|
||||
|
|
|
@ -21,12 +21,12 @@ for my $suite (@suites)
|
|||
my $result = `$prefix$suite`;
|
||||
if( $result =~ /PASSED/ ) {
|
||||
print "PASS\n";
|
||||
my ($tests, $skipped) = $result =~ /([0-9]*) tests.*?([0-9]*) skipped/;
|
||||
$total_tests_run += $tests - $skipped;
|
||||
} else {
|
||||
$failed_suites++;
|
||||
print "FAIL\n";
|
||||
}
|
||||
my ($tests, $skipped) = $result =~ /([0-9]*) tests.*?([0-9]*) skipped/;
|
||||
$total_tests_run += $tests - $skipped;
|
||||
}
|
||||
|
||||
print "-" x 72, "\n";
|
||||
|
|
|
@ -4,38 +4,74 @@ mbed TLS (formerly known as PolarSSL) makes it trivially easy for developers to
|
|||
|
||||
The Beta release of mbed TLS integrates the mbed TLS library into mbed OS, mbed SDK and yotta. This is a preview release intended for evaluation only and is **not recommended for deployment**. It currently implements no secure source of random numbers, weakening its security.
|
||||
|
||||
Currently the only supported yotta targets are:
|
||||
- `frdm-k64f-gcc` and `frdm-k64f-armcc`
|
||||
- `x86-linux-native` and `x86-osx-native`
|
||||
|
||||
## Sample programs
|
||||
|
||||
This release includes the following examples:
|
||||
|
||||
1. [**TLS client:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-tls-client) found in `test/example-tls-client`. Downloads a test file from an HTTPS server and looks for a specific string in that file.
|
||||
1. [**Self test:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-selftest) found in `test/example-selftest`. Tests different basic functions in the mbed TLS library.
|
||||
|
||||
2. [**Self test:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-selftest) found in `test/example-selftest`. Tests different basic functions in the mbed TLS library.
|
||||
2. [**Benchmark:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-benchmark) found in `test/example-benchmark`. Measures the time taken to perform basic cryptographic functions used in the library.
|
||||
|
||||
3. [**Benchmark:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-benchmark) found in `test/example-benchmark`. Measures the time taken to perform basic cryptographic functions used in the library.
|
||||
3. [**Hashing:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-hashing) found in `test/example-hashing`. Demonstrates the various APIs for computes hashes of data (also known as message digests) with SHA-256.
|
||||
|
||||
These examples are integrated as yotta tests, so that they are built automatically when you build mbed TLS. You'll find more examples in the various `test/example-*` directories.
|
||||
4. [**Authenticated encrypted:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-authcrypt) found in `test/example-authcrypt`. Demonstrates usage of the Cipher API for encrypting and authenticating data with AES-CCM.
|
||||
|
||||
## Running mbed TLS
|
||||
These examples are integrated as yotta tests, so that they are built automatically when you build mbed TLS. Each of them comes with complete usage instructions as a Readme file in its directory.
|
||||
|
||||
To build and run the example, please follow the instructions in the [TLS client example](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-tls-client) directory. These include a list of prerequisites and an explanation of building mbed TLS with yotta.
|
||||
## Performing TLS and DTLS connections
|
||||
|
||||
A high-level API for performing TLS and DTLS connections with mbed TLS in mbed OS is provided in a separate yotta module: [mbed-tls-sockets](https://github.com/ARMmbed/mbed-tls-sockets). It is the recommended API for TLS and DTLS connections. It is very similar to the API provided by the [sockets](https://github.com/ARMmbed/sockets) module for unencrypted TCP and UDP connections.
|
||||
|
||||
The `mbed-tls-sockets` module includes a complete [example TLS client](https://github.com/ARMmbed/mbed-tls-sockets/blob/master/test/tls-client/main.cpp) with [usage instructions](https://github.com/ARMmbed/mbed-tls-sockets/blob/master/test/tls-client/README.md).
|
||||
|
||||
## Configuring mbed TLS features
|
||||
|
||||
mbed TLS makes it easy to disable any feature during compilation that isn't required for a particular project. The default configuration enables all modern and widely-used features, which should meet the needs of new projects, and disables all features that are older or less common, to minimize the code footprint.
|
||||
mbed TLS makes it easy to disable any feature during compilation that isn't required for a particular project. The default configuration enables all modern and widely-used features, which should meet the needs of new projects, and disables all features that are older or less common, to minimize the code footprint.
|
||||
|
||||
The list of available compilation flags is presented in the fully documented [config.h file](https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/config.h), present in the `mbedtls` directory of the yotta module.
|
||||
|
||||
If you need to adjust those flags, you can provide your own configuration file with suitable `#define` and `#undef` statements. These will be included between the default definitions and the sanity checks. Your configuration file should be in your application's `include` directory, and can be named freely; you just need to let mbed TLS know the file's name. To do that, use yotta's [configuration system](http://docs.yottabuild.org/reference/config.html). The file's name should be in your `config.json` file, under mbedtls, as the key `user-config-file`. For example:
|
||||
If you need to adjust those flags, you can provide your own configuration-adjustment file with suitable `#define` and `#undef` statements. These will be included between the default definitions and the sanity checks. Your configuration file should be in your application's include directory, and can be named freely; you just need to let mbed TLS know the file's name. To do that, use yotta's [configuration system](http://docs.yottabuild.org/reference/config.html). The file's name should be in your `config.json` file, under mbedtls, as the key `user-config-file`.
|
||||
|
||||
For example, in an application called `myapp`, if you want to enable the EC J-PAKE key exchange and disable the CBC cipher mode, you can create a file named for example `mbedtls-config-changes.h` in the `myapp` directory containing the following lines:
|
||||
|
||||
#define MBEDTLS_ECJPAKE_C
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
|
||||
|
||||
#undef MBEDTLS_CIPHER_MODE_CBC
|
||||
|
||||
and then create a file named `config.json` at the root of your application with the following contents:
|
||||
|
||||
{
|
||||
"mbedtls": {
|
||||
"user-config-file": "\"myapp/my_mbedtls_config_changes.h\""
|
||||
"user-config-file": "\"myapp/mbedtls-config-changes.h\""
|
||||
}
|
||||
}
|
||||
|
||||
Please note: you need to provide the exact name that will be used in the `#include` directive, including the `<>` or quotes around the name.
|
||||
|
||||
## Getting mbed TLS from GitHub
|
||||
|
||||
Like most components of mbed OS, mbed TLS is developed in the open and its source can be found on GitHub: [ARMmbed/mbedtls](https://github.com/ARMmbed/mbedtls). Unlike most other mbed OS components however, you cannot just clone the repository and run `yotta build` from its root. This is because mbed TLS also exists as an independent component, so its repository includes things that are not relevant for mbed OS, as well as other build systems.
|
||||
|
||||
The way to use mbed TLS from a clone of the GitHub repository is to run the following commands from the root of a checkout:
|
||||
|
||||
yotta/create-module.sh
|
||||
cd yotta/module
|
||||
|
||||
You can then run any yotta command you would normally run, such as `yotta build` or `yotta link`.
|
||||
|
||||
## Differences between the standalone and mbed OS editions
|
||||
|
||||
While the two editions share the same code base, there are still a number of differences, mainly in configuration and in integration. You should keep in mind those differences when reading some articles of our [knowledge base](https://tls.mbed.org/kb), as currently the articles are about the standalone edition.
|
||||
|
||||
* The mbed OS edition has a smaller set of features enabled by default in `config.h`, in order to reduce footprint. While the default configuration of the standalone edition puts more emphasize on maintaining interoperability with old peers, the mbed OS edition only enables the most modern ciphers and the latest version of (D)TLS.
|
||||
* The following components of mbed TLS are not enabled in the mbed OS edition as mbed OS already includes equivalent facilities: `net.c` and `timing.c`.
|
||||
* The mbed OS edition comes with a fully integrated API for (D)TLS connections in a companion module: [mbed-tls-sockets](https://github.com/ARMmbed/mbed-tls-sockets), see "Performing TLS and DTLS connections" above.
|
||||
|
||||
## Contributing
|
||||
|
||||
We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
|
||||
|
|
|
@ -171,7 +171,7 @@ static int example(void)
|
|||
|
||||
#if defined(TARGET_LIKE_MBED)
|
||||
|
||||
#include "mbed/test_env.h"
|
||||
#include "mbed-drivers/test_env.h"
|
||||
#include "minar/minar.h"
|
||||
|
||||
static void run() {
|
||||
|
|
|
@ -71,7 +71,7 @@ int main() {
|
|||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed-drivers/mbed.h"
|
||||
|
||||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
|
||||
#include "mbedtls/memory_buffer_alloc.h"
|
||||
|
@ -931,7 +931,7 @@ int benchmark( int argc, char *argv[] )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
#include "mbed/test_env.h"
|
||||
#include "mbed-drivers/test_env.h"
|
||||
#include "minar/minar.h"
|
||||
|
||||
static void run() {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "mbedtls/md.h" /* generic interface */
|
||||
|
||||
#if defined(TARGET_LIKE_MBED)
|
||||
#include "mbed/mbed.h"
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
||||
|
@ -151,7 +151,7 @@ int example(void)
|
|||
|
||||
#if defined(TARGET_LIKE_MBED)
|
||||
|
||||
#include "mbed/test_env.h"
|
||||
#include "mbed-drivers/test_env.h"
|
||||
#include "minar/minar.h"
|
||||
|
||||
static void run() {
|
||||
|
|
|
@ -242,7 +242,7 @@ int selftest( int argc, char *argv[] )
|
|||
|
||||
#if defined(TARGET_LIKE_MBED)
|
||||
|
||||
#include "mbed/test_env.h"
|
||||
#include "mbed-drivers/test_env.h"
|
||||
#include "minar/minar.h"
|
||||
|
||||
static void run() {
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
# HTTPS File Download Example for TLS Client
|
||||
|
||||
This application downloads a file from an HTTPS server (developer.mbed.org) and looks for a specific string in that file.
|
||||
|
||||
This example is implemented as a logic class (HelloHTTPS) wrapping a TCP socket and a TLS context. The logic class handles all events, leaving the main loop to just check if the process has finished.
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
To build and run this example you must have:
|
||||
|
||||
* A computer with the following software installed:
|
||||
* [CMake](http://www.cmake.org/download/).
|
||||
* [yotta](https://github.com/ARMmbed/yotta). Please note that **yotta has its own set of dependencies**, listed in the [installation instructions](http://armmbed.github.io/yotta/#installing-on-windows).
|
||||
* [Python](https://www.python.org/downloads/).
|
||||
* [The ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded).
|
||||
* A serial terminal emulator (Like screen, pySerial and cu).
|
||||
* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in which case you'll have to substitute frdm-k64f-gcc with the appropriate target in the instructions below).
|
||||
* A micro-USB cable.
|
||||
* An Ethernet connection to the internet.
|
||||
* An Ethernet cable.
|
||||
* If your OS is Windows, please follow the installation instructions [for the serial port driver](https://developer.mbed.org/handbook/Windows-serial-configuration).
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Connect the FRDM-K64F to the internet using the Ethernet cable.
|
||||
|
||||
2. Connect the FRDM-K64F to the computer with the micro-USB cable, being careful to use the "OpenSDA" connector on the target board.
|
||||
|
||||
3. Navigate to the mbedtls directory supplied with your release and open a terminal.
|
||||
|
||||
4. Set the yotta target:
|
||||
|
||||
```
|
||||
yotta target frdm-k64f-gcc
|
||||
```
|
||||
|
||||
5. Build mbedtls and the examples. This will take a long time if it is the first time:
|
||||
|
||||
```
|
||||
$ yotta build
|
||||
```
|
||||
|
||||
6. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-tls-client.bin` to your mbed board and wait until the LED next to the USB port stops blinking.
|
||||
|
||||
7. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F.
|
||||
|
||||
Use the following settings:
|
||||
|
||||
* 115200 baud (not 9600).
|
||||
* 8N1.
|
||||
* No flow control.
|
||||
|
||||
8. Press the Reset button on the board.
|
||||
|
||||
9. The output in the terminal window should look similar to this:
|
||||
|
||||
```
|
||||
{{timeout;120}}
|
||||
{{host_test_name;default}}
|
||||
{{description;mbed TLS example HTTPS client}}
|
||||
{{test_id;MBEDTLS_EX_HTTPS_CLIENT}}
|
||||
{{start}}
|
||||
|
||||
Client IP Address is 192.168.0.2
|
||||
Starting DNS lookup for developer.mbed.org
|
||||
DNS Response Received:
|
||||
developer.mbed.org: 217.140.101.30
|
||||
Connecting to 217.140.101.30:443
|
||||
Connected to 217.140.101.30:443
|
||||
Starting the TLS handshake...
|
||||
TLS connection to developer.mbed.org established
|
||||
Server certificate:
|
||||
cert. version : 3
|
||||
serial number : 11:21:4E:4B:13:27:F0:89:21:FB:70:EC:3B:B5:73:5C:FF:B9
|
||||
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 : 2015-03-05 10:31:02
|
||||
expires on : 2016-03-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 473 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: Tue, 18 Aug 2015 18:34:04 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, 19 Aug 2015 04:34:04 GMT
|
||||
X-Upstream-L3: 172.17.42.1:8080
|
||||
X-Upstream-L2: developer-sjc-indigo-2-nginx
|
||||
X-Upstream-L1-next-hop: 217.140.101.86:8001
|
||||
X-Upstream-L1: developer-sjc-indigo-border-nginx
|
||||
|
||||
Hello world!
|
||||
{{success}}
|
||||
{{end}}
|
||||
```
|
||||
|
||||
## Debugging the TLS connection
|
||||
|
||||
If you are experiencing problems with this example, you should first rule out network issues by making sure the [simple HTTP file downloader example](https://github.com/ARMmbed/mbed-example-network-private/tree/master/test/helloworld-tcpclient) for the TCP module works as expected. If not, please follow the debug instructions for the HTTP file example before proceeding with the instructions below.
|
||||
|
||||
To print out more debug information about the TLS connection, edit the file `source/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.
|
||||
|
||||
|
||||
If the TLS connection is failing with an error similar to:
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
it 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 reason for this error may be 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, therefore use at your own risk, or for debugging only!
|
|
@ -1,520 +0,0 @@
|
|||
/*
|
||||
* Hello world example of a TLS client: fetch an HTTPS page
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(TARGET_LIKE_MBED)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("this program only works on mbed OS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/** \file main.cpp
|
||||
* \brief An example TLS Client application
|
||||
* This application sends an HTTPS request to developer.mbed.org and searches for a string in
|
||||
* the result.
|
||||
*
|
||||
* This example is implemented as a logic class (HelloHTTPS) wrapping a TCP socket.
|
||||
* The logic class handles all events, leaving the main loop to just check if the process
|
||||
* has finished.
|
||||
*/
|
||||
|
||||
/* Change to a number between 1 and 4 to debug the TLS connection */
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
/* Change to 1 to skip certificate verification (UNSAFE, for debug only!) */
|
||||
#define UNSAFE 0
|
||||
|
||||
#include "mbed.h"
|
||||
#include "EthernetInterface.h"
|
||||
#include "mbed-net-sockets/TCPStream.h"
|
||||
#include "test_env.h"
|
||||
#include "minar/minar.h"
|
||||
|
||||
#include "lwipv4_init.h"
|
||||
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#if DEBUG_LEVEL > 0
|
||||
#include "mbedtls/debug.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
const char *HTTPS_SERVER_NAME = "developer.mbed.org";
|
||||
const int HTTPS_SERVER_PORT = 443;
|
||||
const int RECV_BUFFER_SIZE = 600;
|
||||
|
||||
const char HTTPS_PATH[] = "/media/uploads/mbed_official/hello.txt";
|
||||
const size_t HTTPS_PATH_LEN = sizeof(HTTPS_PATH) - 1;
|
||||
|
||||
/* Test related data */
|
||||
const char *HTTPS_OK_STR = "200 OK";
|
||||
const char *HTTPS_HELLO_STR = "Hello world!";
|
||||
|
||||
/* personalization string for the drbg */
|
||||
const char *DRBG_PERS = "mbed TLS helloword client";
|
||||
|
||||
/* List of trusted root CA certificates
|
||||
* currently only GlobalSign, the CA for developer.mbed.org
|
||||
*
|
||||
* To add more than one root, just concatenate them.
|
||||
*/
|
||||
const char SSL_CA_PEM[] =
|
||||
/* GlobalSign Root R1 SHA1/RSA/2048
|
||||
* Serial no. 04 00 00 00 00 01 15 4b 5a c3 94 */
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n"
|
||||
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n"
|
||||
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n"
|
||||
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n"
|
||||
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n"
|
||||
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n"
|
||||
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n"
|
||||
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n"
|
||||
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n"
|
||||
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n"
|
||||
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n"
|
||||
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n"
|
||||
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n"
|
||||
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n"
|
||||
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n"
|
||||
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n"
|
||||
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n"
|
||||
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n"
|
||||
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
}
|
||||
|
||||
using namespace mbed::Sockets::v0;
|
||||
|
||||
/**
|
||||
* \brief HelloHTTPS implements the logic for fetching a file from a webserver
|
||||
* using a TCP socket and parsing the result.
|
||||
*/
|
||||
class HelloHTTPS {
|
||||
public:
|
||||
/**
|
||||
* HelloHTTPS Constructor
|
||||
* Initializes the TCP socket, sets up event handlers and flags.
|
||||
*
|
||||
* @param[in] domain The domain name to fetch from
|
||||
* @param[in] port The port of the HTTPS server
|
||||
*/
|
||||
HelloHTTPS(const char * domain, const uint16_t port) :
|
||||
_stream(SOCKET_STACK_LWIP_IPV4), _domain(domain), _port(port)
|
||||
{
|
||||
|
||||
_error = false;
|
||||
_gothello = false;
|
||||
_got200 = false;
|
||||
_bpos = 0;
|
||||
_request_sent = 0;
|
||||
_stream.open(SOCKET_AF_INET4);
|
||||
|
||||
mbedtls_entropy_init(&_entropy);
|
||||
mbedtls_ctr_drbg_init(&_ctr_drbg);
|
||||
mbedtls_x509_crt_init(&_cacert);
|
||||
mbedtls_ssl_init(&_ssl);
|
||||
mbedtls_ssl_config_init(&_ssl_conf);
|
||||
}
|
||||
/**
|
||||
* HelloHTTPS Desctructor
|
||||
*/
|
||||
~HelloHTTPS() {
|
||||
mbedtls_entropy_free(&_entropy);
|
||||
mbedtls_ctr_drbg_free(&_ctr_drbg);
|
||||
mbedtls_x509_crt_free(&_cacert);
|
||||
mbedtls_ssl_free(&_ssl);
|
||||
mbedtls_ssl_config_free(&_ssl_conf);
|
||||
}
|
||||
/**
|
||||
* Initiate the test.
|
||||
*
|
||||
* Starts by clearing test flags, then resolves the address with DNS.
|
||||
*
|
||||
* @param[in] path The path of the file to fetch from the HTTPS server
|
||||
* @return SOCKET_ERROR_NONE on success, or an error code on failure
|
||||
*/
|
||||
void startTest(const char *path) {
|
||||
/* Initialize the flags */
|
||||
_got200 = false;
|
||||
_gothello = false;
|
||||
_error = false;
|
||||
_disconnected = false;
|
||||
_request_sent = false;
|
||||
/* Fill the request buffer */
|
||||
_bpos = snprintf(_buffer, sizeof(_buffer) - 1, "GET %s HTTP/1.1\nHost: %s\n\n", path, HTTPS_SERVER_NAME);
|
||||
|
||||
/*
|
||||
* Initialize TLS-related stuf.
|
||||
*/
|
||||
int ret;
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
|
||||
(const unsigned char *) DRBG_PERS,
|
||||
sizeof (DRBG_PERS))) != 0) {
|
||||
print_mbedtls_error("mbedtls_crt_drbg_init", ret);
|
||||
_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *) SSL_CA_PEM,
|
||||
sizeof (SSL_CA_PEM))) != 0) {
|
||||
print_mbedtls_error("mbedtls_x509_crt_parse", ret);
|
||||
_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
print_mbedtls_error("mbedtls_ssl_config_defaults", ret);
|
||||
_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);
|
||||
mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
|
||||
|
||||
#if UNSAFE
|
||||
mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
#endif
|
||||
|
||||
#if DEBUG_LEVEL > 0
|
||||
mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL);
|
||||
mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
#endif
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) {
|
||||
print_mbedtls_error("mbedtls_ssl_setup", ret);
|
||||
_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_hostname(&_ssl, HTTPS_SERVER_NAME);
|
||||
|
||||
mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(&_stream),
|
||||
ssl_send, ssl_recv, NULL );
|
||||
|
||||
|
||||
/* Connect to the server */
|
||||
printf("Starting DNS lookup for %s\r\n", _domain);
|
||||
/* Resolve the domain name: */
|
||||
socket_error_t err = _stream.resolve(_domain, TCPStream::DNSHandler_t(this, &HelloHTTPS::onDNS));
|
||||
_stream.error_check(err);
|
||||
}
|
||||
/**
|
||||
* Check if the test has completed.
|
||||
* @return Returns true if done, false otherwise.
|
||||
*/
|
||||
bool done() {
|
||||
return _error || (_got200 && _gothello);
|
||||
}
|
||||
/**
|
||||
* Check if there was an error
|
||||
* @return Returns true if there was an error, false otherwise.
|
||||
*/
|
||||
bool error() {
|
||||
return _error;
|
||||
}
|
||||
/**
|
||||
* Closes the TCP socket
|
||||
*/
|
||||
void close() {
|
||||
_stream.close();
|
||||
while (!_disconnected)
|
||||
__WFI();
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* Helper for pretty-printing mbed TLS error codes
|
||||
*/
|
||||
static void print_mbedtls_error(const char *name, int err) {
|
||||
char buf[128];
|
||||
mbedtls_strerror(err, buf, sizeof (buf));
|
||||
printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf);
|
||||
}
|
||||
|
||||
#if DEBUG_LEVEL > 0
|
||||
/**
|
||||
* Debug callback for mbed TLS
|
||||
* Just prints on the USB serial port
|
||||
*/
|
||||
static void my_debug(void *ctx, int level, const char *file, int line,
|
||||
const char *str)
|
||||
{
|
||||
const char *p, *basename;
|
||||
(void) ctx;
|
||||
|
||||
/* Extract basename from file */
|
||||
for(p = basename = file; *p != '\0'; p++) {
|
||||
if(*p == '/' || *p == '\\') {
|
||||
basename = p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s:%04d: |%d| %s", basename, line, level, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Certificate verification callback for mbed TLS
|
||||
* Here we only use it to display information on each cert in the chain
|
||||
*/
|
||||
static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
char buf[1024];
|
||||
(void) data;
|
||||
|
||||
printf("\nVerifying certificate at depth %d:\n", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof (buf) - 1, " ", crt);
|
||||
printf("%s", buf);
|
||||
|
||||
if (*flags == 0)
|
||||
printf("No verification issue for this certificate\n");
|
||||
else
|
||||
{
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof (buf), " ! ", *flags);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Receive callback for mbed TLS
|
||||
*/
|
||||
static int ssl_recv(void *ctx, unsigned char *buf, size_t len) {
|
||||
TCPStream *stream = static_cast<TCPStream *>(ctx);
|
||||
socket_error_t err = stream->recv(buf, &len);
|
||||
|
||||
if (err == SOCKET_ERROR_NONE) {
|
||||
return static_cast<int>(len);
|
||||
} else if (err == SOCKET_ERROR_WOULD_BLOCK) {
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send callback for mbed TLS
|
||||
*/
|
||||
static int ssl_send(void *ctx, const unsigned char *buf, size_t len) {
|
||||
TCPStream *stream = static_cast<TCPStream *>(ctx);
|
||||
|
||||
socket_error_t err = stream->send(buf, len);
|
||||
|
||||
if (err == SOCKET_ERROR_NONE) {
|
||||
return static_cast<int>(len);
|
||||
} else if (err == SOCKET_ERROR_WOULD_BLOCK) {
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void onError(Socket *s, socket_error_t err) {
|
||||
(void) s;
|
||||
printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err);
|
||||
_stream.close();
|
||||
_error = true;
|
||||
MBED_HOSTTEST_RESULT(false);
|
||||
}
|
||||
/**
|
||||
* On Connect handler
|
||||
* Starts the TLS handshake
|
||||
*/
|
||||
void onConnect(TCPStream *s) {
|
||||
char buf[16];
|
||||
_remoteAddr.fmtIPv4(buf,sizeof(buf));
|
||||
printf("Connected to %s:%d\r\n", buf, _port);
|
||||
|
||||
s->setOnReadable(TCPStream::ReadableHandler_t(this, &HelloHTTPS::onReceive));
|
||||
s->setOnDisconnect(TCPStream::DisconnectHandler_t(this, &HelloHTTPS::onDisconnect));
|
||||
|
||||
/* Start the handshake, the rest will be done in onReceive() */
|
||||
printf("Starting the TLS handshake...\r\n");
|
||||
int ret = mbedtls_ssl_handshake(&_ssl);
|
||||
if (ret < 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
print_mbedtls_error("mbedtls_ssl_handshake", ret);
|
||||
onError(s, SOCKET_ERROR_UNKNOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* On Receive handler
|
||||
* Parses the response from the server, to check for the HTTPS 200 status code and the expected response ("Hello World!")
|
||||
*/
|
||||
void onReceive(Socket *s) {
|
||||
/* Send request if not done yet */
|
||||
if (!_request_sent) {
|
||||
int ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) _buffer, _bpos);
|
||||
if (ret < 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
print_mbedtls_error("mbedtls_ssl_write", ret);
|
||||
onError(s, SOCKET_ERROR_UNKNOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we get here, the request was sent */
|
||||
_request_sent = 1;
|
||||
|
||||
/* It also means the handshake is done, time to print info */
|
||||
printf("TLS connection to %s established\r\n", HTTPS_SERVER_NAME);
|
||||
{
|
||||
char buf[1024];
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf), "\r ",
|
||||
mbedtls_ssl_get_peer_cert(&_ssl));
|
||||
printf("Server certificate:\r\n%s\r", buf);
|
||||
|
||||
#if defined(UNSAFE)
|
||||
uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl);
|
||||
if( flags != 0 )
|
||||
{
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof (buf), "\r ! ", flags);
|
||||
printf("Certificate verification failed:\r\n%s\r\r\n", buf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
printf("Certificate verification passed\r\n\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data out of the socket */
|
||||
int ret = mbedtls_ssl_read(&_ssl, (unsigned char *) _buffer, sizeof(_buffer));
|
||||
if (ret < 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
print_mbedtls_error("mbedtls_ssl_read", ret);
|
||||
onError(s, SOCKET_ERROR_UNKNOWN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
_bpos = static_cast<size_t>(ret);
|
||||
|
||||
_buffer[_bpos] = 0;
|
||||
|
||||
/* Check each of the flags */
|
||||
_got200 = _got200 || strstr(_buffer, HTTPS_OK_STR) != NULL;
|
||||
_gothello = _gothello || strstr(_buffer, HTTPS_HELLO_STR) != NULL;
|
||||
|
||||
/* Print status messages */
|
||||
printf("HTTPS: Received %d chars from server\r\n", _bpos);
|
||||
printf("HTTPS: Received 200 OK status ... %s\r\n", _got200 ? "[OK]" : "[FAIL]");
|
||||
printf("HTTPS: Received '%s' status ... %s\r\n", HTTPS_HELLO_STR, _gothello ? "[OK]" : "[FAIL]");
|
||||
printf("HTTPS: Received message:\r\n\r\n");
|
||||
printf("%s", _buffer);
|
||||
_error = !(_got200 && _gothello);
|
||||
|
||||
s->close();
|
||||
}
|
||||
/**
|
||||
* On DNS Handler
|
||||
* Reads the address returned by DNS, then starts the connect process.
|
||||
*/
|
||||
void onDNS(Socket *s, struct socket_addr addr, const char *domain) {
|
||||
/* Check that the result is a valid DNS response */
|
||||
if (socket_addr_is_any(&addr)) {
|
||||
/* Could not find DNS entry */
|
||||
printf("Could not find DNS entry for %s", HTTPS_SERVER_NAME);
|
||||
onError(s, SOCKET_ERROR_DNS_FAILED);
|
||||
} else {
|
||||
/* Start connecting to the remote host */
|
||||
char buf[16];
|
||||
_remoteAddr.setAddr(&addr);
|
||||
_remoteAddr.fmtIPv4(buf,sizeof(buf));
|
||||
printf("DNS Response Received:\r\n%s: %s\r\n", domain, buf);
|
||||
printf("Connecting to %s:%d\r\n", buf, _port);
|
||||
socket_error_t err = _stream.connect(_remoteAddr, _port, TCPStream::ConnectHandler_t(this, &HelloHTTPS::onConnect));
|
||||
|
||||
if (err != SOCKET_ERROR_NONE) {
|
||||
onError(s, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
void onDisconnect(TCPStream *s) {
|
||||
s->close();
|
||||
MBED_HOSTTEST_RESULT(!error());
|
||||
}
|
||||
|
||||
protected:
|
||||
TCPStream _stream; /**< The TCP Socket */
|
||||
const char *_domain; /**< The domain name of the HTTPS server */
|
||||
const uint16_t _port; /**< The HTTPS server port */
|
||||
char _buffer[RECV_BUFFER_SIZE]; /**< The response buffer */
|
||||
size_t _bpos; /**< The current offset in the response buffer */
|
||||
SocketAddr _remoteAddr; /**< The remote address */
|
||||
volatile bool _got200; /**< Status flag for HTTPS 200 */
|
||||
volatile bool _gothello; /**< Status flag for finding the test string */
|
||||
volatile bool _error; /**< Status flag for an error */
|
||||
volatile bool _disconnected;
|
||||
volatile bool _request_sent;
|
||||
|
||||
mbedtls_entropy_context _entropy;
|
||||
mbedtls_ctr_drbg_context _ctr_drbg;
|
||||
mbedtls_x509_crt _cacert;
|
||||
mbedtls_ssl_context _ssl;
|
||||
mbedtls_ssl_config _ssl_conf;
|
||||
};
|
||||
|
||||
/**
|
||||
* The main loop of the HTTPS Hello World test
|
||||
*/
|
||||
EthernetInterface eth;
|
||||
HelloHTTPS *hello;
|
||||
|
||||
void app_start(int, char*[]) {
|
||||
/* The default 9600 bps is too slow to print full TLS debug info and could
|
||||
* cause the other party to time out. Select a higher baud rate for
|
||||
* printf(), regardless of debug level for the sake of uniformity. */
|
||||
Serial pc(USBTX, USBRX);
|
||||
pc.baud(115200);
|
||||
|
||||
MBED_HOSTTEST_TIMEOUT(120);
|
||||
MBED_HOSTTEST_SELECT(default);
|
||||
MBED_HOSTTEST_DESCRIPTION(mbed TLS example HTTPS client);
|
||||
MBED_HOSTTEST_START("MBEDTLS_EX_HTTPS_CLIENT");
|
||||
|
||||
/* Initialise with DHCP, connect, and start up the stack */
|
||||
eth.init();
|
||||
eth.connect();
|
||||
lwipv4_socket_init();
|
||||
|
||||
hello = new HelloHTTPS(HTTPS_SERVER_NAME, HTTPS_SERVER_PORT);
|
||||
|
||||
printf("Client IP Address is %s\r\n", eth.getIPAddress());
|
||||
|
||||
mbed::util::FunctionPointer1<void, const char*> fp(hello, &HelloHTTPS::startTest);
|
||||
minar::Scheduler::postCallback(fp.bind(HTTPS_PATH));
|
||||
}
|
||||
|
||||
#endif /* TARGET_LIKE_MBED */
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mbedtls",
|
||||
"version": "2.1.3",
|
||||
"version": "2.1.4",
|
||||
"description": "The mbed TLS crypto/SSL/TLS library",
|
||||
"licenses": [
|
||||
{
|
||||
|
@ -10,9 +10,9 @@
|
|||
],
|
||||
"dependencies": {},
|
||||
"targetDependencies": {
|
||||
"mbed": { "cmsis-core": "~0.2.3" }
|
||||
"mbed": { "cmsis-core": "^1.0.0" }
|
||||
},
|
||||
"testTargetDependencies": {
|
||||
"mbed": { "sockets": "~0.5.0" }
|
||||
"mbed": { "mbed-drivers": "~0.11.0" }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue