Merge pull request #233 from ARMmbed/yotta-scripted

Yotta scripted
This commit is contained in:
Manuel Pégourié-Gonnard 2015-08-06 18:04:34 +02:00
commit 278098f4f4
25 changed files with 2831 additions and 4 deletions

View File

@ -2,6 +2,9 @@ mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS 2 branch
Features
* Added support for yotta as a build system
Bugfix
* Fix segfault in the benchmark program when benchmarking DHM.
* Fix build error with CMake and pre-4.5 versions of GCC (found by Hugo
@ -20,6 +23,9 @@ Bugfix
Changes
* The PEM parser now accepts a trailing space at end of lines (#226).
* It is now possible to #include a user-provided configuration file at the
end of the default config.h by defining MBEDTLS_USER_CONFIG_FILE on the
compiler's command line.
= mbed TLS 2.0.0 released 2015-07-13

View File

@ -14,13 +14,45 @@ Compiler options can be set using standard variables such as *CC* and *CFLAGS* w
Compiling
=========
There are currently three active build systems within the mbed TLS releases:
There are currently four active build systems within the mbed TLS releases:
- yotta
- Make
- CMake
- Microsoft Visual Studio (Visual Studio 6 and Visual Studio 2010)
The main system used for development is CMake. That system is always the most up-to-date. The others should reflect all changes present in the CMake build system, but some features are not ported there by default.
The main systems used for development are CMake and yotta. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and yotta build system, but some features are not ported there by default.
Please note that the yotta option is slightly different from the other build systems:
- a more minimalistic configuration file is used by default
- depending on the yotta target, features of mbed OS will be used in examples and tests
Yotta
-----
`yotta <http://yottabuild.org>` is a package manager and build system developped by mbed; it is the build system of mbed OS. To install it on your platform, please follow the `yotta installation instructions <http://docs.yottabuild.org/#installing>`.
Once yotta is installed, you can use it to download the latest version of mbed TLS form the yotta registry with::
yotta install mbedtls
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::
yotta/create-module.sh
from the mbed TLS root directory. This will create the yotta module in the *yotta/module* directory. You can then change to that directory and build as usual::
cd yotta/module
yotta build
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 of mbed TLS, yotta edition <https://github.com/ARMmbed/mbedtls/master/tree/yotta/data/README.md>`.
Make
----

View File

@ -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"

View File

@ -2421,6 +2421,23 @@
/* \} name SECTION: Module configuration options */
#if defined(TARGET_LIKE_MBED)
#include "mbedtls/target_config.h"
#endif
/*
* Allow user to override any previous default.
*
* Use two macro names for that, as:
* - with yotta the prefix YOTTA_CFG_ is forced
* - without yotta is looks weird to have a YOTTA prefix.
*/
#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
#elif defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif
#include "check_config.h"
#endif /* MBEDTLS_CONFIG_H */

View File

@ -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

View File

@ -41,7 +41,7 @@ cleanup()
{
make clean
find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} \+
find . -name yotta -prune -o -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} \+
rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
git update-index --no-skip-worktree Makefile library/Makefile programs/Makefile tests/Makefile
git checkout -- Makefile library/Makefile programs/Makefile tests/Makefile
@ -83,6 +83,10 @@ msg "test/build: declared and exported names" # < 3s
cleanup
tests/scripts/check-names.sh
msg "build: create and build yotta module" # ~ 30s
cleanup
tests/scripts/yotta-build.sh
msg "build: cmake, gcc, ASan" # ~ 1 min 50s
cleanup
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .

View File

@ -56,7 +56,7 @@ sed -n 's/MBED..._[A-Z0-9_]*/\'"$NL"'&\'"$NL"/gp \
$HEADERS library/*.c \
| grep MBEDTLS | sort -u > _MBEDTLS_XXX
TYPOS=$( diff _caps _MBEDTLS_XXX | sed -n 's/^> //p' \
| egrep -v 'XXX|__|_$|^MBEDTLS_CONFIG_FILE$' || true )
| egrep -v 'XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$' || true )
rm _MBEDTLS_XXX _caps
if [ "x$TYPOS" = "x" ]; then
echo "PASS"

