Merge branch 'development' into iotssl-1619

This commit is contained in:
Hanno Becker 2018-01-03 10:24:02 +00:00
commit 8bc74d6f2f
20 changed files with 1453 additions and 716 deletions

View file

@ -14,6 +14,18 @@ Security
Features Features
* Allow comments in test data files. * Allow comments in test data files.
* The selftest program can execute a subset of the tests based on command
line arguments.
* New unit tests for timing. Improve the self-test to be more robust
when run on a heavily-loaded machine.
* Add alternative implementation support for CCM and CMAC (MBEDTLS_CCM_ALT,
MBEDTLS_CMAC_ALT). Submitted by Steve Cooreman, Silicon Labs.
* Add support for alternative implementations of GCM, selected by the
configuration flag MBEDTLS_GCM_ALT.
New deprecations
* Deprecate usage of RSA primitives with non-matching key-type
(e.g., signing with a public key).
API Changes API Changes
* Extend RSA interface by multiple functions allowing structure- * Extend RSA interface by multiple functions allowing structure-
@ -73,6 +85,10 @@ Bugfix
* Fix incorrect unit in benchmark output. #850 * Fix incorrect unit in benchmark output. #850
* Fix crash when calling mbedtls_ssl_cache_free() twice. Found by * Fix crash when calling mbedtls_ssl_cache_free() twice. Found by
MilenkoMitrovic, #1104 MilenkoMitrovic, #1104
* Fix mbedtls_timing_alarm(0) on Unix.
* Fix use of uninitialized memory in mbedtls_timing_get_timer when reset=1.
* Fix possible memory leaks in mbedtls_gcm_self_test().
* Added missing return code checks in mbedtls_aes_self_test().
Changes Changes
* Extend cert_write example program by options to set the CRT version * Extend cert_write example program by options to set the CRT version
@ -82,6 +98,7 @@ Changes
particular, don't require P,Q if neither CRT nor blinding are particular, don't require P,Q if neither CRT nor blinding are
used. Reported and fix proposed independently by satur9nine and sliai used. Reported and fix proposed independently by satur9nine and sliai
on GitHub. on GitHub.
* Only run AES-192 self-test if AES-192 is available. Fixes #963.
= mbed TLS 2.6.0 branch released 2017-08-10 = mbed TLS 2.6.0 branch released 2017-08-10

View file

@ -36,9 +36,13 @@
#define MBEDTLS_AES_ENCRYPT 1 #define MBEDTLS_AES_ENCRYPT 1
#define MBEDTLS_AES_DECRYPT 0 #define MBEDTLS_AES_DECRYPT 0
/* Error codes in range 0x0020-0x0022 */
#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ #define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/* Error codes in range 0x0023-0x0023 */
#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available, e.g. unsupported AES key size. */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus) !defined(inline) && !defined(__cplusplus)
#define inline __inline #define inline __inline

View file

@ -28,6 +28,10 @@
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
#if !defined(MBEDTLS_CCM_ALT)
// Regular implementation
//
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -125,6 +129,18 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output, const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len ); const unsigned char *tag, size_t tag_len );
#ifdef __cplusplus
}
#endif
#else /* !MBEDTLS_CCM_ALT */
#include "ccm_alt.h"
#endif /* !MBEDTLS_CCM_ALT */
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/** /**
* \brief Checkup routine * \brief Checkup routine

View file

@ -39,6 +39,8 @@ extern "C" {
#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ #define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */
#endif #endif
#if !defined(MBEDTLS_CMAC_ALT)
/** /**
* CMAC context structure - Contains internal state information only * CMAC context structure - Contains internal state information only
*/ */
@ -154,6 +156,18 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
unsigned char output[16] ); unsigned char output[16] );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#else /* !MBEDTLS_CMAC_ALT */
#include "cmac_alt.h"
#endif /* !MBEDTLS_CMAC_ALT */
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
/** /**
* \brief Checkup routine * \brief Checkup routine

View file

@ -266,8 +266,11 @@
//#define MBEDTLS_ARC4_ALT //#define MBEDTLS_ARC4_ALT
//#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_BLOWFISH_ALT
//#define MBEDTLS_CAMELLIA_ALT //#define MBEDTLS_CAMELLIA_ALT
//#define MBEDTLS_CCM_ALT
//#define MBEDTLS_CMAC_ALT
//#define MBEDTLS_DES_ALT //#define MBEDTLS_DES_ALT
//#define MBEDTLS_RSA_ALT //#define MBEDTLS_RSA_ALT
//#define MBEDTLS_GCM_ALT
//#define MBEDTLS_XTEA_ALT //#define MBEDTLS_XTEA_ALT
//#define MBEDTLS_MD2_ALT //#define MBEDTLS_MD2_ALT
//#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD4_ALT

View file

@ -52,7 +52,7 @@
* GCM 2 0x0012-0x0014 * GCM 2 0x0012-0x0014
* BLOWFISH 2 0x0016-0x0018 * BLOWFISH 2 0x0016-0x0018
* THREADING 3 0x001A-0x001E * THREADING 3 0x001A-0x001E
* AES 2 0x0020-0x0022 * AES 2 0x0020-0x0022 0x0023-0x0023
* CAMELLIA 2 0x0024-0x0026 * CAMELLIA 2 0x0024-0x0026
* XTEA 1 0x0028-0x0028 * XTEA 1 0x0028-0x0028
* BASE64 2 0x002A-0x002C * BASE64 2 0x002A-0x002C

View file

@ -33,6 +33,8 @@
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
#if !defined(MBEDTLS_GCM_ALT)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -206,6 +208,18 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
*/ */
void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); void mbedtls_gcm_free( mbedtls_gcm_context *ctx );
#ifdef __cplusplus
}
#endif
#else /* !MBEDTLS_GCM_ALT */
#include "gcm_alt.h"
#endif /* !MBEDTLS_GCM_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
@ -217,4 +231,5 @@ int mbedtls_gcm_self_test( int verbose );
} }
#endif #endif
#endif /* gcm.h */ #endif /* gcm.h */

View file

@ -1,7 +1,7 @@
/** /**
* \file timing.h * \file timing.h
* *
* \brief Portable interface to the CPU cycle counter * \brief Portable interface to timeouts and to the CPU cycle counter
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
@ -65,6 +65,9 @@ extern volatile int mbedtls_timing_alarmed;
* \warning This is only a best effort! Do not rely on this! * \warning This is only a best effort! Do not rely on this!
* In particular, it is known to be unreliable on virtual * In particular, it is known to be unreliable on virtual
* machines. * machines.
*
* \note This value starts at an unspecified origin and
* may wrap around.
*/ */
unsigned long mbedtls_timing_hardclock( void ); unsigned long mbedtls_timing_hardclock( void );
@ -72,7 +75,18 @@ unsigned long mbedtls_timing_hardclock( void );
* \brief Return the elapsed time in milliseconds * \brief Return the elapsed time in milliseconds
* *
* \param val points to a timer structure * \param val points to a timer structure
* \param reset if set to 1, the timer is restarted * \param reset If 0, query the elapsed time. Otherwise (re)start the timer.
*
* \return Elapsed time since the previous reset in ms. When
* restarting, this is always 0.
*
* \note To initialize a timer, call this function with reset=1.
*
* Determining the elapsed time and resetting the timer is not
* atomic on all platforms, so after the sequence
* `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 =
* get_timer(0) }` the value time1+time2 is only approximately
* the delay since the first reset.
*/ */
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset );
@ -80,6 +94,7 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int
* \brief Setup an alarm clock * \brief Setup an alarm clock
* *
* \param seconds delay before the "mbedtls_timing_alarmed" flag is set * \param seconds delay before the "mbedtls_timing_alarmed" flag is set
* (must be >=0)
* *
* \warning Only one alarm at a time is supported. In a threaded * \warning Only one alarm at a time is supported. In a threaded
* context, this means one for the whole process, not one per * context, this means one for the whole process, not one per
@ -91,11 +106,15 @@ void mbedtls_set_alarm( int seconds );
* \brief Set a pair of delays to watch * \brief Set a pair of delays to watch
* (See \c mbedtls_timing_get_delay().) * (See \c mbedtls_timing_get_delay().)
* *
* \param data Pointer to timing data * \param data Pointer to timing data.
* Must point to a valid \c mbedtls_timing_delay_context struct. * Must point to a valid \c mbedtls_timing_delay_context struct.
* \param int_ms First (intermediate) delay in milliseconds. * \param int_ms First (intermediate) delay in milliseconds.
* The effect if int_ms > fin_ms is unspecified.
* \param fin_ms Second (final) delay in milliseconds. * \param fin_ms Second (final) delay in milliseconds.
* Pass 0 to cancel the current delay. * Pass 0 to cancel the current delay.
*
* \note To set a single delay, either use \c mbedtls_timing_set_timer
* directly or use this function with int_ms == fin_ms.
*/ */
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms );
@ -106,7 +125,7 @@ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms );
* \param data Pointer to timing data * \param data Pointer to timing data
* Must point to a valid \c mbedtls_timing_delay_context struct. * Must point to a valid \c mbedtls_timing_delay_context struct.
* *
* \return -1 if cancelled (fin_ms = 0) * \return -1 if cancelled (fin_ms = 0),
* 0 if none of the delays are passed, * 0 if none of the delays are passed,
* 1 if only the intermediate delay is passed, * 1 if only the intermediate delay is passed,
* 2 if the final delay is passed. * 2 if the final delay is passed.

View file

