diff --git a/threading/README.md b/threading/README.md new file mode 100644 index 000000000..9b715d8e9 --- /dev/null +++ b/threading/README.md @@ -0,0 +1,27 @@ +# mbed TLS threading example on mbed OS + +This application tests the thread safety of mbed TLS within mbed OS. The computations are performed sequentially at first to generate a reference value. Thereafter the aplication performs the same computations in parallel to test thread safety. + +## Getting started + +Set up your environment if you have not done so already. For instructions, refer to the [main readme](../README.md). + +## Monitoring the application + +The output in the terminal window should be similar to this: + +``` +Thread 0: Starting threads one by one... +Thread 1: Done. +Thread 2: Done. +Thread 0: Printing hash output... +Thread 0: 2794387f922b5f36953b6e02e6f499b7e1dbd19accb199192e8fd3c98c5fae7eb4f31f3c996c4ab28689eb5f137a4b947fc56a79698ca8c6ea1d3efec678a82c +Thread 0: Starting threads... +Thread 3: Done. +Thread 4: Done. +Thread 0: Printing hash output... +Thread 0: 2794387f922b5f36953b6e02e6f499b7e1dbd19accb199192e8fd3c98c5fae7eb4f31f3c996c4ab28689eb5f137a4b947fc56a79698ca8c6ea1d3efec678a82c +Thread 0: Done. +``` + +If the second hash string doesn't match the first, then the thread safety measures are not working properly and this build of mbed TLS is not thread safe! diff --git a/threading/main.cpp b/threading/main.cpp new file mode 100644 index 000000000..789a34a41 --- /dev/null +++ b/threading/main.cpp @@ -0,0 +1,176 @@ +/* + * An example of using mbed TLS in a thread safe manner + * + * Copyright (C) 2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "rtos.h" +#include "mbedtls/entropy.h" +#include "mbedtls/threading.h" + +#define THREADS 2 +#define ROUNDS 100 + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define HASHSIZE 64 +#else +#define HASHSIZE 32 +#endif + +#define BUFSIZE 64 +#define MAIN_ID 0 + +#define THREAD_CHK(f) do { if( ( ret = f ) != osOK ) goto cleanup; } while( 0 ) + +const unsigned char data[HASHSIZE] = { 0xaa }; + +Mutex stdio_mutex; + +mbedtls_entropy_context entropy; + +void hexify( unsigned char *obuf, const unsigned char *ibuf, int len ) +{ + unsigned char l, h; + + while( len != 0 ) + { + h = *ibuf / 16; + l = *ibuf % 16; + + if( h < 10 ) + *obuf++ = '0' + h; + else + *obuf++ = 'a' + h - 10; + + if( l < 10 ) + *obuf++ = '0' + l; + else + *obuf++ = 'a' + l - 10; + + ++ibuf; + len--; + } + + *obuf = '\0'; +} + +void notify( const char* message, int thread_id, const int err_code ) +{ + stdio_mutex.lock(); + + if( err_code ) + printf( "Thread %d: ERR - %s: %d\n\r", thread_id, message, err_code ); + else + printf( "Thread %d: %s\n\r", thread_id, message ); + + stdio_mutex.unlock(); +} + +void test_thread( void const *args ) +{ + int thread_id = *( (int*)args ); + int ret = 0; + int i; + + for ( i = 0; i < ROUNDS; i++ ) + { + + ret = mbedtls_entropy_update_manual( &entropy, data, BUFSIZE ); + if( 0 != ret ) + { + notify( "mbed TLS entropy update FAILED", thread_id, ret ); + return; + } + } + + notify( " Done.", thread_id, 0 ); +} + +int main( void ) +{ + unsigned char *hash = new unsigned char[HASHSIZE]; + unsigned char *output = new unsigned char[2 * HASHSIZE + 1]; + Thread thread[THREADS * 2]; + int thread_id[THREADS * 2]; + int ret, i; + + /* + * This calls mbedtls_threading_set_alt and tells the threading + * abstraction layer in mbed TLS to use the mbed implementation. + */ +#if defined(MBEDTLS_THREADING_ALT) + mbedtls_threading_set_mbed(); +#endif + mbedtls_entropy_init( &entropy ); + + notify( "Starting threads one by one...", MAIN_ID, 0 ); + for( i = 0; i < THREADS; i++ ) + { + thread_id[i] = i + 1; + THREAD_CHK( thread[i].start( mbed::callback( test_thread, &thread_id[i] ) ) ); + THREAD_CHK( thread[i].join() ); + } + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_finish( &entropy.accumulator, hash ); +#else + mbedtls_sha256_finish( &entropy.accumulator, hash ); +#endif + + hexify( output, hash, HASHSIZE ); + notify( "Printing hash output...", MAIN_ID, 0 ); + notify( (char*)output, MAIN_ID, 0 ); + + mbedtls_entropy_init( &entropy ); + + notify( "Starting threads...", MAIN_ID, 0 ); + for( i = THREADS; i < 2 * THREADS; i++ ) + { + thread_id[i] = i + 1; + THREAD_CHK( thread[i].start( mbed::callback( test_thread, &thread_id[i] ) ) ); + } + + for( i = THREADS; i < 2 * THREADS; i++ ) + THREAD_CHK( thread[i].join() ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_finish( &entropy.accumulator, hash ); +#else + mbedtls_sha256_finish( &entropy.accumulator, hash ); +#endif + + hexify( output, hash, HASHSIZE ); + notify( "Printing hash output...", MAIN_ID, 0 ); + notify( (char*)output, MAIN_ID, 0 ); + +cleanup: + + if( osOK != ret ) + { + notify( "RTOS thread operation FAILED", MAIN_ID, ret ); + + for( i = 0; i < 2 * THREADS; i++ ) + thread[i].terminate(); + } + +#if defined(MBEDTLS_THREADING_ALT) + mbedtls_entropy_free( &entropy ); +#endif + mbedtls_threading_free_alt(); + + notify( "Done.", MAIN_ID, 0 ); +} diff --git a/threading/mbed-os.lib b/threading/mbed-os.lib new file mode 100644 index 000000000..c6b22afca --- /dev/null +++ b/threading/mbed-os.lib @@ -0,0 +1 @@ +https://github.com/ARMmbed/mbed-os/#e435a07d9252f133ea3d9f6c95dfb176f32ab9b6 diff --git a/threading/mbed_app.json b/threading/mbed_app.json new file mode 100644 index 000000000..8123ccf7d --- /dev/null +++ b/threading/mbed_app.json @@ -0,0 +1,3 @@ +{ + "macros": ["MBEDTLS_THREADING"] +}