37
tests/scripts/yotta-build.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/sh
# Do test builds of the yotta module for all supported targets
set -eu
yotta/create-module.sh
cd yotta/module
# yt update # needs network
yotta_build()
{
TARGET=$1
echo; echo "*** $TARGET ***"
yt target $TARGET
yt build
}
if uname -a | grep 'Linux.*x86' >/dev/null; then
yotta_build x86-linux-native
fi
if uname -a | grep 'Darwin.*x86' >/dev/null; then
yotta_build x86-osx-native
fi
if which armcc >/dev/null && armcc --help >/dev/null 2>&1; then
yotta_build frdm-k64f-armcc
#yotta_build nordic-nrf51822-16k-armcc
fi
if which arm-none-eabi-gcc >/dev/null; then
yotta_build frdm-k64f-gcc
#yotta_build st-nucleo-f401re-gcc # dirent
#yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
#yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform
#yotta_build bbc-microbit-classic-gcc # fails in minar-platform
#yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4
#yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
fi

1
yotta/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
module

44
yotta/create-module.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/sh
set -eu
# relative to the script's directory
TREE=..
DEST=module
# 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'."

55
yotta/data/README.md Normal file
View File

@ -0,0 +1,55 @@
# 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 mbed TLS in mbed OS. 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.
## Configuring mbed TLS features
**Warning:** This is only a preview of a future feature that will require support from yotta; as of yotta 0.5.2 this is not supported yet.
mbed TLS makes it easy to disable during the compilation any feature that is not needed for a particular project. The default configuration enables all modern and widely-used features, which should meet the need of any new project; it disables all features that are either older or less mainstrem, in order to keep the footprint low. The list of available compile flags is available in the fully documented [config.h file](https://github.com/ARMmbed/mbedtls/blob/master/include/mbedtls/config.h), present in the `mbedtls` directory of the yotta module.
Should you need to adjust those flags, you can provide your own configuration file with the suitable `#define` and `#undef` statements, to be included between the default definitions and the sanity checks. This file should be in your application's include directory and can be named freely; you just need to let mbed TLS know the name of the file, by using yotta's [configuration system](http://docs.yottabuild.org/reference/config.html). This name should go in your `config.json`, under mbedtls, as the key `user-config-file`, for example:
{
"mbedtls": {
"user-config-file": "\"myapp/my_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.
## 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 :)

74
yotta/data/adjust-config.sh Executable file
View File

@ -0,0 +1,74 @@
#!/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 $@
}
# not supported on mbed OS, nor used by mbed Client
conf unset MBEDTLS_NET_C
conf unset MBEDTLS_TIMING_C
# not supported on all targets with mbed OS, nor used by mbed Client
conf unset MBEDTLS_FS_IO
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

View File

@ -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 <string.h>
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

View File

@ -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.

View File

@ -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 <stdio.h>
#include <string.h>
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

View File

@ -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}}
```

View File

@ -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 <stdio.h>
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 <stdio.h>
#define mbedtls_exit exit
#define mbedtls_printf printf
#define mbedtls_snprintf snprintf
#define mbedtls_free free
#endif
#include <string.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/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 */

View File

@ -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}}
```

View File

@ -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 <cstdio>
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

View File

@ -0,0 +1,84 @@
# 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-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}}
```

View File

@ -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 <stdio.h>
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#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

View File

@ -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!

View File

@ -0,0 +1,498 @@
/*
* 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 <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 "mbed-net-lwip-eth/EthernetInterface.h"
#include "mbed-net-sockets/TCPStream.h"
#include "minar/minar.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
#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";
}
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.
*
* 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<void *>(&_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, TCPStream::DNSHandler_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) {
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;
minar::Scheduler::stop();
}
/**
* On Connect handler
* Starts the TLS handshake
*/
void onConnect(TCPStream *s) {
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() */
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 *s) {
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<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("%s address: %s\r\n",domain, buf);
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();
minar::Scheduler::stop();
}
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
*/
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<int>(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 */

13
yotta/data/module.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "mbedtls",
"version": "2.0.2",
"private": true,
"license": "GPL-2.0",
"dependencies": {},
"targetDependencies": {
"mbed": { "cmsis-core": "~0.2.3" }
},
"testTargetDependencies": {
"mbed": { "mbed-net-sockets": "~0.2.0" }
}
}

View File

@ -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