@ -1235,9 +1235,11 @@ static const int aes_test_ctr_len[3] =
*/ */
int mbedtls_aes_self_test( int verbose ) int mbedtls_aes_self_test( int verbose )
{ {
int ret = 0, i, j, u, v; int ret = 0, i, j, u, mode;
unsigned int keybits;
unsigned char key[32]; unsigned char key[32];
unsigned char buf[64]; unsigned char buf[64];
const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) #if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
unsigned char iv[16]; unsigned char iv[16];
#endif #endif
@ -1263,45 +1265,52 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
u = i >> 1; u = i >> 1;
v = i & 1; keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, mbedtls_printf( " AES-ECB-%3d (%s): ", keybits,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( buf, 0, 16 ); memset( buf, 0, 16 );
if( v == MBEDTLS_AES_DECRYPT ) if( mode == MBEDTLS_AES_DECRYPT )
{ {
mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
aes_tests = aes_test_ecb_dec[u];
for( j = 0; j < 10000; j++ )
mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
} }
else else
{ {
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
aes_tests = aes_test_ecb_enc[u];
}
for( j = 0; j < 10000; j++ ) /*
mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); * AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) for( j = 0; j < 10000; j++ )
{ {
if( verbose != 0 ) ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
mbedtls_printf( "failed\n" ); if( ret != 0 )
ret = 1;
goto exit; goto exit;
} }
if( memcmp( buf, aes_tests, 16 ) != 0 )
{
ret = 1;
goto exit;
} }
if( verbose != 0 ) if( verbose != 0 )
@ -1318,55 +1327,64 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
u = i >> 1; u = i >> 1;
v = i & 1; keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, mbedtls_printf( " AES-CBC-%3d (%s): ", keybits,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( iv , 0, 16 ); memset( iv , 0, 16 );
memset( prv, 0, 16 ); memset( prv, 0, 16 );
memset( buf, 0, 16 ); memset( buf, 0, 16 );
if( v == MBEDTLS_AES_DECRYPT ) if( mode == MBEDTLS_AES_DECRYPT )
{ {
mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
aes_tests = aes_test_cbc_dec[u];
for( j = 0; j < 10000; j++ )
mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
} }
else else
{ {
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
aes_tests = aes_test_cbc_enc[u];
}
for( j = 0; j < 10000; j++ ) /*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
for( j = 0; j < 10000; j++ )
{
if( mode == MBEDTLS_AES_ENCRYPT )
{ {
unsigned char tmp[16]; unsigned char tmp[16];
mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
memcpy( tmp, prv, 16 ); memcpy( tmp, prv, 16 );
memcpy( prv, buf, 16 ); memcpy( prv, buf, 16 );
memcpy( buf, tmp, 16 ); memcpy( buf, tmp, 16 );
} }
if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
{ if( ret != 0 )
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit; goto exit;
}
}
if( memcmp( buf, aes_tests, 16 ) != 0 )
{
ret = 1;
goto exit;
} }
if( verbose != 0 ) if( verbose != 0 )
@ -1384,45 +1402,52 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
u = i >> 1; u = i >> 1;
v = i & 1; keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( iv, aes_test_cfb128_iv, 16 ); memcpy( iv, aes_test_cfb128_iv, 16 );
memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
offset = 0; offset = 0;
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
if( v == MBEDTLS_AES_DECRYPT ) if( mode == MBEDTLS_AES_DECRYPT )
{ {
memcpy( buf, aes_test_cfb128_ct[u], 64 ); memcpy( buf, aes_test_cfb128_ct[u], 64 );
mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); aes_tests = aes_test_cfb128_pt;
if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
} }
else else
{ {
memcpy( buf, aes_test_cfb128_pt, 64 ); memcpy( buf, aes_test_cfb128_pt, 64 );
mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); aes_tests = aes_test_cfb128_ct[u];
}
if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
{ if( ret != 0 )
if( verbose != 0 ) goto exit;
mbedtls_printf( "failed\n" );
ret = 1; if( memcmp( buf, aes_tests, 64 ) != 0 )
goto exit; {
} ret = 1;
goto exit;
} }
if( verbose != 0 ) if( verbose != 0 )
@ -1440,51 +1465,41 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
u = i >> 1; u = i >> 1;
v = i & 1; mode = i & 1;
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-CTR-128 (%s): ", mbedtls_printf( " AES-CTR-128 (%s): ",
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
memcpy( key, aes_test_ctr_key[u], 16 ); memcpy( key, aes_test_ctr_key[u], 16 );
offset = 0; offset = 0;
mbedtls_aes_setkey_enc( &ctx, key, 128 ); if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
goto exit;
if( v == MBEDTLS_AES_DECRYPT ) len = aes_test_ctr_len[u];
if( mode == MBEDTLS_AES_DECRYPT )
{ {
len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_ct[u], len ); memcpy( buf, aes_test_ctr_ct[u], len );
aes_tests = aes_test_ctr_pt[u];
mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
buf, buf );
if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
} }
else else
{ {
len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_pt[u], len ); memcpy( buf, aes_test_ctr_pt[u], len );
aes_tests = aes_test_ctr_ct[u];
}
mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
buf, buf ); stream_block, buf, buf );
if( ret != 0 )
goto exit;
if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) if( memcmp( buf, aes_tests, len ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
ret = 1;
goto exit;
}
} }
if( verbose != 0 ) if( verbose != 0 )
@ -1498,6 +1513,9 @@ int mbedtls_aes_self_test( int verbose )
ret = 0; ret = 0;
exit: exit:
if( ret != 0 && verbose != 0 )
mbedtls_printf( "failed\n" );
mbedtls_aes_free( &ctx ); mbedtls_aes_free( &ctx );
return( ret ); return( ret );

View file

@ -49,6 +49,8 @@
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_CCM_ALT)
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@ -348,6 +350,7 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
return( 0 ); return( 0 );
} }
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/* /*

View file

@ -65,6 +65,8 @@
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@ -164,7 +166,9 @@ exit:
return( ret ); return( ret );
} }
#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
#if !defined(MBEDTLS_CMAC_ALT)
static void cmac_xor_block( unsigned char *output, const unsigned char *input1, static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
const unsigned char *input2, const unsigned char *input2,
const size_t block_size ) const size_t block_size )
@ -468,6 +472,8 @@ exit:
} }
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#endif /* !MBEDTLS_CMAC_ALT */
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/* /*
* CMAC test data for SP800-38B * CMAC test data for SP800-38B

View file

@ -520,6 +520,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "AES - Feature not available, e.g. unsupported AES key size" );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_ASN1_PARSE_C)

View file

@ -46,6 +46,7 @@
#endif #endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
@ -54,6 +55,8 @@
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_GCM_ALT)
/* /*
* 32-bit integer manipulation macros (big endian) * 32-bit integer manipulation macros (big endian)
*/ */
@ -508,6 +511,8 @@ void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
} }
#endif /* !MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/* /*
* AES-GCM test vectors from: * AES-GCM test vectors from:
@ -744,34 +749,48 @@ int mbedtls_gcm_self_test( int verbose )
int i, j, ret; int i, j, ret;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
mbedtls_gcm_init( &ctx );
for( j = 0; j < 3; j++ ) for( j = 0; j < 3; j++ )
{ {
int key_len = 128 + 64 * j; int key_len = 128 + 64 * j;
for( i = 0; i < MAX_TESTS; i++ ) for( i = 0; i < MAX_TESTS; i++ )
{ {
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "enc" ); key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
{
mbedtls_printf( "skipped\n" );
break;
}
else if( ret != 0 )
{
goto exit;
}
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
pt_len[i], pt_len[i],
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i], additional[add_index[i]], add_len[i],
pt[pt_index[i]], buf, 16, tag_buf ); pt[pt_index[i]], buf, 16, tag_buf );
if( ret != 0 )
goto exit;
if( ret != 0 || if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
@ -779,26 +798,31 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "dec" ); key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
pt_len[i], pt_len[i],
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i], additional[add_index[i]], add_len[i],
ct[j * 6 + i], buf, 16, tag_buf ); ct[j * 6 + i], buf, 16, tag_buf );
if( ret != 0 || if( ret != 0 )
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || goto exit;
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
@ -806,66 +830,51 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "enc" ); key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] ); additional[add_index[i]], add_len[i] );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 ) if( pt_len[i] > 32 )
{ {
size_t rest_len = pt_len[i] - 32; size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
buf + 32 ); buf + 32 );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
else else
{ {
ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 || if( ret != 0 )
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || goto exit;
if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
@ -873,80 +882,75 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "dec" ); key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] ); additional[add_index[i]], add_len[i] );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 ) if( pt_len[i] > 32 )
{ {
size_t rest_len = pt_len[i] - 32; size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
buf + 32 ); buf + 32 );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
else else
{ {
ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 || if( ret != 0 )
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || goto exit;
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
} }
} }
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); ret = 0;
exit:
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
mbedtls_gcm_free( &ctx );
}
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */

View file

