From 63e7ebaaa184f08bf7d2043bd6dbdc7b61c43f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 Jul 2015 14:17:48 +0200 Subject: [PATCH] Add material for generating yotta module --- include/mbedtls/check_config.h | 5 + scripts/bump_version.sh | 4 + yotta/.gitignore | 1 + yotta/create-module.sh | 66 ++ yotta/data/README.md | 39 + yotta/data/adjust-config.sh | 72 ++ yotta/data/entropy_hardware_poll.c | 52 ++ yotta/data/example-authcrypt/README.md | 70 ++ yotta/data/example-authcrypt/main.cpp | 177 +++++ yotta/data/example-benchmark/README.md | 96 +++ yotta/data/example-benchmark/main.cpp | 931 ++++++++++++++++++++++++ yotta/data/example-hashing/README.md | 69 ++ yotta/data/example-hashing/main.cpp | 157 ++++ yotta/data/example-selftest/README.md | 88 +++ yotta/data/example-selftest/main.cpp | 248 +++++++ yotta/data/example-tls-client/README.md | 131 ++++ yotta/data/example-tls-client/main.cpp | 489 +++++++++++++ yotta/data/module.json | 13 + yotta/data/target_config.h | 22 + 19 files changed, 2730 insertions(+) create mode 100644 yotta/.gitignore create mode 100755 yotta/create-module.sh create mode 100644 yotta/data/README.md create mode 100755 yotta/data/adjust-config.sh create mode 100644 yotta/data/entropy_hardware_poll.c create mode 100644 yotta/data/example-authcrypt/README.md create mode 100644 yotta/data/example-authcrypt/main.cpp create mode 100644 yotta/data/example-benchmark/README.md create mode 100644 yotta/data/example-benchmark/main.cpp create mode 100644 yotta/data/example-hashing/README.md create mode 100644 yotta/data/example-hashing/main.cpp create mode 100644 yotta/data/example-selftest/README.md create mode 100644 yotta/data/example-selftest/main.cpp create mode 100644 yotta/data/example-tls-client/README.md create mode 100644 yotta/data/example-tls-client/main.cpp create mode 100644 yotta/data/module.json create mode 100644 yotta/data/target_config.h diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 21a5d4a0f..e2569eb28 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -52,6 +52,11 @@ #endif #endif /* _WIN32 */ +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + #if defined(MBEDTLS_DEPRECATED_WARNING) && \ !defined(__GNUC__) && !defined(__clang__) #error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" diff --git a/scripts/bump_version.sh b/scripts/bump_version.sh index 8e7710533..4d08864ef 100755 --- a/scripts/bump_version.sh +++ b/scripts/bump_version.sh @@ -109,6 +109,10 @@ mv tmp include/mbedtls/version.h sed -e "s/version:\".\{1,\}/version:\"$VERSION\"/g" < tests/suites/test_suite_version.data > tmp mv tmp tests/suites/test_suite_version.data +[ $VERBOSE ] && echo "Bumping version in yotta/data/module.json" +sed -e "s/\"version\": \".\{1,\}\"/version: \"$VERSION\"/g" < yotta/data/module.json > tmp +mv tmp yotta/data/module.json + [ $VERBOSE ] && echo "Bumping PROJECT_NAME in doxygen/mbedtls.doxyfile and doxygen/input/doc_mainpage.h" for i in doxygen/mbedtls.doxyfile doxygen/input/doc_mainpage.h; do diff --git a/yotta/.gitignore b/yotta/.gitignore new file mode 100644 index 000000000..0cca093d7 --- /dev/null +++ b/yotta/.gitignore @@ -0,0 +1 @@ +module diff --git a/yotta/create-module.sh b/yotta/create-module.sh new file mode 100755 index 000000000..73dc92521 --- /dev/null +++ b/yotta/create-module.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +set -eu + +TREE=.. + +# default values, can be overriden by the environment +: ${DEST:=module} +: ${BUILD:=1} + +# make sure we're running in our own directory +if [ -f create-module.sh ]; then :; else + cd $( dirname $0 ) + if [ -f create-module.sh ]; then :; else + echo "Please run the script from is directory." >&2 + exit 1 + fi +fi + +# use a temporary directory to build the module, then rsync to DEST +# this allows touching only new files, for more efficient re-builds +TMP=$DEST-tmp +rm -rf $TMP + +mkdir -p $TMP/mbedtls $TMP/source +cp $TREE/include/mbedtls/*.h $TMP/mbedtls +cp $TREE/library/*.c $TMP/source + +# temporary, should depend on external module later +cp data/entropy_hardware_poll.c $TMP/source +cp data/target_config.h $TMP/mbedtls + +data/adjust-config.sh $TREE/scripts/config.pl $TMP/mbedtls/config.h + +mkdir -p $TMP/test +cp -r data/example-* $TMP/test +# later we should have the generated test suites here too + +cp data/module.json $TMP +cp data/README.md $TMP + +mkdir -p $DEST +rsync -cr --delete --exclude build --exclude yotta_\* $TMP/ $DEST/ +rm -rf $TMP + +echo "mbed TLS yotta module created in '$DEST'." + +test_build() +{ + TARGET=$1 + echo; echo "*** Doing a test build for $TARGET ***" + ( cd $DEST && yt target $TARGET && yt build ) +} + +if [ $BUILD -eq 1 ]; then + if uname -a | grep 'Linux.*x86' >/dev/null; then + test_build x86-linux-native + fi + + if uname -a | grep 'Darwin.*x86' >/dev/null; then + test_build x86-osx-native + fi + + # do that one last so that it remains the target + test_build frdm-k64f-gcc +fi diff --git a/yotta/data/README.md b/yotta/data/README.md new file mode 100644 index 000000000..e126c2067 --- /dev/null +++ b/yotta/data/README.md @@ -0,0 +1,39 @@ +# mbed TLS + +mbed TLS (formerly known as PolarSSL) makes it trivially easy for developers to include cryptographic and SSL/TLS capabilities in their (embedded) products, facilitating this functionality with a minimal coding footprint. It offers an SSL library with an intuitive API and readable source code. + +The Beta release of mbed TLS is an integration of TLS, mbed SDK and yotta. It is a testing preview only and **not suitable for deployment**: there is currently no source of random numbers, meaning no security at all for (D)TLS communication and other protocols that rely on random numbers. + +## Sample programs + +This release includes the following examples: + +1. [**TLS client:**](https://github.com/ARMmbed/mbedtls/tree/master/yotta/data/example-tls-client) downloads a file from an HTTPS server (mbed.org) and looks for a specific string in that file. + +2. [**Self test:**](https://github.com/ARMmbed/mbedtls/tree/master/yotta/data/example-selftest) tests different mbed TLS base functionalities. + +3. [**Benchmark:**](https://github.com/ARMmbed/mbedtls/tree/master/yotta/data/example-benchmark) tests the time required to perform TLS base crypto functions. + +These examples are integrated as yotta tests so that they are build automatically when you build mbed TLS. You'll find other examples in the various `tests/example-*` directories. + +## Running TLS + +Please follow the instructions in the [TLS client sample](https://github.com/ARMmbed/mbedtls/tree/master/yotta/data/example-tls-client). These include a list of prerequisites and an explanation of building mbed TLS with yotta. + +## Contributing + +We graciously accept bugs and contributions from the community. There are some requirements we need to fulfil in order to be able to integrate contributions in the main code: + +* Simple bug fixes to existing code do not contain copyright themselves and we can integrate those without any issue. The same goes for trivial contributions. + +* For larger contributions, e.g. a new feature, the code possibly falls under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for that, which we will mail to you in case you submit a contribution or pull request that we deem this necessary for. + +To contribute, please: + +* [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug. + +* Fork the [mbed TLS repository on Github](https://github.com/ARMmbed/mbedtls) to start making your changes. + +* Write a test that shows that the bug was fixed or that the feature works as expected. + +* Send a pull request and bug us until it gets merged and published. We will include your name in the ChangeLog :) diff --git a/yotta/data/adjust-config.sh b/yotta/data/adjust-config.sh new file mode 100755 index 000000000..955fe0d22 --- /dev/null +++ b/yotta/data/adjust-config.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +set -eu + +if [ $# -ne 2 ]; then + echo "Usage: $0 path/to/config.pl path/to/config.h" >&2 + exit 1 +fi + +SCRIPT=$1 +FILE=$2 + +conf() { + $SCRIPT -f $FILE $@ +} + +conf unset MBEDTLS_NET_C +conf unset MBEDTLS_TIMING_C + +conf unset MBEDTLS_CIPHER_MODE_CFB +conf unset MBEDTLS_CIPHER_MODE_CTR +conf unset MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +conf unset MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +conf unset MBEDTLS_CIPHER_PADDING_ZEROS +conf unset MBEDTLS_ECP_DP_SECP192R1_ENABLED +conf unset MBEDTLS_ECP_DP_SECP224R1_ENABLED +conf unset MBEDTLS_ECP_DP_SECP521R1_ENABLED +conf unset MBEDTLS_ECP_DP_SECP192K1_ENABLED +conf unset MBEDTLS_ECP_DP_SECP224K1_ENABLED +conf unset MBEDTLS_ECP_DP_SECP256K1_ENABLED +conf unset MBEDTLS_ECP_DP_BP256R1_ENABLED +conf unset MBEDTLS_ECP_DP_BP384R1_ENABLED +conf unset MBEDTLS_ECP_DP_BP512R1_ENABLED +conf unset MBEDTLS_PK_PARSE_EC_EXTENDED + +conf unset MBEDTLS_AESNI_C +conf unset MBEDTLS_ARC4_C +conf unset MBEDTLS_BLOWFISH_C +conf unset MBEDTLS_CAMELLIA_C +conf unset MBEDTLS_DES_C +conf unset MBEDTLS_DHM_C +conf unset MBEDTLS_GENPRIME +conf unset MBEDTLS_MD5_C +conf unset MBEDTLS_PADLOCK_C +conf unset MBEDTLS_PEM_WRITE_C +conf unset MBEDTLS_PKCS5_C +conf unset MBEDTLS_PKCS12_C +conf unset MBEDTLS_RIPEMD160_C +#conf unset MBEDTLS_SHA1_C +conf unset MBEDTLS_XTEA_C + +conf unset MBEDTLS_X509_RSASSA_PSS_SUPPORT + +conf unset MBEDTLS_X509_CSR_PARSE_C +conf unset MBEDTLS_X509_CREATE_C +conf unset MBEDTLS_X509_CRT_WRITE_C +conf unset MBEDTLS_X509_CSR_WRITE_C + +conf unset MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +conf unset MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +conf unset MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +conf unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +conf unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +conf unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +conf unset MBEDTLS_SSL_FALLBACK_SCSV +conf unset MBEDTLS_SSL_CBC_RECORD_SPLITTING +conf unset MBEDTLS_SSL_PROTO_SSL3 +conf unset MBEDTLS_SSL_PROTO_TLS1 +conf unset MBEDTLS_SSL_PROTO_TLS1_1 +conf unset MBEDTLS_SSL_TRUNCATED_HMAC + +perl -pi -e 's/#include "check_config.h"/#include "target_config.h"\n$&/' $FILE diff --git a/yotta/data/entropy_hardware_poll.c b/yotta/data/entropy_hardware_poll.c new file mode 100644 index 000000000..54e96c211 --- /dev/null +++ b/yotta/data/entropy_hardware_poll.c @@ -0,0 +1,52 @@ +/* + * Temporary "entropy" collector for Cortex-M4 + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * WARNING: this is a temporary hack! + * 1. Currently does not provide strong entropy, should be replaced to use the + * on-board hardware RNG (see IOTSSL-303) + * 2. This should be in a separete yotta module which would be a target + * dependency of mbedtls (see IOTSSL-313) + */ + +#if defined(TARGET_LIKE_CORTEX_M4) + +#include "MK64F12.h" +#include "core_cm4.h" +#include + +unsigned long hardclock( void ) +{ + static int dwt_started = 0; + + if( dwt_started == 0 ) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + return( DWT->CYCCNT ); +} + +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} + +#endif diff --git a/yotta/data/example-authcrypt/README.md b/yotta/data/example-authcrypt/README.md new file mode 100644 index 000000000..8bb847069 --- /dev/null +++ b/yotta/data/example-authcrypt/README.md @@ -0,0 +1,70 @@ +# Authenticated encryption example + +This application performs authenticated encryption and authenticated decryption of a buffer. It serves as a tutorial for the basic authenticated encryption functions of mbed TLS. + +## Pre-requisites + +To build and run this example the requirements below are necessary: + +* 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/). + * [ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded). + * A serial terminal emulator (e.g. screen, pySerial, cu). +* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in that case you'll have to substitute frdm-k64f-gcc with the appropriate target below). +* A micro-USB 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 computer with the micro-USB cable, being careful to use the micro-usb port labeled "OpenSDA". + +2. Navigate to the mbedtls directory supplied with your release and open a terminal. + +3. Set the yotta target: + + ``` + yotta target frdm-k64f-gcc + ``` + +4. Check that there are no missing dependencies: + + ``` + $ yt ls + ``` + + If there are, yotta will list them in the terminal. Please install them before proceeding. + +5. Build mbedtls and the examples. This will take a long time if it is the first time: + + ``` + $ yt build + ``` + +6. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-authcrypt.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. For settings, use 9600 baud, 8N1, no flow control. + +8. Press the reset button on the board. + +9. The output in the terminal window should look like: + + ``` + {{timeout;10}} + {{host_test_name;default}} + {{description;mbed TLS example authcrypt}} + {{test_id;MBEDTLS_EX_AUTHCRYPT}} + {{start}} + + + plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400 + ciphertext: c57f7afb94f14c7977d785d08682a2596bd62ee9dcf216b8cccd997afee9b402f5de1739e8e6467aa363749ef39392e5c66622b01c7203ec0a3d14 + decrypted: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400 + + DONE + {{success}} + {{end}} + ``` + +The actual output for the ciphertext line will vary on each run due to the use of a random nonce in the encryption process. diff --git a/yotta/data/example-authcrypt/main.cpp b/yotta/data/example-authcrypt/main.cpp new file mode 100644 index 000000000..0c7b9b14b --- /dev/null +++ b/yotta/data/example-authcrypt/main.cpp @@ -0,0 +1,177 @@ +/* + * Hello world example of using the authenticated encryption with mbed TLS + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include "mbedtls/cipher.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include + +static void print_hex(const char *title, const unsigned char buf[], size_t len) +{ + printf("%s: ", title); + + for (size_t i = 0; i < len; i++) + printf("%02x", buf[i]); + + printf("\r\n"); +} + +/* + * The pre-shared key. Should be generated randomly and be unique to the + * device/channel/etc. Just used a fixed on here for simplicity. + */ +static const unsigned char secret_key[16] = { + 0xf4, 0x82, 0xc6, 0x70, 0x3c, 0xc7, 0x61, 0x0a, + 0xb9, 0xa0, 0xb8, 0xe9, 0x87, 0xb8, 0xc1, 0x72, +}; + +static int example(void) +{ + /* message that should be protected */ + const char message[] = "Some things are better left unread"; + /* metadata transmitted in the clear but authenticated */ + const char metadata[] = "eg sequence number, routing info"; + /* ciphertext buffer large enough to hold message + nonce + tag */ + unsigned char ciphertext[128] = { 0 }; + int ret; + + printf("\r\n\r\n"); + print_hex("plaintext message", (unsigned char *) message, sizeof message); + + /* + * Setup random number generator + * (Note: later this might be done automatically.) + */ + mbedtls_entropy_context entropy; /* entropy pool for seeding PRNG */ + mbedtls_ctr_drbg_context drbg; /* pseudo-random generator */ + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&drbg); + + /* Seed the PRNG using the entropy pool, and throw in our secret key as an + * additional source of randomness. */ + ret = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy, + secret_key, sizeof (secret_key)); + if (ret != 0) { + printf("mbedtls_ctr_drbg_init() returned -0x%04X\r\n", -ret); + return 1; + } + + /* + * Setup AES-CCM contex + */ + mbedtls_cipher_context_t ctx; + + mbedtls_cipher_init(&ctx); + + ret = mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CCM)); + if (ret != 0) { + printf("mbedtls_cipher_setup() returned -0x%04X\r\n", -ret); + return 1; + } + + ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_ENCRYPT); + if (ret != 0) { + printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret); + return 1; + } + + /* + * Encrypt-authenticate the message and authenticate additional data + * + * First generate a random 8-byte nonce. + * Put it directly in the output buffer as the recipient will need it. + * + * Warning: you must never re-use the same (key, nonce) pair. One of the + * best ways to ensure this to use a counter for the nonce. However this + * means you should save the counter accross rebots, if the key is a + * long-term one. The alternative we choose here is to generate the nonce + * randomly. However it only works if you have a good source of + * randomness. + */ + const size_t nonce_len = 8; + mbedtls_ctr_drbg_random(&drbg, ciphertext, nonce_len); + + size_t ciphertext_len = 0; + /* Go for a conservative 16-byte (128-bit) tag + * and append it to the ciphertext */ + const size_t tag_len = 16; + ret = mbedtls_cipher_auth_encrypt(&ctx, ciphertext, nonce_len, + (const unsigned char *) metadata, sizeof metadata, + (const unsigned char *) message, sizeof message, + ciphertext + nonce_len, &ciphertext_len, + ciphertext + nonce_len + sizeof message, tag_len ); + if (ret != 0) { + printf("mbedtls_cipher_auth_encrypt() returned -0x%04X\r\n", -ret); + return 1; + } + ciphertext_len += nonce_len + tag_len; + + /* + * The following information should now be transmitted: + * - first ciphertext_len bytes of ciphertext buffer + * - metadata if not already transmitted elsewhere + */ + print_hex("ciphertext", ciphertext, ciphertext_len); + + /* + * Decrypt-authenticate + */ + unsigned char decrypted[128] = { 0 }; + size_t decrypted_len = 0; + + ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_DECRYPT); + if (ret != 0) { + printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret); + return 1; + } + + ret = mbedtls_cipher_auth_decrypt(&ctx, + ciphertext, nonce_len, + (const unsigned char *) metadata, sizeof metadata, + ciphertext + nonce_len, ciphertext_len - nonce_len - tag_len, + decrypted, &decrypted_len, + ciphertext + ciphertext_len - tag_len, tag_len ); + /* Checking the return code is CRITICAL for security here */ + if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { + printf("Something bad is happening! Data is not authentic!\r\n"); + return 1; + } + if (ret != 0) { + printf("mbedtls_cipher_authdecrypt() returned -0x%04X\r\n", -ret); + return 1; + } + + print_hex("decrypted", decrypted, decrypted_len); + + printf("\r\nDONE\r\n"); + + return 0; +} + +#if defined(TARGET_LIKE_MBED) + +#include "mbed/test_env.h" + +int main() { + MBED_HOSTTEST_TIMEOUT(10); + MBED_HOSTTEST_SELECT(default); + MBED_HOSTTEST_DESCRIPTION(mbed TLS example authcrypt); + MBED_HOSTTEST_START("MBEDTLS_EX_AUTHCRYPT"); + MBED_HOSTTEST_RESULT(example() == 0); +} + +#else + +int main() { + return example(); +} + +#endif diff --git a/yotta/data/example-benchmark/README.md b/yotta/data/example-benchmark/README.md new file mode 100644 index 000000000..e0800ebdb --- /dev/null +++ b/yotta/data/example-benchmark/README.md @@ -0,0 +1,96 @@ +# mbed TLS benchmark + +This application benchmarks the various cryptographic primitives offered by mbed TLS. + +## Pre-requisites + +To build and run this example the requirements below are necessary: + +* 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/). + * [ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded). + * A serial terminal emulator (e.g. screen, pySerial, cu). +* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in that case you'll have to substitute frdm-k64f-gcc with the appropriate target below). +* A micro-USB 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 computer with the micro-USB cable, being careful to use the micro-usb port labeled "OpenSDA". + +2. Navigate to the mbedtls directory supplied with your release and open a terminal. + +3. Set the yotta target: + + ``` + yotta target frdm-k64f-gcc + ``` + +4. Check that there are no missing dependencies: + + ``` + $ yt ls + ``` + + If there are, yotta will list them in the terminal. Please install them before proceeding. + +5. Build mbedtls and the examples. This will take a long time if it is the first time: + + ``` + $ yt build + ``` + +6. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-benchmark.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. For settings, use 9600 baud, 8N1, no flow control. + +8. Press the reset button on the board. + +9. The output in the terminal window should look like: + + ``` + {{timeout;150}} + {{host_test_name;default}} + {{description;mbed TLS benchmark program}} + {{test_id;MBEDTLS_BENCHMARK}} + {{start}} + + + SHA-1 : 3644 Kb/s, 32 cycles/byte + SHA-256 : 1957 Kb/s, 59 cycles/byte + SHA-512 : 587 Kb/s, 200 cycles/byte + AES-CBC-128 : 1359 Kb/s, 86 cycles/byte + AES-CBC-192 : 1183 Kb/s, 99 cycles/byte + AES-CBC-256 : 1048 Kb/s, 111 cycles/byte + AES-GCM-128 : 421 Kb/s, 279 cycles/byte + AES-GCM-192 : 403 Kb/s, 292 cycles/byte + AES-GCM-256 : 385 Kb/s, 305 cycles/byte + AES-CCM-128 : 542 Kb/s, 216 cycles/byte + AES-CCM-192 : 484 Kb/s, 242 cycles/byte + AES-CCM-256 : 437 Kb/s, 268 cycles/byte + CTR_DRBG (NOPR) : 1002 Kb/s, 117 cycles/byte + CTR_DRBG (PR) : 705 Kb/s, 166 cycles/byte + HMAC_DRBG SHA-1 (NOPR) : 228 Kb/s, 517 cycles/byte + HMAC_DRBG SHA-1 (PR) : 210 Kb/s, 561 cycles/byte + HMAC_DRBG SHA-256 (NOPR) : 212 Kb/s, 557 cycles/byte + HMAC_DRBG SHA-256 (PR) : 185 Kb/s, 637 cycles/byte + RSA-2048 : 41 ms/ public + RSA-2048 : 1349 ms/private + RSA-4096 : 134 ms/ public + RSA-4096 : 7149 ms/private + ECDSA-secp384r1 : 640 ms/sign + ECDSA-secp256r1 : 387 ms/sign + ECDSA-secp384r1 : 1233 ms/verify + ECDSA-secp256r1 : 751 ms/verify + ECDHE-secp384r1 : 1191 ms/handshake + ECDHE-secp256r1 : 730 ms/handshake + ECDHE-Curve25519 : 611 ms/handshake + ECDH-secp384r1 : 584 ms/handshake + ECDH-secp256r1 : 365 ms/handshake + ECDH-Curve25519 : 303 ms/handshake + + {{success}} + {{end}} + ``` diff --git a/yotta/data/example-benchmark/main.cpp b/yotta/data/example-benchmark/main.cpp new file mode 100644 index 000000000..fabaef9db --- /dev/null +++ b/yotta/data/example-benchmark/main.cpp @@ -0,0 +1,931 @@ +/* + * Benchmark demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(TARGET_LIKE_MBED) + +#include + +int main() { + printf("this version of this program only works on mbed OS\n"); + return 0; +} + +#else + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_exit exit +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#define mbedtls_free free +#endif + +#include + +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/arc4.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/blowfish.h" +#include "mbedtls/camellia.h" +#include "mbedtls/gcm.h" +#include "mbedtls/ccm.h" +#include "mbedtls/havege.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/rsa.h" +#include "mbedtls/pk.h" +#include "mbedtls/dhm.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/error.h" + +#include "mbed.h" + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +#endif + +#define RSA_PRIVATE_KEY_2048 \ +"-----BEGIN RSA PRIVATE KEY-----\r\n" \ +"MIIEogIBAAKCAQEA2dwVr+IMGEtA2/MCP6fA5eb/6B18Bq6e7gw8brNPkm3E6LyR\r\n" \ +"4DnMJVxZmw3bPDKBDoKzfntkMESi/Yw5UopLtVfjGfWeQWPClqffLZBsZ60BRAsg\r\n" \ +"/g+ID5tgzxSuxzftypK59uexOVCAm7hCKZHGO3DbI7bLY27j7VAgEP7d/yuaz5Fx\r\n" \ +"Kl/vu7shqrBoz6ABJVJD3KC8nUiMRUCXRINmxbyUUjA4DnicZv6+xrGKr36r6M8h\r\n" \ +"VYLa5msKc8WzbnBWzpUsrpb4/r7ML+qp92gdSfVJ8/bLiU7h2C7faDA59uaqrFK9\r\n" \ +"xmDdx7FaWhGQs3LWW6w1UNgkPS0FDYUslpsnsQIDAQABAoIBAC7IJNwM5V3+IuJY\r\n" \ +"T35Nzo1PyloUosJokvY5KGz5Ejg2XBdCDu0gXCcVqqQyGIbXrYDpLhQV+RCoXHun\r\n" \ +"tdN0oQdC5SB47s/J1Uo2qCUHo0+sBd6PqTkFKsl3KxWssk9TQjvCwC412IefMs69\r\n" \ +"hW+ZvwCanmQP56LleApIr2oW4KLfW8Ry/QfZlua+dizctdN7+H1mWwgZQTY9T27J\r\n" \ +"6RtGRA5NVkKVPzIHVJfdpKoO7xGg1g06aEbPB/VmGvZaaFWWnaf7uRvFjLZecBLu\r\n" \ +"QSx2DA/GDjirlDYj99PJb7DtB4xRtKzsyw0o+xapC8w6OtIl/3xFt9moCu2jGrsx\r\n" \ +"vpjHdfECgYEA7fSACRseIs9gAIVX8wq6gayTpA47DHYWAD6IQfIj35SJ+AgsvbFF\r\n" \ +"4AmrwDhcJVPmDy1N4nLBfyGAMt/2CfiYkdkW6QFX/ULRMMBL/G7kWV8hYQDICB2g\r\n" \ +"xaMRN1lPCmFq6BkSWjwIYTnYDFBDWVm1GVT8TMtJoM8Erej9qC0PeFUCgYEA6mF3\r\n" \ +"bigO3t8f5sig+XepaftEUbkJMzo72TVRnIR2ycdR2ihelPQ+25g9dwV0ZA5XXhBS\r\n" \ +"DKOABWjMM739Mwmy9v26Dlmu9R01zHQktMvtEAyfz7lk2NF0aMuj8285OJUBf9bz\r\n" \ +"Cq3MjtMCD+4CZ6iaEqCdUKOuxfpx5cWVJV+qve0CgYBhD1YaYMFOGaBjFgDl1f51\r\n" \ +"Xltqk5NqZdBbkSYrIAWZ8RDF5y+4wFJsLAWuhk6vuyUgE66tK3nZzWRpXAkT0B8L\r\n" \ +"fq1lpXKqj1KcvBNCiEkEW1VWJ+dvyAYIF5eyJ++hoFLnETL3M32HivyhKSwPihPg\r\n" \ +"nVW8TT9fJJIYDe1JZ/fjcQKBgHJfv7UsrR0LSvkG3K8AOtbx+8PZhOjPuRbk0v+L\r\n" \ +"EKCkuIe5/XW4vtfQMeZb7hFJgk7vrepm+vkoy8VQKDf4urGW3W1VTHBmobM01hi4\r\n" \ +"DuYvEul+Mf0wMRtWjJolo4m+BO5KiW2jpFfqFm6JmfjVqOIAKOSKC6am8V/MDF0h\r\n" \ +"kyN9AoGAT9oOiEXMolbkDZw/QCaBiRoAGlGlNYUkJ+58U6OjIZLISw6aFv+Y2uE0\r\n" \ +"mEImItjuYZtSYKblWikp6ldPoKlt9bwEFe3c6IZ8kJ3+xyEyAGrvjXjEY7PzP6dp\r\n" \ +"Ajbjp9X9uocEBv9W/KsBLdQ7yizcL/toHwdBO4vQqmqTvAc5IIw=\r\n" \ +"-----END RSA PRIVATE KEY-----\r\n" + +#define RSA_PRIVATE_KEY_4096 \ +"-----BEGIN RSA PRIVATE KEY-----\r\n" \ +"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\r\n" \ +"-----END RSA PRIVATE KEY-----\r\n" + +#if defined _MSC_VER && !defined snprintf +#define snprintf _snprintf +#endif + +/* + * For heap usage estimates, we need an estimate of the overhead per allocated + * block. ptmalloc2/3 (used in gnu libc for instance) uses 2 size_t per block, + * so use that as our baseline. + */ +#define MEM_BLOCK_OVERHEAD ( 2 * sizeof( size_t ) ) + +/* + * Size to use for the malloc buffer if MEMORY_BUFFER_ALLOC_C is defined. + */ +#define HEAP_SIZE (1u << 16) // 64k + +#define BUFSIZE 1024 +#define HEADER_FORMAT " %-24s : " +#define TITLE_LEN 25 + +#define OPTIONS \ + "md4, md5, ripemd160, sha1, sha256, sha512,\r\n" \ + "arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish,\r\n" \ + "havege, ctr_drbg, hmac_drbg\r\n" \ + "rsa, dhm, ecdsa, ecdh.\r\n" + +#if defined(MBEDTLS_ERROR_C) +#define PRINT_ERROR \ + mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) ); \ + mbedtls_printf( "FAILED: %s\r\n", tmp ); +#else +#define PRINT_ERROR \ + mbedtls_printf( "FAILED: -0x%04x\r\n", -ret ); +#endif + +static unsigned long mbedtls_timing_hardclock( void ) +{ + static int dwt_started = 0; + + if( dwt_started == 0 ) + { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + return( DWT->CYCCNT ); +} + +static volatile int alarmed; +static void alarm() { alarmed = 1; } + +#define TIME_AND_TSC( TITLE, CODE ) \ +do { \ + unsigned long i, j, tsc; \ + Timeout t; \ + \ + mbedtls_printf( HEADER_FORMAT, TITLE ); \ + fflush( stdout ); \ + \ + for( i = 1, alarmed = 0, t.attach( alarm, 1.0 ); !alarmed; i++ ) \ + { \ + CODE; \ + } \ + \ + tsc = mbedtls_timing_hardclock(); \ + for( j = 0; j < 1024; j++ ) \ + { \ + CODE; \ + } \ + \ + mbedtls_printf( "%9lu Kb/s, %9lu cycles/byte\r\n", \ + i * BUFSIZE / 1024, \ + ( mbedtls_timing_hardclock() - tsc ) / ( j * BUFSIZE ) ); \ +} while( 0 ) + +#if defined(MBEDTLS_ERROR_C) +#define PRINT_ERROR \ + mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) ); \ + mbedtls_printf( "FAILED: %s\r\n", tmp ); +#else +#define PRINT_ERROR \ + mbedtls_printf( "FAILED: -0x%04x\r\n", -ret ); +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG) + +#define MEMORY_MEASURE_INIT \ + size_t max_used, max_blocks, max_bytes; \ + size_t prv_used, prv_blocks; \ + mbedtls_memory_buffer_alloc_cur_get( &prv_used, &prv_blocks ); \ + mbedtls_memory_buffer_alloc_max_reset( ); + +#define MEMORY_MEASURE_PRINT( title_len ) \ + mbedtls_memory_buffer_alloc_max_get( &max_used, &max_blocks ); \ + for( i = 12 - title_len; i != 0; i-- ) mbedtls_printf( " " ); \ + max_used -= prv_used; \ + max_blocks -= prv_blocks; \ + max_bytes = max_used + MEM_BLOCK_OVERHEAD * max_blocks; \ + mbedtls_printf( "%6u heap bytes", (unsigned) max_bytes ); + +#else +#define MEMORY_MEASURE_INIT +#define MEMORY_MEASURE_PRINT( title_len ) +#endif + +#define TIME_PUBLIC( TITLE, TYPE, CODE ) \ +do { \ + unsigned long ms; \ + int ret = 0; \ + Timer t; \ + MEMORY_MEASURE_INIT; \ + \ + mbedtls_printf( HEADER_FORMAT, TITLE ); \ + fflush( stdout ); \ + \ + t.start(); \ + CODE; \ + t.stop(); \ + ms = t.read_ms(); \ + \ + if( ret != 0 ) \ + { \ + PRINT_ERROR; \ + } \ + else \ + { \ + mbedtls_printf( "%6lu ms/" TYPE, ms ); \ + MEMORY_MEASURE_PRINT( sizeof( TYPE ) + 1 ); \ + mbedtls_printf( "\r\n" ); \ + } \ +} while( 0 ) + +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ + size_t use_len; + int rnd; + + if( rng_state != NULL ) + rng_state = NULL; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + rnd = rand(); + memcpy( output, &rnd, use_len ); + output += use_len; + len -= use_len; + } + + return( 0 ); +} + +/* + * Clear some memory that was used to prepare the context + */ +#if defined(MBEDTLS_ECP_C) +void ecp_clear_precomputed( mbedtls_ecp_group *grp ) +{ + if( grp->T != NULL ) + { + size_t i; + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + grp->T = NULL; + grp->T_size = 0; +} +#else +#define ecp_clear_precomputed( g ) +#endif + +unsigned char buf[BUFSIZE]; + +typedef struct { + char md4, md5, ripemd160, sha1, sha256, sha512, + arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish, + havege, ctr_drbg, hmac_drbg, + rsa, dhm, ecdsa, ecdh; +} todo_list; + +int benchmark( int argc, char *argv[] ) +{ + int i; + unsigned char tmp[200]; + char title[TITLE_LEN]; + todo_list todo; +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + unsigned char malloc_buf[HEAP_SIZE] = { 0 }; +#endif + + if( argc <= 1 ) + { + memset( &todo, 1, sizeof( todo ) ); + } + else + { + memset( &todo, 0, sizeof( todo ) ); + + for( i = 1; i < argc; i++ ) + { + if( strcmp( argv[i], "md4" ) == 0 ) + todo.md4 = 1; + else if( strcmp( argv[i], "md5" ) == 0 ) + todo.md5 = 1; + else if( strcmp( argv[i], "ripemd160" ) == 0 ) + todo.ripemd160 = 1; + else if( strcmp( argv[i], "sha1" ) == 0 ) + todo.sha1 = 1; + else if( strcmp( argv[i], "sha256" ) == 0 ) + todo.sha256 = 1; + else if( strcmp( argv[i], "sha512" ) == 0 ) + todo.sha512 = 1; + else if( strcmp( argv[i], "arc4" ) == 0 ) + todo.arc4 = 1; + else if( strcmp( argv[i], "des3" ) == 0 ) + todo.des3 = 1; + else if( strcmp( argv[i], "des" ) == 0 ) + todo.des = 1; + else if( strcmp( argv[i], "aes_cbc" ) == 0 ) + todo.aes_cbc = 1; + else if( strcmp( argv[i], "aes_gcm" ) == 0 ) + todo.aes_gcm = 1; + else if( strcmp( argv[i], "aes_ccm" ) == 0 ) + todo.aes_ccm = 1; + else if( strcmp( argv[i], "camellia" ) == 0 ) + todo.camellia = 1; + else if( strcmp( argv[i], "blowfish" ) == 0 ) + todo.blowfish = 1; + else if( strcmp( argv[i], "havege" ) == 0 ) + todo.havege = 1; + else if( strcmp( argv[i], "ctr_drbg" ) == 0 ) + todo.ctr_drbg = 1; + else if( strcmp( argv[i], "hmac_drbg" ) == 0 ) + todo.hmac_drbg = 1; + else if( strcmp( argv[i], "rsa" ) == 0 ) + todo.rsa = 1; + else if( strcmp( argv[i], "dhm" ) == 0 ) + todo.dhm = 1; + else if( strcmp( argv[i], "ecdsa" ) == 0 ) + todo.ecdsa = 1; + else if( strcmp( argv[i], "ecdh" ) == 0 ) + todo.ecdh = 1; + else + { + mbedtls_printf( "Unrecognized option: %s\r\n", argv[i] ); + mbedtls_printf( "Available options: " OPTIONS ); + } + } + } + + mbedtls_printf( "\r\n\r\n" ); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init( malloc_buf, sizeof( malloc_buf ) ); +#endif + memset( buf, 0xAA, sizeof( buf ) ); + memset( tmp, 0xBB, sizeof( tmp ) ); + +#if defined(MBEDTLS_MD4_C) + if( todo.md4 ) + TIME_AND_TSC( "MD4", mbedtls_md4( buf, BUFSIZE, tmp ) ); +#endif + +#if defined(MBEDTLS_MD5_C) + if( todo.md5 ) + TIME_AND_TSC( "MD5", mbedtls_md5( buf, BUFSIZE, tmp ) ); +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + if( todo.ripemd160 ) + TIME_AND_TSC( "RIPEMD160", mbedtls_ripemd160( buf, BUFSIZE, tmp ) ); +#endif + +#if defined(MBEDTLS_SHA1_C) + if( todo.sha1 ) + TIME_AND_TSC( "SHA-1", mbedtls_sha1( buf, BUFSIZE, tmp ) ); +#endif + +#if defined(MBEDTLS_SHA256_C) + if( todo.sha256 ) + TIME_AND_TSC( "SHA-256", mbedtls_sha256( buf, BUFSIZE, tmp, 0 ) ); +#endif + +#if defined(MBEDTLS_SHA512_C) + if( todo.sha512 ) + TIME_AND_TSC( "SHA-512", mbedtls_sha512( buf, BUFSIZE, tmp, 0 ) ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( todo.arc4 ) + { + mbedtls_arc4_context arc4; + mbedtls_arc4_init( &arc4 ); + mbedtls_arc4_setup( &arc4, tmp, 32 ); + TIME_AND_TSC( "ARC4", mbedtls_arc4_crypt( &arc4, BUFSIZE, buf, buf ) ); + mbedtls_arc4_free( &arc4 ); + } +#endif + +#if defined(MBEDTLS_DES_C) && defined(MBEDTLS_CIPHER_MODE_CBC) + if( todo.des3 ) + { + mbedtls_des3_context des3; + mbedtls_des3_init( &des3 ); + mbedtls_des3_set3key_enc( &des3, tmp ); + TIME_AND_TSC( "3DES", + mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) ); + mbedtls_des3_free( &des3 ); + } + + if( todo.des ) + { + mbedtls_des_context des; + mbedtls_des_init( &des ); + mbedtls_des_setkey_enc( &des, tmp ); + TIME_AND_TSC( "DES", + mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) ); + mbedtls_des_free( &des ); + } +#endif + +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( todo.aes_cbc ) + { + int keysize; + mbedtls_aes_context aes; + mbedtls_aes_init( &aes ); + for( keysize = 128; keysize <= 256; keysize += 64 ) + { + mbedtls_snprintf( title, sizeof( title ), "AES-CBC-%d", keysize ); + + memset( buf, 0, sizeof( buf ) ); + memset( tmp, 0, sizeof( tmp ) ); + mbedtls_aes_setkey_enc( &aes, tmp, keysize ); + + TIME_AND_TSC( title, + mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) ); + } + mbedtls_aes_free( &aes ); + } +#endif +#if defined(MBEDTLS_GCM_C) + if( todo.aes_gcm ) + { + int keysize; + mbedtls_gcm_context gcm; + + mbedtls_gcm_init( &gcm ); + for( keysize = 128; keysize <= 256; keysize += 64 ) + { + mbedtls_snprintf( title, sizeof( title ), "AES-GCM-%d", keysize ); + + memset( buf, 0, sizeof( buf ) ); + memset( tmp, 0, sizeof( tmp ) ); + mbedtls_gcm_setkey( &gcm, MBEDTLS_CIPHER_ID_AES, tmp, keysize ); + + TIME_AND_TSC( title, + mbedtls_gcm_crypt_and_tag( &gcm, MBEDTLS_GCM_ENCRYPT, BUFSIZE, tmp, + 12, NULL, 0, buf, buf, 16, tmp ) ); + + mbedtls_gcm_free( &gcm ); + } + } +#endif +#if defined(MBEDTLS_CCM_C) + if( todo.aes_ccm ) + { + int keysize; + mbedtls_ccm_context ccm; + + mbedtls_ccm_init( &ccm ); + for( keysize = 128; keysize <= 256; keysize += 64 ) + { + mbedtls_snprintf( title, sizeof( title ), "AES-CCM-%d", keysize ); + + memset( buf, 0, sizeof( buf ) ); + memset( tmp, 0, sizeof( tmp ) ); + mbedtls_ccm_setkey( &ccm, MBEDTLS_CIPHER_ID_AES, tmp, keysize ); + + TIME_AND_TSC( title, + mbedtls_ccm_encrypt_and_tag( &ccm, BUFSIZE, tmp, + 12, NULL, 0, buf, buf, tmp, 16 ) ); + + mbedtls_ccm_free( &ccm ); + } + } +#endif +#endif + +#if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC) + if( todo.camellia ) + { + int keysize; + mbedtls_camellia_context camellia; + mbedtls_camellia_init( &camellia ); + for( keysize = 128; keysize <= 256; keysize += 64 ) + { + mbedtls_snprintf( title, sizeof( title ), "CAMELLIA-CBC-%d", keysize ); + + memset( buf, 0, sizeof( buf ) ); + memset( tmp, 0, sizeof( tmp ) ); + mbedtls_camellia_setkey_enc( &camellia, tmp, keysize ); + + TIME_AND_TSC( title, + mbedtls_camellia_crypt_cbc( &camellia, MBEDTLS_CAMELLIA_ENCRYPT, + BUFSIZE, tmp, buf, buf ) ); + } + mbedtls_camellia_free( &camellia ); + } +#endif + +#if defined(MBEDTLS_BLOWFISH_C) && defined(MBEDTLS_CIPHER_MODE_CBC) + if( todo.blowfish ) + { + int keysize; + mbedtls_blowfish_context blowfish; + mbedtls_blowfish_init( &blowfish ); + + for( keysize = 128; keysize <= 256; keysize += 64 ) + { + mbedtls_snprintf( title, sizeof( title ), "BLOWFISH-CBC-%d", keysize ); + + memset( buf, 0, sizeof( buf ) ); + memset( tmp, 0, sizeof( tmp ) ); + mbedtls_blowfish_setkey( &blowfish, tmp, keysize ); + + TIME_AND_TSC( title, + mbedtls_blowfish_crypt_cbc( &blowfish, MBEDTLS_BLOWFISH_ENCRYPT, BUFSIZE, + tmp, buf, buf ) ); + } + + mbedtls_blowfish_free( &blowfish ); + } +#endif + +#if defined(MBEDTLS_HAVEGE_C) + if( todo.havege ) + { + mbedtls_havege_state hs; + mbedtls_havege_init( &hs ); + TIME_AND_TSC( "HAVEGE", mbedtls_havege_random( &hs, buf, BUFSIZE ) ); + mbedtls_havege_free( &hs ); + } +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + if( todo.ctr_drbg ) + { + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_ctr_drbg_init( &ctr_drbg ); + + if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + TIME_AND_TSC( "CTR_DRBG (NOPR)", + if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + + if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON ); + TIME_AND_TSC( "CTR_DRBG (PR)", + if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + } +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( todo.hmac_drbg ) + { + mbedtls_hmac_drbg_context hmac_drbg; + const mbedtls_md_info_t *md_info; + + mbedtls_hmac_drbg_init( &hmac_drbg ); + +#if defined(MBEDTLS_SHA1_C) + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + mbedtls_exit(1); + + if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)", + if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + mbedtls_hmac_drbg_free( &hmac_drbg ); + + if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg, + MBEDTLS_HMAC_DRBG_PR_ON ); + TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)", + if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + mbedtls_hmac_drbg_free( &hmac_drbg ); +#endif + +#if defined(MBEDTLS_SHA256_C) + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ) ) == NULL ) + mbedtls_exit(1); + + if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)", + if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + mbedtls_hmac_drbg_free( &hmac_drbg ); + + if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 ) + mbedtls_exit(1); + mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg, + MBEDTLS_HMAC_DRBG_PR_ON ); + TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)", + if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 ) + mbedtls_exit(1) ); + mbedtls_hmac_drbg_free( &hmac_drbg ); +#endif + } +#endif + +#if defined(MBEDTLS_RSA_C) && \ + defined(MBEDTLS_PEM_PARSE_C) && defined(MBEDTLS_PK_PARSE_C) + if( todo.rsa ) + { + mbedtls_pk_context pk; + mbedtls_rsa_context *rsa; + const char *rsa_keys[] = { RSA_PRIVATE_KEY_2048, RSA_PRIVATE_KEY_4096 }; + size_t i; + + for( i = 0; i < sizeof( rsa_keys ) / sizeof( rsa_keys[0] ); i++ ) + { + mbedtls_pk_init( &pk ); + mbedtls_pk_parse_key( &pk, (const unsigned char *) rsa_keys[i], + strlen( rsa_keys[i] ) + 1, NULL, 0 ); + rsa = mbedtls_pk_rsa( pk ); + + mbedtls_snprintf( title, sizeof( title ), "RSA-%d", mbedtls_pk_get_bitlen( &pk ) ); + + TIME_PUBLIC( title, " public", + buf[0] = 0; + ret = mbedtls_rsa_public( rsa, buf, buf ) ); + + TIME_PUBLIC( title, "private", + buf[0] = 0; + ret = mbedtls_rsa_private( rsa, myrand, NULL, buf, buf ) ); + + mbedtls_pk_free( &pk ); + } + } +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_BIGNUM_C) + if( todo.dhm ) + { + int dhm_sizes[] = { 2048, 3072 }; + const char *dhm_P[] = { + MBEDTLS_DHM_RFC3526_MODP_2048_P, + MBEDTLS_DHM_RFC3526_MODP_3072_P, + }; + const char *dhm_G[] = { + MBEDTLS_DHM_RFC3526_MODP_2048_G, + MBEDTLS_DHM_RFC3526_MODP_3072_G, + }; + + mbedtls_dhm_context dhm; + size_t olen; + for( i = 0; (size_t) i < sizeof( dhm_sizes ) / sizeof( dhm_sizes[0] ); i++ ) + { + mbedtls_dhm_init( &dhm ); + + if( mbedtls_mpi_read_string( &dhm.P, 16, dhm_P[i] ) != 0 || + mbedtls_mpi_read_string( &dhm.G, 16, dhm_G[i] ) != 0 ) + { + mbedtls_exit( 1 ); + } + + dhm.len = mbedtls_mpi_size( &dhm.P ); + mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len, myrand, NULL ); + if( mbedtls_mpi_copy( &dhm.GY, &dhm.GX ) != 0 ) + mbedtls_exit( 1 ); + + mbedtls_snprintf( title, sizeof( title ), "DHE-%d", dhm_sizes[i] ); + TIME_PUBLIC( title, "handshake", + ret |= mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len, + myrand, NULL ); + ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) ); + + mbedtls_snprintf( title, sizeof( title ), "DH-%d", dhm_sizes[i] ); + TIME_PUBLIC( title, "handshake", + ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) ); + + mbedtls_dhm_free( &dhm ); + } + } +#endif + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA256_C) + if( todo.ecdsa ) + { + mbedtls_ecdsa_context ecdsa; + const mbedtls_ecp_curve_info *curve_info; + size_t sig_len; + + memset( buf, 0x2A, sizeof( buf ) ); + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + mbedtls_ecdsa_init( &ecdsa ); + + if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 ) + mbedtls_exit( 1 ); + ecp_clear_precomputed( &ecdsa.grp ); + + mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s", + curve_info->name ); + TIME_PUBLIC( title, "sign", + ret = mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size, + tmp, &sig_len, myrand, NULL ) ); + + mbedtls_ecdsa_free( &ecdsa ); + } + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + mbedtls_ecdsa_init( &ecdsa ); + + if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 || + mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size, + tmp, &sig_len, myrand, NULL ) != 0 ) + { + mbedtls_exit( 1 ); + } + ecp_clear_precomputed( &ecdsa.grp ); + + mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s", + curve_info->name ); + TIME_PUBLIC( title, "verify", + ret = mbedtls_ecdsa_read_signature( &ecdsa, buf, curve_info->bit_size, + tmp, sig_len ) ); + + mbedtls_ecdsa_free( &ecdsa ); + } + } +#endif + +#if defined(MBEDTLS_ECDH_C) + if( todo.ecdh ) + { + mbedtls_ecdh_context ecdh; +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + mbedtls_mpi z; +#endif + const mbedtls_ecp_curve_info *curve_info; + size_t olen; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + mbedtls_ecdh_init( &ecdh ); + + if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 || + mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf), + myrand, NULL ) != 0 || + mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 ) + { + mbedtls_exit( 1 ); + } + ecp_clear_precomputed( &ecdh.grp ); + + mbedtls_snprintf( title, sizeof( title ), "ECDHE-%s", + curve_info->name ); + TIME_PUBLIC( title, "handshake", + ret |= mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf), + myrand, NULL ); + ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ), + myrand, NULL ) ); + mbedtls_ecdh_free( &ecdh ); + } + + /* Curve25519 needs to be handled separately */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + mbedtls_ecdh_init( &ecdh ); + mbedtls_mpi_init( &z ); + + if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 || + mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp, myrand, NULL ) != 0 ) + { + mbedtls_exit( 1 ); + } + + TIME_PUBLIC( "ECDHE-Curve25519", "handshake", + ret |= mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q, + myrand, NULL ); + ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d, + myrand, NULL ) ); + + mbedtls_ecdh_free( &ecdh ); + mbedtls_mpi_free( &z ); +#endif + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + mbedtls_ecdh_init( &ecdh ); + + if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 || + mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf), + myrand, NULL ) != 0 || + mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 || + mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf), + myrand, NULL ) != 0 ) + { + mbedtls_exit( 1 ); + } + ecp_clear_precomputed( &ecdh.grp ); + + mbedtls_snprintf( title, sizeof( title ), "ECDH-%s", + curve_info->name ); + TIME_PUBLIC( title, "handshake", + ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ), + myrand, NULL ) ); + mbedtls_ecdh_free( &ecdh ); + } + + /* Curve25519 needs to be handled separately */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + mbedtls_ecdh_init( &ecdh ); + mbedtls_mpi_init( &z ); + + if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 || + mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp, + myrand, NULL ) != 0 || + mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q, myrand, NULL ) != 0 ) + { + mbedtls_exit( 1 ); + } + + TIME_PUBLIC( "ECDH-Curve25519", "handshake", + ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d, + myrand, NULL ) ); + + mbedtls_ecdh_free( &ecdh ); + mbedtls_mpi_free( &z ); +#endif + } +#endif + + mbedtls_printf( "\r\n" ); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_free(); +#endif + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\r\n" ); + fflush( stdout ); getchar(); +#endif + + return( 0 ); +} + +#include "mbed/test_env.h" + +int main() { + MBED_HOSTTEST_TIMEOUT(150); + MBED_HOSTTEST_SELECT(default); + MBED_HOSTTEST_DESCRIPTION(mbed TLS benchmark program); + MBED_HOSTTEST_START("MBEDTLS_BENCHMARK"); + MBED_HOSTTEST_RESULT(benchmark(0, NULL) == 0); +} + +#endif /* TARGET_LIKE_MBED */ diff --git a/yotta/data/example-hashing/README.md b/yotta/data/example-hashing/README.md new file mode 100644 index 000000000..703d5b49b --- /dev/null +++ b/yotta/data/example-hashing/README.md @@ -0,0 +1,69 @@ +# Hashing tutorial + +This application performs hashing of a buffer with SHA-256 using various APIs. It serves as a tutorial for the basic hashing APIs of mbed TLS. + +## Pre-requisites + +To build and run this example the requirements below are necessary: + +* 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/). + * [ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded). + * A serial terminal emulator (e.g. screen, pySerial, cu). +* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in that case you'll have to substitute frdm-k64f-gcc with the appropriate target below). +* A micro-USB 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 computer with the micro-USB cable, being careful to use the micro-usb port labeled "OpenSDA". + +2. Navigate to the mbedtls directory supplied with your release and open a terminal. + +3. Set the yotta target: + + ``` + yotta target frdm-k64f-gcc + ``` + +4. Check that there are no missing dependencies: + + ``` + $ yt ls + ``` + + If there are, yotta will list them in the terminal. Please install them before proceeding. + +5. Build mbedtls and the examples. This will take a long time if it is the first time: + + ``` + $ yt build + ``` + +6. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-hashing.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. For settings, use 9600 baud, 8N1, no flow control. + +8. Press the reset button on the board. + +9. The output in the terminal window should look like: + + ``` + {{timeout;10}} + {{host_test_name;default}} + {{description;mbed TLS example on hashing}} + {{test_id;MBEDTLS_EX_HASHING}} + {{start}} + + + Method 1: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3 + Method 2: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3 + Method 3: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3 + Method 4: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3 + + DONE + {{success}} + {{end}} + ``` diff --git a/yotta/data/example-hashing/main.cpp b/yotta/data/example-hashing/main.cpp new file mode 100644 index 000000000..8eb3c1b05 --- /dev/null +++ b/yotta/data/example-hashing/main.cpp @@ -0,0 +1,157 @@ +/* + * Hello world example of using the hashing functions of mbed TLS + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * This program illustrates various ways of hashing a buffer. + * You normally need only one of these two includes. + */ +#include "mbedtls/sha256.h" /* SHA-256 only */ +#include "mbedtls/md.h" /* generic interface */ + +#if defined(TARGET_LIKE_MBED) +#include "mbed/mbed.h" +#endif +#include + +static void print_hex(const char *title, const unsigned char buf[], size_t len) +{ + printf("%s: ", title); + + for (size_t i = 0; i < len; i++) + printf("%02x", buf[i]); + + printf("\r\n"); +} + +static const char hello_str[] = "Hello, world!"; +static const unsigned char *hello_buffer = (const unsigned char *) hello_str; +static const size_t hello_len = sizeof hello_str - 1; + +int example(void) +{ + printf( "\r\n\r\n" ); + + /* + * Method 1: use all-in-one function of a specific SHA-xxx module + */ + unsigned char output1[32]; /* SHA-256 outputs 32 bytes */ + + /* 0 here means use the full SHA-256, not the SHA-224 variant */ + mbedtls_sha256(hello_buffer, hello_len, output1, 0); + + print_hex("Method 1", output1, sizeof output1); + + + /* + * Method 2: use the streaming interface of a specific SHA-xxx module + * This is useful if we get our input piecewise. + */ + unsigned char output2[32]; + mbedtls_sha256_context ctx2; + + mbedtls_sha256_init(&ctx2); + mbedtls_sha256_starts(&ctx2, 0); /* SHA-256, not 224 */ + + /* Simulating multiple fragments */ + mbedtls_sha256_update(&ctx2, hello_buffer, 1); + mbedtls_sha256_update(&ctx2, hello_buffer + 1, 1); + mbedtls_sha256_update(&ctx2, hello_buffer + 2, hello_len - 2); + + mbedtls_sha256_finish(&ctx2, output2); + print_hex("Method 2", output2, sizeof output2); + + /* Or you could re-use the context by doing mbedtls_sha256_starts() again */ + mbedtls_sha256_free(&ctx2); + + /* + * Method 3: use all-in-one function of the generice interface + */ + unsigned char output3[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ + + /* Can easily pick any hash you want, by identifier */ + const mbedtls_md_info_t *md_info3 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + + if (md_info3 == NULL) + { + printf("SHA256 not available\r\n"); + return 1; + } + + int ret3 = mbedtls_md(md_info3, hello_buffer, hello_len, output3); + + if (ret3 != 0) + { + printf("md() returned -0x%04X\r\n", -ret3); + return 1; + } + + print_hex("Method 3", output3, mbedtls_md_get_size(md_info3)); + + + /* + * Method 4: streaming & generic interface + */ + unsigned char output4[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ + + const mbedtls_md_info_t *md_info4 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + + if (md_info4 == NULL) + { + printf("SHA256 not available\r\n"); + return 1; + } + + mbedtls_md_context_t ctx4; + + mbedtls_md_init(&ctx4); + + int ret4 = mbedtls_md_init_ctx(&ctx4, md_info4); + if (ret4 != 0) + { + printf("md_init_ctx() returned -0x%04X\r\n", -ret4); + return 1; + } + + mbedtls_md_starts(&ctx4); + + /* Simulating multiple fragments */ + mbedtls_md_update(&ctx4, hello_buffer, 1); + mbedtls_md_update(&ctx4, hello_buffer + 1, 1); + mbedtls_md_update(&ctx4, hello_buffer + 2, hello_len - 2); + + mbedtls_md_finish(&ctx4, output4); + print_hex("Method 4", output4, mbedtls_md_get_size(md_info4)); + + /* Or you could re-use the context by doing mbedtls_md_starts() again */ + mbedtls_md_free(&ctx4); + + + printf("\r\nDONE\r\n"); + + return 0; +} + +#if defined(TARGET_LIKE_MBED) + +#include "mbed/test_env.h" + +int main() { + MBED_HOSTTEST_TIMEOUT(10); + MBED_HOSTTEST_SELECT(default); + MBED_HOSTTEST_DESCRIPTION(mbed TLS example on hashing); + MBED_HOSTTEST_START("MBEDTLS_EX_HASHING"); + MBED_HOSTTEST_RESULT(example() == 0); +} + +#else + +int main() { + return example(); +} + +#endif diff --git a/yotta/data/example-selftest/README.md b/yotta/data/example-selftest/README.md new file mode 100644 index 000000000..fef63423d --- /dev/null +++ b/yotta/data/example-selftest/README.md @@ -0,0 +1,88 @@ +# mbed TLS selftest programs + +This application runs the various selftest function of individual mbed TLS components. It serves as a basic sanity check for mbed TLS on your platform. In the future, a wider portion of the mbed TLS test suite will be ported on mbed OS. + +## Pre-requisites + +To build and run this example the requirements below are necessary: + +* 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/). + * [ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded). + * A serial terminal emulator (e.g. screen, pySerial, cu). +* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in that case you'll have to substitute frdm-k64f-gcc with the appropriate target below). +* A micro-USB 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 computer with the micro-USB cable, being careful to use the micro-usb port labeled "OpenSDA". + +2. Navigate to the mbedtls directory supplied with your release and open a terminal. + +3. Set the yotta target: + + ``` + yotta target frdm-k64f-gcc + ``` + +4. Check that there are no missing dependencies: + + ``` + $ yt ls + ``` + + If there are, yotta will list them in the terminal. Please install them before proceeding. + +5. Build mbedtls and the examples. This will take a long time if it is the first time: + + ``` + $ yt build + ``` + +6. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-selftest.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. For settings, use 9600 baud, 8N1, no flow control. + +8. Press the reset button on the board. + +9. The output in the terminal window should look like: + + ``` + {{timeout;40}} + {{host_test_name;default}} + {{description;mbed TLS selftest program}} + {{test_id;MBEDTLS_SELFTEST}} + {{start}} + + SHA-1 test #1: passed + SHA-1 test #2: passed + SHA-1 test #3: passed + + SHA-224 test #1: passed + SHA-224 test #2: passed + SHA-224 test #3: passed + SHA-256 test #1: passed + SHA-256 test #2: passed + SHA-256 test #3: passed + + [ ... several lines omitted ... ] + + CTR_DRBG (PR = TRUE) : passed + CTR_DRBG (PR = FALSE): passed + + HMAC_DRBG (PR = True) : passed + HMAC_DRBG (PR = False) : passed + + ECP test #1 (constant op_count, base point G): passed + ECP test #2 (constant op_count, other point): passed + + ENTROPY test: passed + + [ All tests passed ] + + {{success}} + {{end}} + ``` diff --git a/yotta/data/example-selftest/main.cpp b/yotta/data/example-selftest/main.cpp new file mode 100644 index 000000000..7c2310130 --- /dev/null +++ b/yotta/data/example-selftest/main.cpp @@ -0,0 +1,248 @@ +/* + * Self-test demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/dhm.h" +#include "mbedtls/gcm.h" +#include "mbedtls/ccm.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/arc4.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/camellia.h" +#include "mbedtls/base64.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa.h" +#include "mbedtls/x509.h" +#include "mbedtls/xtea.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/ecp.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +#endif + +int selftest( int argc, char *argv[] ) +{ + int ret = 0, v; +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + unsigned char buf[1000000]; +#endif + + if( argc == 2 && strcmp( argv[1], "-quiet" ) == 0 ) + v = 0; + else + { + v = 1; + mbedtls_printf( "\n" ); + } + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init( buf, sizeof(buf) ); +#endif + +#if defined(MBEDTLS_MD2_C) + if( ( ret = mbedtls_md2_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_MD4_C) + if( ( ret = mbedtls_md4_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_MD5_C) + if( ( ret = mbedtls_md5_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + if( ( ret = mbedtls_ripemd160_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_SHA1_C) + if( ( ret = mbedtls_sha1_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_SHA256_C) + if( ( ret = mbedtls_sha256_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_SHA512_C) + if( ( ret = mbedtls_sha512_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ( ret = mbedtls_arc4_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_DES_C) + if( ( ret = mbedtls_des_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_AES_C) + if( ( ret = mbedtls_aes_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C) + if( ( ret = mbedtls_gcm_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C) + if( ( ret = mbedtls_ccm_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_BASE64_C) + if( ( ret = mbedtls_base64_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_BIGNUM_C) + if( ( ret = mbedtls_mpi_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_RSA_C) + if( ( ret = mbedtls_rsa_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_X509_USE_C) + if( ( ret = mbedtls_x509_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_XTEA_C) + if( ( ret = mbedtls_xtea_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + if( ( ret = mbedtls_camellia_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + if( ( ret = mbedtls_ctr_drbg_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( ( ret = mbedtls_hmac_drbg_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_ECP_C) + if( ( ret = mbedtls_ecp_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_DHM_C) + if( ( ret = mbedtls_dhm_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_ENTROPY_C) + if( ( ret = mbedtls_entropy_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_PKCS5_C) + if( ( ret = mbedtls_pkcs5_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#if defined(MBEDTLS_TIMING_C) + if( ( ret = mbedtls_timing_self_test( v ) ) != 0 ) + return( ret ); +#endif + +#else + mbedtls_printf( " POLARSSL_SELF_TEST not defined.\n" ); +#endif + + if( v != 0 ) + { +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_memory_buffer_alloc_status(); +#endif + } + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_free(); + + if( ( ret = mbedtls_memory_buffer_alloc_self_test( v ) ) != 0 ) + return( ret ); +#endif + + if( v != 0 ) + { + mbedtls_printf( " [ All tests passed ]\n\n" ); +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + } + + return( ret ); +} + +#if defined(TARGET_LIKE_MBED) + +#include "mbed/test_env.h" + +int main() { + MBED_HOSTTEST_TIMEOUT(40); + MBED_HOSTTEST_SELECT(default); + MBED_HOSTTEST_DESCRIPTION(mbed TLS selftest program); + MBED_HOSTTEST_START("MBEDTLS_SELFTEST"); + MBED_HOSTTEST_RESULT(selftest(0, NULL) == 0); +} + +#else + +int main() { + return selftest(0, NULL); +} + +#endif diff --git a/yotta/data/example-tls-client/README.md b/yotta/data/example-tls-client/README.md new file mode 100644 index 000000000..0da780e46 --- /dev/null +++ b/yotta/data/example-tls-client/README.md @@ -0,0 +1,131 @@ +# HTTPS file downloader (TLS client example) + +This application downloads a file from an HTTPS server (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 the requirements below are necessary: + +* 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/). + * [ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded). + * A serial terminal emulator (e.g. screen, pySerial, cu). +* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board that has an Ethernet port and is supported by mbed OS (in that case you'll have to substitute frdm-k64f-gcc with the appropriate target below). +* An Ethernet connection to the internet. +* An Ethernet cable. +* A micro-USB 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 micro-usb port labeled "OpenSDA". + +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. Check that there are no missing dependencies: + + ``` + $ yt ls + ``` + + If there are, yotta will list them in the terminal. Please install them before proceeding. + +5. Build mbedtls and the examples. This will take a long time if it is the first time: + + ``` + $ yt build + ``` + +7. 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. + +8. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F. For settings, use 115200 baud, 8N1, no flow control. **Warning:** for this example, the baud rate is not the default 9600, it is 115200. + +9. Press the reset button on the board. + +10. The output in the terminal window should look like: + + ``` + {{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 + Connecting to developer.mbed.org:443 + 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, 28 Jul 2015 14:32:30 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, 29 Jul 2015 00:32:30 GMT + X-Upstream-L3: 172.17.42.1:8080 + X-Upstream-L2: developer-sjc-indigo-1-nginx + X-Upstream-L1-next-hop: 217.140.101.34: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/maste r/test/helloworld-tcpclient) for the TCP module works as expected. If not, please follow the debug instructions for this example. + +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 `mbed.org` switches to a new CA when updating its certificate). Alternatively, this could mean someone is performing a man-in-the-middle attack on your connection. You can ignore this error and proceed with the connection anyway by changing the definition of `UNSAFE` near the top of the file from 0 to 1. **Warning:** this removes all security against an active attacker, use at your own risk, for debugging only! diff --git a/yotta/data/example-tls-client/main.cpp b/yotta/data/example-tls-client/main.cpp new file mode 100644 index 000000000..970788c30 --- /dev/null +++ b/yotta/data/example-tls-client/main.cpp @@ -0,0 +1,489 @@ +/* + * Hello world example of a TLS client: fetch an HTTPS page + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(TARGET_LIKE_MBED) + +#include + +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 +#include + +#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 + +#include "lwipv4_init.h" + +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 just Verisign since it's the root used by developer.mbed.org + * If you want to trust more that one root, just concatenate them. + */ +const char SSL_CA_PEM[] = +"-----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"; +} + +/** + * \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. + * + * Note that CThunk is used for event handlers. This will be changed to a C++ + * function pointer in an upcoming release. + * + * + * @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); + } + /** + * 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 + */ + socket_error_t 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); + return SOCKET_ERROR_UNKNOWN; + } + + 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); + return SOCKET_ERROR_UNKNOWN; + } + + 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); + return SOCKET_ERROR_UNKNOWN; + } + + 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); + return SOCKET_ERROR_UNKNOWN; + } + + mbedtls_ssl_set_hostname(&_ssl, HTTPS_SERVER_NAME); + + mbedtls_ssl_set_bio(&_ssl, static_cast(&_stream), + ssl_send, ssl_recv, NULL ); + + + /* Connect to the server */ + printf("Connecting to %s:%d\r\n", _domain, _port); + /* Resolve the domain name: */ + socket_error_t err = _stream.resolve(_domain, handler_t(this, &HelloHTTPS::onDNS)); + return 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 *str) + { + (void) ctx; + (void) level; + + printf("%s", 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, int *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) { + mbed::TCPStream *stream = static_cast(ctx); + socket_error_t err = stream->recv(buf, &len); + + if (err == SOCKET_ERROR_NONE) { + return static_cast(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) { + mbed::TCPStream *stream = static_cast(ctx); + + socket_error_t err = stream->send(buf, len); + + if (err == SOCKET_ERROR_NONE) { + return static_cast(len); + } else if (err == SOCKET_ERROR_WOULD_BLOCK) { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } else { + return -1; + } + } + + /** + * On Connect handler + * Sends the request which was generated in startTest + */ + void onConnect(socket_error_t err) { + (void) err; + + _stream.setOnReadable(handler_t(this, &HelloHTTPS::onReceive)); + _stream.setOnDisconnect(handler_t(this, &HelloHTTPS::onDisconnect)); + + /* Start the handshake, the rest will be done in onReceive() */ + 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); + _error = true; + } + 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_error_t err) { + (void) err; + + if (_error) + return; + + /* 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); + _error = true; + } + 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); + _error = true; + } + return; + } + _bpos = static_cast(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); + } + /** + * On DNS Handler + * Reads the address returned by DNS, then starts the connect process. + */ + void onDNS(socket_error_t err) { + socket_event_t *e = _stream.getEvent(); + /* Check that the result is a valid DNS response */ + if (socket_addr_is_any(&e->i.d.addr)) { + /* Could not find DNS entry */ + _error = true; + printf("Could not find DNS entry for %s", HTTPS_SERVER_NAME); + return; + } else { + /* Start connecting to the remote host */ + _remoteAddr.setAddr(&e->i.d.addr); + err = _stream.connect(&_remoteAddr, _port, handler_t(this, &HelloHTTPS::onConnect)); + + if (err != SOCKET_ERROR_NONE) { + _error = true; + } + } + } + void onDisconnect(socket_error_t err) { + (void) err; + _disconnected = true; + } + +protected: + mbed::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 */ + mbed::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 + */ +int example_client() { + EthernetInterface eth; + /* Initialise with DHCP, connect, and start up the stack */ + eth.init(); + eth.connect(); + lwipv4_socket_init(); + + printf("\r\n\r\n"); + printf("Client IP Address is %s\r\n", eth.getIPAddress()); + + HelloHTTPS hello(HTTPS_SERVER_NAME, HTTPS_SERVER_PORT); + socket_error_t rc = hello.startTest(HTTPS_PATH); + if (rc != SOCKET_ERROR_NONE) { + return 1; + } + while (!hello.done()) { + __WFI(); + } + if (hello.error()) { + printf("Failed to fetch %s from %s:%d\r\n", HTTPS_PATH, HTTPS_SERVER_NAME, HTTPS_SERVER_PORT); + } + /* Shut down the socket before the ethernet interface */ + hello.close(); + eth.disconnect(); + return static_cast(hello.error()); +} + +#include "mbed/test_env.h" + +int main() { + /* 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"); + MBED_HOSTTEST_RESULT(example_client() == 0); +} + +#endif /* TARGET_LIKE_MBED */ diff --git a/yotta/data/module.json b/yotta/data/module.json new file mode 100644 index 000000000..3bca3d417 --- /dev/null +++ b/yotta/data/module.json @@ -0,0 +1,13 @@ +{ + "name": "mbedtls", + "version": "2.0.1", + "private": true, + "license": "GPL-2.0", + "dependencies": {}, + "targetDependencies": { + "mbed": { "cmsis-core": "~0.2.1" } + }, + "testTargetDependencies": { + "mbed": { "mbed-net-sockets": "~0.1.3" } + } +} diff --git a/yotta/data/target_config.h b/yotta/data/target_config.h new file mode 100644 index 000000000..02af2b3db --- /dev/null +++ b/yotta/data/target_config.h @@ -0,0 +1,22 @@ +/* + * Temporary target-specific config.h for entropy collection + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(TARGET_LIKE_MBED) +#define MBEDTLS_NO_PLATFORM_ENTROPY +#undef MBEDTLS_HAVE_TIME_DATE +#undef MBEDTLS_FS_IO +#endif + +/* + * WARNING: this is a temporary hack! + * 2. This should be in a separete yotta module which would be a target + * dependency of mbedtls (see IOTSSL-313) + */ +#if defined(TARGET_LIKE_CORTEX_M4) +#define MBEDTLS_ENTROPY_HARDWARE_ALT +#endif