@ -244,21 +244,23 @@ volatile int mbedtls_timing_alarmed = 0;
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{ {
unsigned long delta;
LARGE_INTEGER offset, hfreq;
struct _hr_time *t = (struct _hr_time *) val; struct _hr_time *t = (struct _hr_time *) val;
QueryPerformanceCounter( &offset );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( 1000 *
( offset.QuadPart - t->start.QuadPart ) ) /
hfreq.QuadPart );
if( reset ) if( reset )
{
QueryPerformanceCounter( &t->start ); QueryPerformanceCounter( &t->start );
return( 0 );
return( delta ); }
else
{
unsigned long delta;
LARGE_INTEGER now, hfreq;
QueryPerformanceCounter( &now );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
/ hfreq.QuadPart );
return( delta );
}
} }
/* It's OK to use a global because alarm() is supposed to be global anyway */ /* It's OK to use a global because alarm() is supposed to be global anyway */
@ -285,23 +287,22 @@ void mbedtls_set_alarm( int seconds )
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{ {
unsigned long delta;
struct timeval offset;
struct _hr_time *t = (struct _hr_time *) val; struct _hr_time *t = (struct _hr_time *) val;
gettimeofday( &offset, NULL );
if( reset ) if( reset )
{ {
t->start.tv_sec = offset.tv_sec; gettimeofday( &t->start, NULL );
t->start.tv_usec = offset.tv_usec;
return( 0 ); return( 0 );
} }
else
delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 {
+ ( offset.tv_usec - t->start.tv_usec ) / 1000; unsigned long delta;
struct timeval now;
return( delta ); gettimeofday( &now, NULL );
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
}
} }
static void sighandler( int signum ) static void sighandler( int signum )
@ -315,6 +316,12 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0; mbedtls_timing_alarmed = 0;
signal( SIGALRM, sighandler ); signal( SIGALRM, sighandler );
alarm( seconds ); alarm( seconds );
if( seconds == 0 )
{
/* alarm(0) cancelled any previous pending alarm, but the
handler won't fire, so raise the flag straight away. */
mbedtls_timing_alarmed = 1;
}
} }
#endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* _WIN32 && !EFIX64 && !EFI32 */
@ -378,13 +385,21 @@ static void busy_msleep( unsigned long msec )
(void) j; (void) j;
} }
#define FAIL do \ #define FAIL do \
{ \ { \
if( verbose != 0 ) \ if( verbose != 0 ) \
mbedtls_printf( "failed\n" ); \ { \
\ mbedtls_printf( "failed at line %d\n", __LINE__ ); \
return( 1 ); \ mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \
} while( 0 ) cycles, ratio, millisecs, secs, hardfail, \
(unsigned long) a, (unsigned long) b ); \
mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \
mbedtls_timing_get_timer( &hires, 0 ), \
mbedtls_timing_get_timer( &ctx.timer, 0 ), \
mbedtls_timing_get_delay( &ctx ) ); \
} \
return( 1 ); \
} while( 0 )
/* /*
* Checkup routine * Checkup routine
@ -394,22 +409,22 @@ static void busy_msleep( unsigned long msec )
*/ */
int mbedtls_timing_self_test( int verbose ) int mbedtls_timing_self_test( int verbose )
{ {
unsigned long cycles, ratio; unsigned long cycles = 0, ratio = 0;
unsigned long millisecs, secs; unsigned long millisecs = 0, secs = 0;
int hardfail; int hardfail = 0;
struct mbedtls_timing_hr_time hires; struct mbedtls_timing_hr_time hires;
uint32_t a, b; uint32_t a = 0, b = 0;
mbedtls_timing_delay_context ctx; mbedtls_timing_delay_context ctx;
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " TIMING tests note: will take some time!\n" ); mbedtls_printf( " TIMING tests note: will take some time!\n" );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " );
for( secs = 1; secs <= 3; secs++ )
{ {
secs = 1;
(void) mbedtls_timing_get_timer( &hires, 1 ); (void) mbedtls_timing_get_timer( &hires, 1 );
mbedtls_set_alarm( (int) secs ); mbedtls_set_alarm( (int) secs );
@ -421,12 +436,7 @@ int mbedtls_timing_self_test( int verbose )
/* For some reason on Windows it looks like alarm has an extra delay /* For some reason on Windows it looks like alarm has an extra delay
* (maybe related to creating a new thread). Allow some room here. */ * (maybe related to creating a new thread). Allow some room here. */
if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 )
{ FAIL;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
if( verbose != 0 ) if( verbose != 0 )
@ -435,28 +445,22 @@ int mbedtls_timing_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); mbedtls_printf( " TIMING test #2 (set/get_delay ): " );
for( a = 200; a <= 400; a += 200 )
{ {
for( b = 200; b <= 400; b += 200 ) a = 800;
{ b = 400;
mbedtls_timing_set_delay( &ctx, a, a + b ); mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */
busy_msleep( a - a / 8 ); busy_msleep( a - a / 4 ); /* T = a - a/4 */
if( mbedtls_timing_get_delay( &ctx ) != 0 ) if( mbedtls_timing_get_delay( &ctx ) != 0 )
FAIL; FAIL;
busy_msleep( a / 4 ); busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */
if( mbedtls_timing_get_delay( &ctx ) != 1 ) if( mbedtls_timing_get_delay( &ctx ) != 1 )
FAIL; FAIL;
busy_msleep( b - a / 8 - b / 8 ); busy_msleep( b ); /* T = a + b + b/4 */
if( mbedtls_timing_get_delay( &ctx ) != 1 ) if( mbedtls_timing_get_delay( &ctx ) != 2 )
FAIL; FAIL;
busy_msleep( b / 4 );
if( mbedtls_timing_get_delay( &ctx ) != 2 )
FAIL;
}
} }
mbedtls_timing_set_delay( &ctx, 0, 0 ); mbedtls_timing_set_delay( &ctx, 0, 0 );
@ -475,7 +479,6 @@ int mbedtls_timing_self_test( int verbose )
* On a 4Ghz 32-bit machine the cycle counter wraps about once per second; * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
* since the whole test is about 10ms, it shouldn't happen twice in a row. * since the whole test is about 10ms, it shouldn't happen twice in a row.
*/ */
hardfail = 0;
hard_test: hard_test:
if( hardfail > 1 ) if( hardfail > 1 )

View file

@ -96,12 +96,21 @@ static const char *features[] = {
#if defined(MBEDTLS_CAMELLIA_ALT) #if defined(MBEDTLS_CAMELLIA_ALT)
"MBEDTLS_CAMELLIA_ALT", "MBEDTLS_CAMELLIA_ALT",
#endif /* MBEDTLS_CAMELLIA_ALT */ #endif /* MBEDTLS_CAMELLIA_ALT */
#if defined(MBEDTLS_CCM_ALT)
"MBEDTLS_CCM_ALT",
#endif /* MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_CMAC_ALT)
"MBEDTLS_CMAC_ALT",
#endif /* MBEDTLS_CMAC_ALT */
#if defined(MBEDTLS_DES_ALT) #if defined(MBEDTLS_DES_ALT)
"MBEDTLS_DES_ALT", "MBEDTLS_DES_ALT",
#endif /* MBEDTLS_DES_ALT */ #endif /* MBEDTLS_DES_ALT */
#if defined(MBEDTLS_RSA_ALT) #if defined(MBEDTLS_RSA_ALT)
"MBEDTLS_RSA_ALT", "MBEDTLS_RSA_ALT",
#endif /* MBEDTLS_RSA_ALT */ #endif /* MBEDTLS_RSA_ALT */
#if defined(MBEDTLS_GCM_ALT)
"MBEDTLS_GCM_ALT",
#endif /* MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_XTEA_ALT) #if defined(MBEDTLS_XTEA_ALT)
"MBEDTLS_XTEA_ALT", "MBEDTLS_XTEA_ALT",
#endif /* MBEDTLS_XTEA_ALT */ #endif /* MBEDTLS_XTEA_ALT */

View file

@ -107,8 +107,8 @@ static int run_test_snprintf( void )
* self-test. If this fails, we attempt the test anyway, so no error is passed * self-test. If this fails, we attempt the test anyway, so no error is passed
* back. * back.
*/ */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_ENTROPY_C) && \ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_ENTROPY_C)
defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
static void create_entropy_seed_file( void ) static void create_entropy_seed_file( void )
{ {
int result; int result;
@ -136,9 +136,137 @@ static void create_entropy_seed_file( void )
} }
#endif #endif
int mbedtls_entropy_self_test_wrapper( int verbose )
{
#if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
create_entropy_seed_file( );
#endif
return( mbedtls_entropy_self_test( verbose ) );
}
#endif
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
int mbedtls_memory_buffer_alloc_free_and_self_test( int verbose )
{
if( verbose != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_status( );
#endif
}
mbedtls_memory_buffer_alloc_free( );
return( mbedtls_memory_buffer_alloc_self_test( verbose ) );
}
#endif
typedef struct
{
const char *name;
int ( *function )( int );
} selftest_t;
const selftest_t selftests[] =
{
#if defined(MBEDTLS_MD2_C)
{"md2", mbedtls_md2_self_test},
#endif
#if defined(MBEDTLS_MD4_C)
{"md4", mbedtls_md4_self_test},
#endif
#if defined(MBEDTLS_MD5_C)
{"md5", mbedtls_md5_self_test},
#endif
#if defined(MBEDTLS_RIPEMD160_C)
{"ripemd160", mbedtls_ripemd160_self_test},
#endif
#if defined(MBEDTLS_SHA1_C)
{"sha1", mbedtls_sha1_self_test},
#endif
#if defined(MBEDTLS_SHA256_C)
{"sha256", mbedtls_sha256_self_test},
#endif
#if defined(MBEDTLS_SHA512_C)
{"sha512", mbedtls_sha512_self_test},
#endif
#if defined(MBEDTLS_ARC4_C)
{"arc4", mbedtls_arc4_self_test},
#endif
#if defined(MBEDTLS_DES_C)
{"des", mbedtls_des_self_test},
#endif
#if defined(MBEDTLS_AES_C)
{"aes", mbedtls_aes_self_test},
#endif
#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)
{"gcm", mbedtls_gcm_self_test},
#endif
#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)
{"ccm", mbedtls_ccm_self_test},
#endif
#if defined(MBEDTLS_CMAC_C)
{"cmac", mbedtls_cmac_self_test},
#endif
#if defined(MBEDTLS_BASE64_C)
{"base64", mbedtls_base64_self_test},
#endif
#if defined(MBEDTLS_BIGNUM_C)
{"mpi", mbedtls_mpi_self_test},
#endif
#if defined(MBEDTLS_RSA_C)
{"rsa", mbedtls_rsa_self_test},
#endif
#if defined(MBEDTLS_X509_USE_C)
{"x509", mbedtls_x509_self_test},
#endif
#if defined(MBEDTLS_XTEA_C)
{"xtea", mbedtls_xtea_self_test},
#endif
#if defined(MBEDTLS_CAMELLIA_C)
{"camellia", mbedtls_camellia_self_test},
#endif
#if defined(MBEDTLS_CTR_DRBG_C)
{"ctr_drbg", mbedtls_ctr_drbg_self_test},
#endif
#if defined(MBEDTLS_HMAC_DRBG_C)
{"hmac_drbg", mbedtls_hmac_drbg_self_test},
#endif
#if defined(MBEDTLS_ECP_C)
{"ecp", mbedtls_ecp_self_test},
#endif
#if defined(MBEDTLS_ECJPAKE_C)
{"ecjpake", mbedtls_ecjpake_self_test},
#endif
#if defined(MBEDTLS_DHM_C)
{"dhm", mbedtls_dhm_self_test},
#endif
#if defined(MBEDTLS_ENTROPY_C)
{"entropy", mbedtls_entropy_self_test_wrapper},
#endif
#if defined(MBEDTLS_PKCS5_C)
{"pkcs5", mbedtls_pkcs5_self_test},
#endif
/* Slower test after the faster ones */
#if defined(MBEDTLS_TIMING_C)
{"timing", mbedtls_timing_self_test},
#endif
/* Heap test comes last */
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
{"memory_buffer_alloc", mbedtls_memory_buffer_alloc_free_and_self_test},
#endif
{NULL, NULL}
};
#endif /* MBEDTLS_SELF_TEST */
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
{ {
int v, suites_tested = 0, suites_failed = 0; #if defined(MBEDTLS_SELF_TEST)
const selftest_t *test;
#endif /* MBEDTLS_SELF_TEST */
char **argp;
int v = 1; /* v=1 for verbose mode */
int exclude_mode = 0;
int suites_tested = 0, suites_failed = 0;
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_SELF_TEST)
unsigned char buf[1000000]; unsigned char buf[1000000];
#endif #endif
@ -165,16 +293,24 @@ int main( int argc, char *argv[] )
mbedtls_exit( MBEDTLS_EXIT_FAILURE ); mbedtls_exit( MBEDTLS_EXIT_FAILURE );
} }
if( argc == 2 && ( strcmp( argv[1], "--quiet" ) == 0 || for( argp = argv + ( argc >= 1 ? 1 : argc ); *argp != NULL; ++argp )
strcmp( argv[1], "-q" ) == 0 ) )
{ {
v = 0; if( strcmp( *argp, "--quiet" ) == 0 ||
strcmp( *argp, "-q" ) == 0 )
{
v = 0;
}
else if( strcmp( *argp, "--exclude" ) == 0 ||
strcmp( *argp, "-x" ) == 0 )
{
exclude_mode = 1;
}
else
break;
} }
else
{ if( v != 0 )
v = 1;
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
}
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
@ -182,246 +318,60 @@ int main( int argc, char *argv[] )
mbedtls_memory_buffer_alloc_init( buf, sizeof(buf) ); mbedtls_memory_buffer_alloc_init( buf, sizeof(buf) );
#endif #endif
#if defined(MBEDTLS_MD2_C) if( *argp != NULL && exclude_mode == 0 )
if( mbedtls_md2_self_test( v ) != 0 )
{ {
suites_failed++; /* Run the specified tests */
for( ; *argp != NULL; argp++ )
{
for( test = selftests; test->name != NULL; test++ )
{
if( !strcmp( *argp, test->name ) )
{
if( test->function( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
break;
}
}
if( test->name == NULL )
{
mbedtls_printf( " Test suite %s not available -> failed\n\n", *argp );
suites_failed++;
}
}
} }
suites_tested++; else
#endif
#if defined(MBEDTLS_MD4_C)
if( mbedtls_md4_self_test( v ) != 0 )
{ {
suites_failed++; /* Run all the tests except excluded ones */
for( test = selftests; test->name != NULL; test++ )
{
if( exclude_mode )
{
char **excluded;
for( excluded = argp; *excluded != NULL; ++excluded )
{
if( !strcmp( *excluded, test->name ) )
break;
}
if( *excluded )
{
if( v )
mbedtls_printf( " Skip: %s\n", test->name );
continue;
}
}
if( test->function( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
}
} }
suites_tested++;
#endif
#if defined(MBEDTLS_MD5_C)
if( mbedtls_md5_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_RIPEMD160_C)
if( mbedtls_ripemd160_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_SHA1_C)
if( mbedtls_sha1_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_SHA256_C)
if( mbedtls_sha256_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_SHA512_C)
if( mbedtls_sha512_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_ARC4_C)
if( mbedtls_arc4_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_DES_C)
if( mbedtls_des_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_AES_C)
if( mbedtls_aes_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)
if( mbedtls_gcm_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)
if( mbedtls_ccm_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_CMAC_C)
if( ( mbedtls_cmac_self_test( v ) ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_BASE64_C)
if( mbedtls_base64_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_BIGNUM_C)
if( mbedtls_mpi_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_RSA_C)
if( mbedtls_rsa_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_X509_USE_C)
if( mbedtls_x509_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_XTEA_C)
if( mbedtls_xtea_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_CAMELLIA_C)
if( mbedtls_camellia_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_CTR_DRBG_C)
if( mbedtls_ctr_drbg_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_HMAC_DRBG_C)
if( mbedtls_hmac_drbg_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_ECP_C)
if( mbedtls_ecp_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_ECJPAKE_C)
if( mbedtls_ecjpake_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_DHM_C)
if( mbedtls_dhm_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_ENTROPY_C)
#if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
create_entropy_seed_file();
#endif
if( mbedtls_entropy_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#if defined(MBEDTLS_PKCS5_C)
if( mbedtls_pkcs5_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
/* Slow tests last */
#if defined(MBEDTLS_TIMING_C)
if( mbedtls_timing_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#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( mbedtls_memory_buffer_alloc_self_test( v ) != 0 )
{
suites_failed++;
}
suites_tested++;
#endif
#else #else
(void) exclude_mode;
mbedtls_printf( " MBEDTLS_SELF_TEST not defined.\n" ); mbedtls_printf( " MBEDTLS_SELF_TEST not defined.\n" );
#endif #endif

View file

@ -45,7 +45,7 @@ my $config_file = "include/mbedtls/config.h";
my $usage = <<EOU; my $usage = <<EOU;
$0 [-f <file> | --file <file>] [-o | --force] $0 [-f <file> | --file <file>] [-o | --force]
[set <symbol> <value> | unset <symbol> | get <symbol> | [set <symbol> <value> | unset <symbol> | get <symbol> |
full | realfull] full | realfull | baremetal]
Commands Commands
set <symbol> [<value>] - Uncomments or adds a #define for the <symbol> to set <symbol> [<value>] - Uncomments or adds a #define for the <symbol> to
@ -63,6 +63,7 @@ Commands
excluding some reserved symbols, until the excluding some reserved symbols, until the
'Module configuration options' section 'Module configuration options' section
realfull - Uncomments all #define's with no exclusions realfull - Uncomments all #define's with no exclusions
baremetal - Sets full configuration suitable for baremetal build.
Options Options
-f | --file <filename> - The file or file path for the configuration file -f | --file <filename> - The file or file path for the configuration file
@ -91,14 +92,38 @@ MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
MBEDTLS_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT
MBEDTLS_PKCS11_C MBEDTLS_PKCS11_C
MBEDTLS_NO_UDBL_DIVISION
_ALT\s*$ _ALT\s*$
); );
# Things that should be disabled in "baremetal"
my @excluded_baremetal = qw(
MBEDTLS_NET_C
MBEDTLS_TIMING_C
MBEDTLS_FS_IO
MBEDTLS_ENTROPY_NV_SEED
MBEDTLS_HAVE_TIME
MBEDTLS_HAVE_TIME_DATE
MBEDTLS_DEPRECATED_WARNING
MBEDTLS_HAVEGE_C
MBEDTLS_THREADING_C
MBEDTLS_THREADING_PTHREAD
MBEDTLS_MEMORY_BACKTRACE
MBEDTLS_MEMORY_BUFFER_ALLOC_C
MBEDTLS_PLATFORM_TIME_ALT
MBEDTLS_PLATFORM_FPRINTF_ALT
);
# Things that should be enabled in "full" even if they match @excluded # Things that should be enabled in "full" even if they match @excluded
my @non_excluded = qw( my @non_excluded = qw(
PLATFORM_[A-Z0-9]+_ALT PLATFORM_[A-Z0-9]+_ALT
); );
# Things that should be enabled in "baremetal"
my @non_excluded_baremetal = qw(
MBEDTLS_NO_PLATFORM_ENTROPY
);
# Process the command line arguments # Process the command line arguments
my $force_option = 0; my $force_option = 0;
@ -123,7 +148,7 @@ while ($arg = shift) {
# ...else assume it's a command # ...else assume it's a command
$action = $arg; $action = $arg;
if ($action eq "full" || $action eq "realfull") { if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
# No additional parameters # No additional parameters
die $usage if @ARGV; die $usage if @ARGV;
@ -166,7 +191,12 @@ open my $config_read, '<', $config_file or die "read $config_file: $!\n";
my @config_lines = <$config_read>; my @config_lines = <$config_read>;
close $config_read; close $config_read;
my ($exclude_re, $no_exclude_re); # Add required baremetal symbols to the list that is included.
if ( $action eq "baremetal" ) {
@non_excluded = ( @non_excluded, @non_excluded_baremetal );
}
my ($exclude_re, $no_exclude_re, $exclude_baremetal_re);
if ($action eq "realfull") { if ($action eq "realfull") {
$exclude_re = qr/^$/; $exclude_re = qr/^$/;
$no_exclude_re = qr/./; $no_exclude_re = qr/./;
@ -174,6 +204,9 @@ if ($action eq "realfull") {
$exclude_re = join '|', @excluded; $exclude_re = join '|', @excluded;
$no_exclude_re = join '|', @non_excluded; $no_exclude_re = join '|', @non_excluded;
} }
if ( $action eq "baremetal" ) {
$exclude_baremetal_re = join '|', @excluded_baremetal;
}
my $config_write = undef; my $config_write = undef;
if ($action ne "get") { if ($action ne "get") {
@ -182,17 +215,19 @@ if ($action ne "get") {
my $done; my $done;
for my $line (@config_lines) { for my $line (@config_lines) {
if ($action eq "full" || $action eq "realfull") { if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
if ($line =~ /name SECTION: Module configuration options/) { if ($line =~ /name SECTION: Module configuration options/) {
$done = 1; $done = 1;
} }
if (!$done && $line =~ m!^//\s?#define! && if (!$done && $line =~ m!^//\s?#define! &&
( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) ) { ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) {
$line =~ s!^//\s?!!; $line =~ s!^//\s?!!;
} }
if (!$done && $line =~ m!^\s?#define! && if (!$done && $line =~ m!^\s?#define! &&
! ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) ) { ! ( ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) ) {
$line =~ s!^!//!; $line =~ s!^!//!;
} }
} elsif ($action eq "unset") { } elsif ($action eq "unset") {

View file

@ -4,20 +4,78 @@
# #
# This file is part of mbed TLS (https://tls.mbed.org) # This file is part of mbed TLS (https://tls.mbed.org)
# #
# Copyright (c) 2014-2016, ARM Limited, All Rights Reserved # Copyright (c) 2014-2017, ARM Limited, All Rights Reserved
#
################################################################
#### Documentation
################################################################
# Purpose # Purpose
# -------
# #
# To run all tests possible or available on the platform. # To run all tests possible or available on the platform.
# #
# Notes for users
# ---------------
#
# Warning: the test is destructive. It includes various build modes and # Warning: the test is destructive. It includes various build modes and
# configurations, and can and will arbitrarily change the current CMake # configurations, and can and will arbitrarily change the current CMake
# configuration. After this script has been run, the CMake cache will be lost # configuration. The following files must be committed into git:
# and CMake will no longer be initialised. # * include/mbedtls/config.h
# * Makefile, library/Makefile, programs/Makefile, tests/Makefile
# After running this script, the CMake cache will be lost and CMake
# will no longer be initialised.
# #
# The script assumes the presence of gcc and clang (recent enough for using # The script assumes the presence of a number of tools:
# ASan with gcc and MemSan with clang, or valgrind) are available, as well as # * Basic Unix tools (Windows users note: a Unix-style find must be before
# cmake and a "good" find. # the Windows find in the PATH)
# * Perl
# * GNU Make
# * CMake
# * GCC and Clang (recent enough for using ASan with gcc and MemSan with clang, or valgrind)
# * arm-gcc and mingw-gcc
# * ArmCC 5 and ArmCC 6, unless invoked with --no-armcc
# * Yotta build dependencies, unless invoked with --no-yotta
# * OpenSSL and GnuTLS command line tools, recent enough for the
# interoperability tests. If they don't support SSLv3 then a legacy
# version of these tools must be present as well (search for LEGACY
# below).
# See the invocation of check_tools below for details.
#
# This script must be invoked from the toplevel directory of a git
# working copy of Mbed TLS.
#
# Note that the output is not saved. You may want to run
# script -c tests/scripts/all.sh
# or
# tests/scripts/all.sh >all.log 2>&1
#
# Notes for maintainers
# ---------------------
#
# The tests are roughly in order from fastest to slowest. This doesn't
# have to be exact, but in general you should add slower tests towards
# the end and fast checks near the beginning.
#
# Sanity checks have the following form:
# 1. msg "short description of what is about to be done"
# 2. run sanity check (failure stops the script)
#
# Build or build-and-test steps have the following form:
# 1. msg "short description of what is about to be done"
# 2. cleanup
# 3. preparation (config.pl, cmake, ...) (failure stops the script)
# 4. make
# 5. Run tests if relevant. All tests must be prefixed with
# if_build_successful for the sake of --keep-going.
################################################################
#### Initialization and command line parsing
################################################################
# Abort on errors (and uninitialised variables) # Abort on errors (and uninitialised variables)
set -eu set -eu
@ -35,7 +93,9 @@ CONFIG_BAK="$CONFIG_H.bak"
MEMORY=0 MEMORY=0
FORCE=0 FORCE=0
KEEP_GOING=0
RELEASE=0 RELEASE=0
RUN_ARMCC=1
YOTTA=1 YOTTA=1
# Default commands, can be overriden by the environment # Default commands, can be overriden by the environment
@ -56,28 +116,38 @@ fi
usage() usage()
{ {
printf "Usage: $0\n" cat <<EOF
printf " -h|--help\t\tPrint this help.\n" Usage: $0 [OPTION]...
printf " -m|--memory\t\tAdditional optional memory tests.\n" -h|--help Print this help.
printf " -f|--force\t\tForce the tests to overwrite any modified files.\n"
printf " -s|--seed\t\tInteger seed value to use for this test run.\n" General options:
printf " -r|--release-test\t\tRun this script in release mode. This fixes the seed value to 1.\n" -f|--force Force the tests to overwrite any modified files.
printf " --no-yotta\t\tSkip yotta build\n" -k|--keep-going Run all tests and report errors at the end.
printf " --out-of-source-dir=<path>\t\tDirectory used for CMake out-of-source build tests." -m|--memory Additional optional memory tests.
printf " --openssl=<OpenSSL_path>\t\tPath to OpenSSL executable to use for most tests.\n" --armcc Run ARM Compiler builds (on by default).
printf " --openssl-legacy=<OpenSSL_path>\t\tPath to OpenSSL executable to use for legacy tests e.g. SSLv3.\n" --no-armcc Skip ARM Compiler builds.
printf " --gnutls-cli=<GnuTLS_cli_path>\t\tPath to GnuTLS client executable to use for most tests.\n" --no-yotta Skip yotta module build.
printf " --gnutls-serv=<GnuTLS_serv_path>\t\tPath to GnuTLS server executable to use for most tests.\n" --out-of-source-dir=<path> Directory used for CMake out-of-source build tests.
printf " --gnutls-legacy-cli=<GnuTLS_cli_path>\t\tPath to GnuTLS client executable to use for legacy tests.\n" -r|--release-test Run this script in release mode. This fixes the seed value to 1.
printf " --gnutls-legacy-serv=<GnuTLS_serv_path>\t\tPath to GnuTLS server executable to use for legacy tests.\n" -s|--seed Integer seed value to use for this test run.
printf " --armc5-bin-dir=<ARMC5_bin_dir_path>\t\tPath to the ARM Compiler 5 bin directory.\n" --yotta Build yotta module (on by default).
printf " --armc6-bin-dir=<ARMC6_bin_dir_path>\t\tPath to the ARM Compiler 6 bin directory.\n"
Tool path options:
--armc5-bin-dir=<ARMC5_bin_dir_path> ARM Compiler 5 bin directory.
--armc6-bin-dir=<ARMC6_bin_dir_path> ARM Compiler 6 bin directory.
--gnutls-cli=<GnuTLS_cli_path> GnuTLS client executable to use for most tests.
--gnutls-serv=<GnuTLS_serv_path> GnuTLS server executable to use for most tests.
--gnutls-legacy-cli=<GnuTLS_cli_path> GnuTLS client executable to use for legacy tests.
--gnutls-legacy-serv=<GnuTLS_serv_path> GnuTLS server executable to use for legacy tests.
--openssl=<OpenSSL_path> OpenSSL executable to use for most tests.
--openssl-legacy=<OpenSSL_path> OpenSSL executable to use for legacy tests e.g. SSLv3.
EOF
} }
# remove built files as well as the cmake cache/config # remove built files as well as the cmake cache/config
cleanup() cleanup()
{ {
make clean command make clean
find . -name yotta -prune -o -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 rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
@ -89,7 +159,21 @@ cleanup()
fi fi
} }
trap cleanup INT TERM HUP # Executed on exit. May be redefined depending on command line options.
final_report () {
:
}
fatal_signal () {
cleanup
final_report $1
trap - $1
kill -$1 $$
}
trap 'fatal_signal HUP' HUP
trap 'fatal_signal INT' INT
trap 'fatal_signal TERM' TERM
msg() msg()
{ {
@ -98,17 +182,20 @@ msg()
echo "* $1 " echo "* $1 "
printf "* "; date printf "* "; date
echo "******************************************************************" echo "******************************************************************"
current_section=$1
} }
armc6_build_test() if [ $RUN_ARMCC -ne 0 ]; then
{ armc6_build_test()
FLAGS="$1" {
FLAGS="$1"
msg "build: ARM Compiler 6 ($FLAGS), make" msg "build: ARM Compiler 6 ($FLAGS), make"
ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \ ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \
WARNING_CFLAGS='-xc -std=c99' make lib WARNING_CFLAGS='-xc -std=c99' make lib
make clean make clean
} }
fi
err_msg() err_msg()
{ {
@ -127,49 +214,8 @@ check_tools()
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
--memory|-m*) --armcc)
MEMORY=${1#-m} RUN_ARMCC=1
;;
--force|-f)
FORCE=1
;;
--seed|-s)
shift
SEED="$1"
;;
--release-test|-r)
RELEASE=1
;;
--no-yotta)
YOTTA=0
;;
--out-of-source-dir)
shift
OUT_OF_SOURCE_DIR="$1"
;;
--openssl)
shift
OPENSSL="$1"
;;
--openssl-legacy)
shift
OPENSSL_LEGACY="$1"
;;
--gnutls-cli)
shift
GNUTLS_CLI="$1"
;;
--gnutls-serv)
shift
GNUTLS_SERV="$1"
;;
--gnutls-legacy-cli)
shift
GNUTLS_LEGACY_CLI="$1"
;;
--gnutls-legacy-serv)
shift
GNUTLS_LEGACY_SERV="$1"
;; ;;
--armc5-bin-dir) --armc5-bin-dir)
shift shift
@ -179,9 +225,67 @@ while [ $# -gt 0 ]; do
shift shift
ARMC6_BIN_DIR="$1" ARMC6_BIN_DIR="$1"
;; ;;
--help|-h|*) --force|-f)
FORCE=1
;;
--gnutls-cli)
shift
GNUTLS_CLI="$1"
;;
--gnutls-legacy-cli)
shift
GNUTLS_LEGACY_CLI="$1"
;;
--gnutls-legacy-serv)
shift
GNUTLS_LEGACY_SERV="$1"
;;
--gnutls-serv)
shift
GNUTLS_SERV="$1"
;;
--help|-h)
usage usage
exit 1 exit
;;
--keep-going|-k)
KEEP_GOING=1
;;
--memory|-m)
MEMORY=1
;;
--no-armcc)
RUN_ARMCC=0
;;
--no-yotta)
YOTTA=0
;;
--openssl)
shift
OPENSSL="$1"
;;
--openssl-legacy)
shift
OPENSSL_LEGACY="$1"
;;
--out-of-source-dir)
shift
OUT_OF_SOURCE_DIR="$1"
;;
--release-test|-r)
RELEASE=1
;;
--seed|-s)
shift
SEED="$1"
;;
--yotta)
YOTTA=1
;;
*)
echo >&2 "Unknown option: $1"
echo >&2 "Run $0 --help for usage."
exit 120
;; ;;
esac esac
shift shift
@ -195,7 +299,7 @@ if [ $FORCE -eq 1 ]; then
cleanup cleanup
else else
if [ $YOTTA -eq 1 ] && [ -d yotta/module ]; then if [ $YOTTA -ne 0 ] && [ -d yotta/module ]; then
err_msg "Warning - there is an existing yotta module in the directory 'yotta/module'" err_msg "Warning - there is an existing yotta module in the directory 'yotta/module'"
echo "You can either delete your work and retry, or force the test to overwrite the" echo "You can either delete your work and retry, or force the test to overwrite the"
echo "test by rerunning the script as: $0 --force" echo "test by rerunning the script as: $0 --force"
@ -210,7 +314,6 @@ else
fi fi
if ! git diff-files --quiet include/mbedtls/config.h; then if ! git diff-files --quiet include/mbedtls/config.h; then
echo $?
err_msg "Warning - the configuration file 'include/mbedtls/config.h' has been edited. " err_msg "Warning - the configuration file 'include/mbedtls/config.h' has been edited. "
echo "You can either delete or preserve your work, or force the test by rerunning the" echo "You can either delete or preserve your work, or force the test by rerunning the"
echo "script as: $0 --force" echo "script as: $0 --force"
@ -218,6 +321,71 @@ else
fi fi
fi fi
build_status=0
if [ $KEEP_GOING -eq 1 ]; then
failure_summary=
failure_count=0
start_red=
end_color=
if [ -t 1 ]; then
case "$TERM" in
*color*|cygwin|linux|rxvt*|screen|[Eex]term*)
start_red=$(printf '\033[31m')
end_color=$(printf '\033[0m')
;;
esac
fi
record_status () {
if "$@"; then
last_status=0
else
last_status=$?
text="$current_section: $* -> $last_status"
failure_summary="$failure_summary
$text"
failure_count=$((failure_count + 1))
echo "${start_red}^^^^$text^^^^${end_color}"
fi
}
make () {
case "$*" in
*test|*check)
if [ $build_status -eq 0 ]; then
record_status command make "$@"
else
echo "(skipped because the build failed)"
fi
;;
*)
record_status command make "$@"
build_status=$last_status
;;
esac
}
final_report () {
if [ $failure_count -gt 0 ]; then
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "${start_red}FAILED: $failure_count${end_color}$failure_summary"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
elif [ -z "${1-}" ]; then
echo "SUCCESS :)"
fi
if [ -n "${1-}" ]; then
echo "Killed by SIG$1."
fi
}
else
record_status () {
"$@"
}
fi
if_build_succeeded () {
if [ $build_status -eq 0 ]; then
record_status "$@"
fi
}
if [ $RELEASE -eq 1 ]; then if [ $RELEASE -eq 1 ]; then
# Fix the seed value to 1 to ensure that the tests are deterministic. # Fix the seed value to 1 to ensure that the tests are deterministic.
SEED=1 SEED=1
@ -252,9 +420,17 @@ export GNUTLS_SERV="$GNUTLS_SERV"
# Make sure the tools we need are available. # Make sure the tools we need are available.
check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \ check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \
"$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \ "$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \
"arm-none-eabi-gcc" "$ARMC5_CC" "$ARMC5_AR" "$ARMC6_CC" "$ARMC6_AR" \ "arm-none-eabi-gcc" "i686-w64-mingw32-gcc"
"i686-w64-mingw32-gcc" if [ $RUN_ARMCC -ne 0 ]; then
check_tools "$ARMC5_CC" "$ARMC5_AR" "$ARMC6_CC" "$ARMC6_AR"
fi
################################################################
#### Basic checks
################################################################
# #
# Test Suites to be executed # Test Suites to be executed
@ -290,12 +466,18 @@ msg "test: doxygen warnings" # ~ 3s
cleanup cleanup
tests/scripts/doxygen.sh tests/scripts/doxygen.sh
if [ $YOTTA -ne 0 ]; then
# Note - use of yotta is deprecated, and yotta also requires armcc to be
# on the path, and uses whatever version of armcc it finds there. ################################################################
#### Build and test many configurations and targets
################################################################
if [ $RUN_ARMCC -ne 0 ] && [ $YOTTA -ne 0 ]; then
# Note - use of yotta is deprecated, and yotta also requires armcc to be on the
# path, and uses whatever version of armcc it finds there.
msg "build: create and build yotta module" # ~ 30s msg "build: create and build yotta module" # ~ 30s
cleanup cleanup
tests/scripts/yotta-build.sh record_status tests/scripts/yotta-build.sh
fi fi
msg "build: cmake, gcc, ASan" # ~ 1 min 50s msg "build: cmake, gcc, ASan" # ~ 1 min 50s
@ -307,16 +489,16 @@ msg "test: main suites (inc. selftests) (ASan build)" # ~ 50s
make test make test
msg "test: ssl-opt.sh (ASan build)" # ~ 1 min msg "test: ssl-opt.sh (ASan build)" # ~ 1 min
tests/ssl-opt.sh if_build_succeeded tests/ssl-opt.sh
msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s
tests/scripts/test-ref-configs.pl if_build_succeeded tests/scripts/test-ref-configs.pl
msg "build: with ASan (rebuild after ref-configs)" # ~ 1 min msg "build: with ASan (rebuild after ref-configs)" # ~ 1 min
make make
msg "test: compat.sh (ASan build)" # ~ 6 min msg "test: compat.sh (ASan build)" # ~ 6 min
tests/compat.sh if_build_succeeded tests/compat.sh
msg "build: Default + SSLv3 (ASan build)" # ~ 6 min msg "build: Default + SSLv3 (ASan build)" # ~ 6 min
cleanup cleanup
@ -329,11 +511,11 @@ msg "test: SSLv3 - main suites (inc. selftests) (ASan build)" # ~ 50s
make test make test
msg "build: SSLv3 - compat.sh (ASan build)" # ~ 6 min msg "build: SSLv3 - compat.sh (ASan build)" # ~ 6 min
tests/compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2' if_build_succeeded tests/compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2'
OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3' if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3'
msg "build: SSLv3 - ssl-opt.sh (ASan build)" # ~ 6 min msg "build: SSLv3 - ssl-opt.sh (ASan build)" # ~ 6 min
tests/ssl-opt.sh if_build_succeeded tests/ssl-opt.sh
msg "build: Default + !MBEDTLS_SSL_RENEGOTIATION (ASan build)" # ~ 6 min msg "build: Default + !MBEDTLS_SSL_RENEGOTIATION (ASan build)" # ~ 6 min
cleanup cleanup
@ -346,7 +528,7 @@ msg "test: !MBEDTLS_SSL_RENEGOTIATION - main suites (inc. selftests) (ASan build
make test make test
msg "test: !MBEDTLS_SSL_RENEGOTIATION - ssl-opt.sh (ASan build)" # ~ 6 min msg "test: !MBEDTLS_SSL_RENEGOTIATION - ssl-opt.sh (ASan build)" # ~ 6 min
tests/ssl-opt.sh if_build_succeeded tests/ssl-opt.sh
msg "build: cmake, full config, clang, C99" # ~ 50s msg "build: cmake, full config, clang, C99" # ~ 50s
cleanup cleanup
@ -354,30 +536,30 @@ cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On . CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic' make make CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic'
msg "test: main suites (full config)" # ~ 5s msg "test: main suites (full config)" # ~ 5s
CFLAGS='-Werror -Wall -Wextra' make test make CFLAGS='-Werror -Wall -Wextra' test
msg "test: ssl-opt.sh default (full config)" # ~ 1s msg "test: ssl-opt.sh default (full config)" # ~ 1s
tests/ssl-opt.sh -f Default if_build_succeeded tests/ssl-opt.sh -f Default
msg "test: compat.sh RC4, DES & NULL (full config)" # ~ 2 min msg "test: compat.sh RC4, DES & NULL (full config)" # ~ 2 min
OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR' if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR'
msg "test/build: curves.pl (gcc)" # ~ 4 min msg "test/build: curves.pl (gcc)" # ~ 4 min
cleanup cleanup
cmake -D CMAKE_BUILD_TYPE:String=Debug . cmake -D CMAKE_BUILD_TYPE:String=Debug .
tests/scripts/curves.pl if_build_succeeded tests/scripts/curves.pl
msg "test/build: key-exchanges (gcc)" # ~ 1 min msg "test/build: key-exchanges (gcc)" # ~ 1 min
cleanup cleanup
cmake -D CMAKE_BUILD_TYPE:String=Check . cmake -D CMAKE_BUILD_TYPE:String=Check .
tests/scripts/key-exchanges.pl if_build_succeeded tests/scripts/key-exchanges.pl
msg "build: Unix make, -Os (gcc)" # ~ 30s msg "build: Unix make, -Os (gcc)" # ~ 30s
cleanup cleanup
CC=gcc CFLAGS='-Werror -Wall -Wextra -Os' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
# Full configuration build, without platform support, file IO and net sockets. # Full configuration build, without platform support, file IO and net sockets.
# This should catch missing mbedtls_printf definitions, and by disabling file # This should catch missing mbedtls_printf definitions, and by disabling file
@ -399,8 +581,8 @@ scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl unset MBEDTLS_FS_IO scripts/config.pl unset MBEDTLS_FS_IO
# Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19, # Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19,
# to re-enable platform integration features otherwise disabled in C99 builds # to re-enable platform integration features otherwise disabled in C99 builds
CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' make lib programs make CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' make test make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' test
# catch compile bugs in _uninit functions # catch compile bugs in _uninit functions
msg "build: full config with NO_STD_FUNCTION, make, gcc" # ~ 30s msg "build: full config with NO_STD_FUNCTION, make, gcc" # ~ 30s
@ -409,21 +591,21 @@ cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full scripts/config.pl full
scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full scripts/config.pl full
scripts/config.pl unset MBEDTLS_SSL_SRV_C scripts/config.pl unset MBEDTLS_SSL_SRV_C
CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full scripts/config.pl full
scripts/config.pl unset MBEDTLS_SSL_CLI_C scripts/config.pl unset MBEDTLS_SSL_CLI_C
CC=gcc CFLAGS='-Werror -Wall -Werror -O0' make make CC=gcc CFLAGS='-Werror -Wall -Werror -O0'
# Note, C99 compliance can also be tested with the sockets support disabled, # Note, C99 compliance can also be tested with the sockets support disabled,
# as that requires a POSIX platform (which isn't the same as C99). # as that requires a POSIX platform (which isn't the same as C99).
@ -433,7 +615,7 @@ cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full scripts/config.pl full
scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc. scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc.
scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux
CC=gcc CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' make lib make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib
msg "build: default config except MFL extension (ASan build)" # ~ 30s msg "build: default config except MFL extension (ASan build)" # ~ 30s
cleanup cleanup
@ -443,7 +625,7 @@ CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make make
msg "test: ssl-opt.sh, MFL-related tests" msg "test: ssl-opt.sh, MFL-related tests"
tests/ssl-opt.sh -f "Max fragment length" if_build_succeeded tests/ssl-opt.sh -f "Max fragment length"
msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)" msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)"
cleanup cleanup
@ -461,42 +643,42 @@ msg "test: MBEDTLS_TEST_NULL_ENTROPY - main suites (inc. selftests) (ASan build)
make test make test
if uname -a | grep -F Linux >/dev/null; then if uname -a | grep -F Linux >/dev/null; then
msg "build/test: make shared" # ~ 40s msg "build/test: make shared" # ~ 40s
cleanup cleanup
make SHARED=1 all check make SHARED=1 all check
fi fi
if uname -a | grep -F x86_64 >/dev/null; then if uname -a | grep -F x86_64 >/dev/null; then
msg "build: i386, make, gcc" # ~ 30s msg "build: i386, make, gcc" # ~ 30s
cleanup cleanup
CC=gcc CFLAGS='-Werror -Wall -Wextra -m32' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -m32'
msg "build: gcc, force 32-bit compilation" msg "build: gcc, force 32-bit compilation"
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl unset MBEDTLS_HAVE_ASM scripts/config.pl unset MBEDTLS_HAVE_ASM
scripts/config.pl unset MBEDTLS_AESNI_C scripts/config.pl unset MBEDTLS_AESNI_C
scripts/config.pl unset MBEDTLS_PADLOCK_C scripts/config.pl unset MBEDTLS_PADLOCK_C
CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32'
msg "build: gcc, force 64-bit compilation" msg "build: gcc, force 64-bit compilation"
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl unset MBEDTLS_HAVE_ASM scripts/config.pl unset MBEDTLS_HAVE_ASM
scripts/config.pl unset MBEDTLS_AESNI_C scripts/config.pl unset MBEDTLS_AESNI_C
scripts/config.pl unset MBEDTLS_PADLOCK_C scripts/config.pl unset MBEDTLS_PADLOCK_C
CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
msg "test: gcc, force 64-bit compilation" msg "test: gcc, force 64-bit compilation"
make test make test
msg "build: gcc, force 64-bit compilation" msg "build: gcc, force 64-bit compilation"
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl unset MBEDTLS_HAVE_ASM scripts/config.pl unset MBEDTLS_HAVE_ASM
scripts/config.pl unset MBEDTLS_AESNI_C scripts/config.pl unset MBEDTLS_AESNI_C
scripts/config.pl unset MBEDTLS_PADLOCK_C scripts/config.pl unset MBEDTLS_PADLOCK_C
CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' make make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
fi # x86_64 fi # x86_64
msg "build: arm-none-eabi-gcc, make" # ~ 10s msg "build: arm-none-eabi-gcc, make" # ~ 10s
@ -514,7 +696,7 @@ scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
scripts/config.pl unset MBEDTLS_THREADING_C scripts/config.pl unset MBEDTLS_THREADING_C
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' make lib make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
cleanup cleanup
@ -532,7 +714,7 @@ scripts/config.pl unset MBEDTLS_THREADING_C
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' make lib make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
echo "Checking that software 64-bit division is not required" echo "Checking that software 64-bit division is not required"
! grep __aeabi_uldiv library/*.o ! grep __aeabi_uldiv library/*.o
@ -556,32 +738,34 @@ scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT # depends on MBEDTLS_HAVE_TIME scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT # depends on MBEDTLS_HAVE_TIME
CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' make lib if [ $RUN_ARMCC -ne 0 ]; then
make clean make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
make clean
# ARM Compiler 6 - Target ARMv7-A # ARM Compiler 6 - Target ARMv7-A
armc6_build_test "--target=arm-arm-none-eabi -march=armv7-a" armc6_build_test "--target=arm-arm-none-eabi -march=armv7-a"
# ARM Compiler 6 - Target ARMv7-M # ARM Compiler 6 - Target ARMv7-M
armc6_build_test "--target=arm-arm-none-eabi -march=armv7-m" armc6_build_test "--target=arm-arm-none-eabi -march=armv7-m"
# ARM Compiler 6 - Target ARMv8-A - AArch32 # ARM Compiler 6 - Target ARMv8-A - AArch32
armc6_build_test "--target=arm-arm-none-eabi -march=armv8.2-a" armc6_build_test "--target=arm-arm-none-eabi -march=armv8.2-a"
# ARM Compiler 6 - Target ARMv8-M # ARM Compiler 6 - Target ARMv8-M
armc6_build_test "--target=arm-arm-none-eabi -march=armv8-m.main" armc6_build_test "--target=arm-arm-none-eabi -march=armv8-m.main"
# ARM Compiler 6 - Target ARMv8-A - AArch64 # ARM Compiler 6 - Target ARMv8-A - AArch64
armc6_build_test "--target=aarch64-arm-none-eabi -march=armv8.2-a" armc6_build_test "--target=aarch64-arm-none-eabi -march=armv8.2-a"
fi
msg "build: allow SHA1 in certificates by default" msg "build: allow SHA1 in certificates by default"
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl set MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES scripts/config.pl set MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
CFLAGS='-Werror -Wall -Wextra' make make CFLAGS='-Werror -Wall -Wextra'
msg "test: allow SHA1 in certificates by default" msg "test: allow SHA1 in certificates by default"
make test make test
tests/ssl-opt.sh -f SHA-1 if_build_succeeded tests/ssl-opt.sh -f SHA-1
msg "build: default config, MBEDTLS_RSA_NO_CRT, make, gcc" msg "build: default config, MBEDTLS_RSA_NO_CRT, make, gcc"
cleanup cleanup
@ -594,63 +778,63 @@ make test
msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s
cleanup cleanup
CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 make lib programs make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs
# note Make tests only builds the tests, but doesn't run them # note Make tests only builds the tests, but doesn't run them
CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 make tests make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 tests
WINDOWS_BUILD=1 make clean make WINDOWS_BUILD=1 clean
msg "build: Windows cross build - mingw64, make (DLL)" # ~ 30s msg "build: Windows cross build - mingw64, make (DLL)" # ~ 30s
CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 make lib programs make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 lib programs
CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 make tests make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 tests
WINDOWS_BUILD=1 make clean make WINDOWS_BUILD=1 clean
# MemSan currently only available on Linux 64 bits # MemSan currently only available on Linux 64 bits
if uname -a | grep 'Linux.*x86_64' >/dev/null; then if uname -a | grep 'Linux.*x86_64' >/dev/null; then
msg "build: MSan (clang)" # ~ 1 min 20s msg "build: MSan (clang)" # ~ 1 min 20s
cleanup cleanup
cp "$CONFIG_H" "$CONFIG_BAK" cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm
CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan . CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
make make
msg "test: main suites (MSan)" # ~ 10s msg "test: main suites (MSan)" # ~ 10s
make test make test
msg "test: ssl-opt.sh (MSan)" # ~ 1 min msg "test: ssl-opt.sh (MSan)" # ~ 1 min
tests/ssl-opt.sh if_build_succeeded tests/ssl-opt.sh
# Optional part(s) # Optional part(s)
if [ "$MEMORY" -gt 0 ]; then if [ "$MEMORY" -gt 0 ]; then
msg "test: compat.sh (MSan)" # ~ 6 min 20s msg "test: compat.sh (MSan)" # ~ 6 min 20s
tests/compat.sh if_build_succeeded tests/compat.sh
fi fi
else # no MemSan else # no MemSan
msg "build: Release (clang)" msg "build: Release (clang)"
cleanup cleanup
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release . CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
make make
msg "test: main suites valgrind (Release)" msg "test: main suites valgrind (Release)"
make memcheck make memcheck
# Optional part(s) # Optional part(s)
# Currently broken, programs don't seem to receive signals # Currently broken, programs don't seem to receive signals
# under valgrind on OS X # under valgrind on OS X
if [ "$MEMORY" -gt 0 ]; then if [ "$MEMORY" -gt 0 ]; then
msg "test: ssl-opt.sh --memcheck (Release)" msg "test: ssl-opt.sh --memcheck (Release)"
tests/ssl-opt.sh --memcheck if_build_succeeded tests/ssl-opt.sh --memcheck
fi fi
if [ "$MEMORY" -gt 1 ]; then if [ "$MEMORY" -gt 1 ]; then
msg "test: compat.sh --memcheck (Release)" msg "test: compat.sh --memcheck (Release)"
tests/compat.sh --memcheck if_build_succeeded tests/compat.sh --memcheck
fi fi
fi # MemSan fi # MemSan
@ -667,5 +851,13 @@ make test
cd "$MBEDTLS_ROOT_DIR" cd "$MBEDTLS_ROOT_DIR"
rm -rf "$OUT_OF_SOURCE_DIR" rm -rf "$OUT_OF_SOURCE_DIR"
################################################################
#### Termination
################################################################
msg "Done, cleaning up" msg "Done, cleaning up"
cleanup cleanup
final_report

View file

@ -1,2 +1,41 @@
Timing selftest Timing: basic timer operation
timing_selftest: timing_timer_simple:
Timing: timer reset
timing_timer_reset:
Timing: two parallel timers, delay 0
timing_two_timers:0:
Timing: two parallel timers, delay 100
timing_two_timers:100:
Timing: two parallel timers, delay 1000
timing_two_timers:1000:
Timing: two parallel timers, delay 10000
timing_two_timers:10000:
Timing: delay 0ms, 0ms
timing_delay:0:0:
Timing: delay 0ms, 50ms
timing_delay:0:50:
Timing: delay 50ms, 50ms
timing_delay:50:50:
Timing: delay 50ms, 100ms
timing_delay:50:100:
Timing: delay 50ms, 200ms
timing_delay:50:200:
Timing: alarm in 0 second
timing_alarm:0:
Timing: alarm in 1 second
timing_alarm:1:
Timing: hardclock
timing_hardclock:

View file

@ -1,5 +1,51 @@
/* BEGIN_HEADER */ /* BEGIN_HEADER */
/* This test module exercises the timing module. One of the expected failure
modes is for timers to never expire, which could lead to an infinite loop.
The function timing_timer_simple is protected against this failure mode and
checks that timers do expire. Other functions will terminate if their
timers do expire. Therefore it is recommended to run timing_timer_simple
first and run other test functions only if that timing_timer_simple
succeeded. */
#include <limits.h>
#include "mbedtls/timing.h" #include "mbedtls/timing.h"
/* Wait this many milliseconds for a short timing test. This duration
should be large enough that, in practice, if you read the timer
value twice in a row, it won't have jumped by that much. */
#define TIMING_SHORT_TEST_MS 100
/* A loop that waits TIMING_SHORT_TEST_MS must not take more than this many
iterations. This value needs to be large enough to accommodate fast
platforms (e.g. at 4GHz and 10 cycles/iteration a CPU can run through 20
million iterations in 50ms). The only motivation to keep this value low is
to avoid having an infinite loop if the timer functions are not implemented
correctly. Ideally this value should be based on the processor speed but we
don't have this information! */
#define TIMING_SHORT_TEST_ITERATIONS_MAX 1e8
/* alarm(0) must fire in no longer than this amount of time. */
#define TIMING_ALARM_0_DELAY_MS TIMING_SHORT_TEST_MS
static int expected_delay_status( uint32_t int_ms, uint32_t fin_ms,
unsigned long actual_ms )
{
return( fin_ms == 0 ? -1 :
actual_ms >= fin_ms ? 2 :
actual_ms >= int_ms ? 1 :
0 );
}
/* Some conditions in timing_timer_simple suggest that timers are unreliable.
Most other test cases rely on timers to terminate, and could loop
indefinitely if timers are too broken. So if timing_timer_simple detected a
timer that risks not terminating (going backwards, or not reaching the
desired count in the alloted clock cycles), set this flag to immediately
fail those other tests without running any timers. */
static int timers_are_badly_broken = 0;
/* END_HEADER */ /* END_HEADER */
/* BEGIN_DEPENDENCIES /* BEGIN_DEPENDENCIES
@ -7,9 +53,351 @@
* END_DEPENDENCIES * END_DEPENDENCIES
*/ */
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ /* BEGIN_CASE */
void timing_selftest() void timing_timer_simple( )
{ {
TEST_ASSERT( mbedtls_timing_self_test( 1 ) == 0 ); struct mbedtls_timing_hr_time timer;
unsigned long millis = 0;
unsigned long new_millis = 0;
unsigned long iterations = 0;
/* Start the timer. */
(void) mbedtls_timing_get_timer( &timer, 1 );
/* Busy-wait loop for a few milliseconds. */
do
{
new_millis = mbedtls_timing_get_timer( &timer, 0 );
++iterations;
/* Check that the timer didn't go backwards */
TEST_ASSERT( new_millis >= millis );
millis = new_millis;
}
while( millis < TIMING_SHORT_TEST_MS &&
iterations <= TIMING_SHORT_TEST_ITERATIONS_MAX );
/* The wait duration should have been large enough for at least a
few runs through the loop, even on the slowest realistic platform. */
TEST_ASSERT( iterations >= 2 );
/* The wait duration shouldn't have overflowed the iteration count. */
TEST_ASSERT( iterations < TIMING_SHORT_TEST_ITERATIONS_MAX );
return;
exit:
if( iterations >= TIMING_SHORT_TEST_ITERATIONS_MAX ||
new_millis < millis )
{
/* The timer was very unreliable: it didn't increment and the loop ran
out, or it went backwards. Other tests that use timers might go
into an infinite loop, so we'll skip them. */
timers_are_badly_broken = 1;
}
/* No cleanup needed, but show some diagnostic iterations, because timing
problems can be hard to reproduce. */
mbedtls_fprintf( stdout, " Finished with millis=%lu new_millis=%lu get(timer)<=%lu iterations=%lu\n",
millis, new_millis, mbedtls_timing_get_timer( &timer, 0 ),
iterations );
}
/* END_CASE */
/* BEGIN_CASE */
void timing_timer_reset( )
{
struct mbedtls_timing_hr_time timer;
unsigned long millis = 0;
unsigned long iterations = 0;
/* Skip this test if it looks like timers don't work at all, to avoid an
infinite loop below. */
TEST_ASSERT( !timers_are_badly_broken );
/* Start the timer. Timers are always reset to 0. */
TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
/* Busy-wait loop for a few milliseconds */
do
{
++iterations;
millis = mbedtls_timing_get_timer( &timer, 0 );
}
while( millis < TIMING_SHORT_TEST_MS );
/* Reset the timer and check that it has restarted. */
TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
/* Read the timer immediately after reset. It should be 0 or close
to it. */
TEST_ASSERT( mbedtls_timing_get_timer( &timer, 0 ) < TIMING_SHORT_TEST_MS );
return;
exit:
/* No cleanup needed, but show some diagnostic information, because timing
problems can be hard to reproduce. */
if( !timers_are_badly_broken )
mbedtls_fprintf( stdout, " Finished with millis=%lu get(timer)<=%lu iterations=%lu\n",
millis, mbedtls_timing_get_timer( &timer, 0 ),
iterations );
}
/* END_CASE */
/* BEGIN_CASE */
void timing_two_timers( int delta )
{
struct mbedtls_timing_hr_time timer1, timer2;
unsigned long millis1 = 0, millis2 = 0;
/* Skip this test if it looks like timers don't work at all, to avoid an
infinite loop below. */
TEST_ASSERT( !timers_are_badly_broken );
/* Start the first timer and wait for a short time. */
(void) mbedtls_timing_get_timer( &timer1, 1 );
do
{
millis1 = mbedtls_timing_get_timer( &timer1, 0 );
}
while( millis1 < TIMING_SHORT_TEST_MS );
/* Do a short busy-wait, so that the difference between timer1 and timer2
doesn't practically always end up being very close to a whole number of
milliseconds. */
while( delta > 0 )
--delta;
/* Start the second timer and compare it with the first. */
mbedtls_timing_get_timer( &timer2, 1 );
do
{
millis1 = mbedtls_timing_get_timer( &timer1, 0 );
millis2 = mbedtls_timing_get_timer( &timer2, 0 );
/* The first timer should always be ahead of the first. */
TEST_ASSERT( millis1 > millis2 );
/* The timers shouldn't drift apart, i.e. millis2-millis1 should stay
roughly constant, but this is hard to test reliably, especially in
a busy environment such as an overloaded continuous integration
system, so we don't test it it. */
}
while( millis2 < TIMING_SHORT_TEST_MS );
return;
exit:
/* No cleanup needed, but show some diagnostic iterations, because timing
problems can be hard to reproduce. */
if( !timers_are_badly_broken )
mbedtls_fprintf( stdout, " Finished with millis1=%lu get(timer1)<=%lu millis2=%lu get(timer2)<=%lu\n",
millis1, mbedtls_timing_get_timer( &timer1, 0 ),
millis2, mbedtls_timing_get_timer( &timer2, 0 ) );
}
/* END_CASE */
/* BEGIN_CASE */
void timing_alarm( int seconds )
{
struct mbedtls_timing_hr_time timer;
unsigned long millis = 0;
/* We check that about the desired number of seconds has elapsed. Be
slightly liberal with the lower bound, so as to allow platforms where
the alarm (with second resolution) and the timer (with millisecond
resolution) are based on different clocks. Be very liberal with the
upper bound, because the platform might be busy. */
unsigned long millis_min = ( seconds > 0 ?
seconds * 900 :
0 );
unsigned long millis_max = ( seconds > 0 ?
seconds * 1100 + 400 :
TIMING_ALARM_0_DELAY_MS );
unsigned long iterations = 0;
/* Skip this test if it looks like timers don't work at all, to avoid an
infinite loop below. */
TEST_ASSERT( !timers_are_badly_broken );
/* Set an alarm and count how long it takes with a timer. */
(void) mbedtls_timing_get_timer( &timer, 1 );
mbedtls_set_alarm( seconds );
if( seconds > 0 )
{
/* We set the alarm for at least 1 second. It should not have fired
immediately, even on a slow and busy platform. */
TEST_ASSERT( !mbedtls_timing_alarmed );
}
/* A 0-second alarm should fire quickly, but we don't guarantee that it
fires immediately, so mbedtls_timing_alarmed may or may not be set at
this point. */
/* Busy-wait until the alarm rings */
do
{
++iterations;
millis = mbedtls_timing_get_timer( &timer, 0 );
}
while( !mbedtls_timing_alarmed && millis <= millis_max );
TEST_ASSERT( mbedtls_timing_alarmed );
TEST_ASSERT( millis >= millis_min );
TEST_ASSERT( millis <= millis_max );
mbedtls_timing_alarmed = 0;
return;
exit:
/* Show some diagnostic iterations, because timing
problems can be hard to reproduce. */
if( !timers_are_badly_broken )
mbedtls_fprintf( stdout, " Finished with alarmed=%d millis=%lu get(timer)<=%lu iterations=%lu\n",
mbedtls_timing_alarmed,
millis, mbedtls_timing_get_timer( &timer, 0 ),
iterations );
/* Cleanup */
mbedtls_timing_alarmed = 0;
}
/* END_CASE */
/* BEGIN_CASE */
void timing_delay( int int_ms, int fin_ms )
{
/* This function assumes that if int_ms is nonzero then it is large
enough that we have time to read all timers at least once in an
interval of time lasting int_ms milliseconds, and likewise for (fin_ms
- int_ms). So don't call it with arguments that are too small. */
mbedtls_timing_delay_context delay;
struct mbedtls_timing_hr_time timer;
unsigned long delta = 0; /* delay started between timer=0 and timer=delta */
unsigned long before = 0, after = 0;
unsigned long iterations = 0;
int status = -2;
int saw_status_1 = 0;
int warn_inconclusive = 0;
assert( int_ms >= 0 );
assert( fin_ms >= 0 );
/* Skip this test if it looks like timers don't work at all, to avoid an
infinite loop below. */
TEST_ASSERT( !timers_are_badly_broken );
/* Start a reference timer. Program a delay, and verify that the status of
the delay is consistent with the time given by the reference timer. */
(void) mbedtls_timing_get_timer( &timer, 1 );
mbedtls_timing_set_delay( &delay, int_ms, fin_ms );
/* Set delta to an upper bound for the interval between the start of timer
and the start of delay. Reading timer after starting delay gives us an
upper bound for the interval, rounded to a 1ms precision. Since this
might have been rounded down, but we need an upper bound, we add 1. */
delta = mbedtls_timing_get_timer( &timer, 0 ) + 1;
status = mbedtls_timing_get_delay( &delay );
if( fin_ms == 0 )
{
/* Cancelled timer. Just check the correct status for this case. */
TEST_ASSERT( status == -1 );
return;
}
/* Initially, none of the delays must be passed yet if they're nonzero.
This could fail for very small values of int_ms and fin_ms, where "very
small" depends how fast and how busy the platform is. */
if( int_ms > 0 )
{
TEST_ASSERT( status == 0 );
}
else
{
TEST_ASSERT( status == 1 );
}
do
{
unsigned long delay_min, delay_max;
int status_min, status_max;
++iterations;
before = mbedtls_timing_get_timer( &timer, 0 );
status = mbedtls_timing_get_delay( &delay );
after = mbedtls_timing_get_timer( &timer, 0 );
/* At a time between before and after, the delay's status was status.
Check that this is consistent given that the delay was started
between times 0 and delta. */
delay_min = ( before > delta ? before - delta : 0 );
status_min = expected_delay_status( int_ms, fin_ms, delay_min );
delay_max = after;
status_max = expected_delay_status( int_ms, fin_ms, delay_max );
TEST_ASSERT( status >= status_min );
TEST_ASSERT( status <= status_max );
if( status == 1 )
saw_status_1 = 1;
}
while ( before <= fin_ms + delta && status != 2 );
/* Since we've waited at least fin_ms, the delay must have fully
expired. */
TEST_ASSERT( status == 2 );
/* If the second delay is more than the first, then there must have been a
point in time when the first delay was passed but not the second delay.
This could fail for very small values of (fin_ms - int_ms), where "very
small" depends how fast and how busy the platform is. In practice, this
is the test that's most likely to fail on a heavily loaded machine. */
if( fin_ms > int_ms )
{
warn_inconclusive = 1;
TEST_ASSERT( saw_status_1 );
}
return;
exit:
/* No cleanup needed, but show some diagnostic iterations, because timing
problems can be hard to reproduce. */
if( !timers_are_badly_broken )
mbedtls_fprintf( stdout, " Finished with delta=%lu before=%lu after=%lu status=%d iterations=%lu\n",
delta, before, after, status, iterations );
if( warn_inconclusive )
mbedtls_fprintf( stdout, " Inconclusive test, try running it on a less heavily loaded machine.\n" );
}
/* END_CASE */
/* BEGIN_CASE */
void timing_hardclock( )
{
/* We make very few guarantees about mbedtls_timing_hardclock: its rate is
platform-dependent, it can wrap around. So there isn't much we can
test. But we do at least test that it doesn't crash, stall or return
completely nonsensical values. */
struct mbedtls_timing_hr_time timer;
unsigned long hardclock0 = -1, hardclock1 = -1, delta1 = -1;
/* Skip this test if it looks like timers don't work at all, to avoid an
infinite loop below. */
TEST_ASSERT( !timers_are_badly_broken );
hardclock0 = mbedtls_timing_hardclock( );
/* Wait 2ms to ensure a nonzero delay. Since the timer interface has 1ms
resolution and unspecified precision, waiting 1ms might be a very small
delay that's rounded up. */
(void) mbedtls_timing_get_timer( &timer, 1 );
while( mbedtls_timing_get_timer( &timer, 0 ) < 2 )
/*busy-wait loop*/;
hardclock1 = mbedtls_timing_hardclock( );
/* Although the hardclock counter can wrap around, the difference
(hardclock1 - hardclock0) is taken modulo the type size, so it is
correct as long as the counter only wrapped around at most once. We
further require the difference to be nonzero (after a wait of more than
1ms, the counter must have changed), and not to be overly large (after
a wait of less than 3ms, plus time lost because other processes were
scheduled on the CPU). If the hardclock counter runs at 4GHz, then
1000000000 (which is 1/4 of the counter wraparound on a 32-bit machine)
allows 250ms. */
delta1 = hardclock1 - hardclock0;
TEST_ASSERT( delta1 > 0 );
TEST_ASSERT( delta1 < 1000000000 );
return;
exit:
/* No cleanup needed, but show some diagnostic iterations, because timing
problems can be hard to reproduce. */
if( !timers_are_badly_broken )
mbedtls_fprintf( stdout, " Finished with hardclock=%lu,%lu\n",
hardclock0, hardclock1 );
} }
/* END_CASE */ /* END_CASE */