Merge branch 'development' into iotssl-1619
diff --git a/ChangeLog b/ChangeLog
index cf2c882..75a2867 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14,6 +14,18 @@
Features
* 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
* Extend RSA interface by multiple functions allowing structure-
@@ -73,6 +85,10 @@
* Fix incorrect unit in benchmark output. #850
* Fix crash when calling mbedtls_ssl_cache_free() twice. Found by
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
* Extend cert_write example program by options to set the CRT version
@@ -82,6 +98,7 @@
particular, don't require P,Q if neither CRT nor blinding are
used. Reported and fix proposed independently by satur9nine and sliai
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
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index 1829f72..c8dd0f3 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -36,9 +36,13 @@
#define MBEDTLS_AES_ENCRYPT 1
#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_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) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index ef75839..579402f 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -28,6 +28,10 @@
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
+#if !defined(MBEDTLS_CCM_ALT)
+// Regular implementation
+//
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -125,6 +129,18 @@
const unsigned char *input, unsigned char *output,
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)
/**
* \brief Checkup routine
diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h
index 9a2b96b..4d3f2d2 100644
--- a/include/mbedtls/cmac.h
+++ b/include/mbedtls/cmac.h
@@ -39,6 +39,8 @@
#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */
#endif
+#if !defined(MBEDTLS_CMAC_ALT)
+
/**
* CMAC context structure - Contains internal state information only
*/
@@ -154,6 +156,18 @@
unsigned char output[16] );
#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) )
/**
* \brief Checkup routine
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index d878e0a..5b2c4ad 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -266,8 +266,11 @@
//#define MBEDTLS_ARC4_ALT
//#define MBEDTLS_BLOWFISH_ALT
//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CMAC_ALT
//#define MBEDTLS_DES_ALT
//#define MBEDTLS_RSA_ALT
+//#define MBEDTLS_GCM_ALT
//#define MBEDTLS_XTEA_ALT
//#define MBEDTLS_MD2_ALT
//#define MBEDTLS_MD4_ALT
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index d51bcde..4eb7b78 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -52,7 +52,7 @@
* GCM 2 0x0012-0x0014
* BLOWFISH 2 0x0016-0x0018
* THREADING 3 0x001A-0x001E
- * AES 2 0x0020-0x0022
+ * AES 2 0x0020-0x0022 0x0023-0x0023
* CAMELLIA 2 0x0024-0x0026
* XTEA 1 0x0028-0x0028
* BASE64 2 0x002A-0x002C
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 1b77aae..8f3b565 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -33,6 +33,8 @@
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
+#if !defined(MBEDTLS_GCM_ALT)
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -206,6 +208,18 @@
*/
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
*
@@ -217,4 +231,5 @@
}
#endif
+
#endif /* gcm.h */
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index ae7a713..bfb8579 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -1,7 +1,7 @@
/**
* \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
* SPDX-License-Identifier: Apache-2.0
@@ -65,6 +65,9 @@
* \warning This is only a best effort! Do not rely on this!
* In particular, it is known to be unreliable on virtual
* machines.
+ *
+ * \note This value starts at an unspecified origin and
+ * may wrap around.
*/
unsigned long mbedtls_timing_hardclock( void );
@@ -72,7 +75,18 @@
* \brief Return the elapsed time in milliseconds
*
* \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 );
@@ -80,6 +94,7 @@
* \brief Setup an alarm clock
*
* \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
* context, this means one for the whole process, not one per
@@ -91,11 +106,15 @@
* \brief Set a pair of delays to watch
* (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.
* \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.
* 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 );
@@ -106,7 +125,7 @@
* \param data Pointer to timing data
* 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,
* 1 if only the intermediate delay is passed,
* 2 if the final delay is passed.
diff --git a/library/aes.c b/library/aes.c
index 5860384..dba4a5f 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1235,9 +1235,11 @@
*/
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 buf[64];
+ const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
unsigned char iv[16];
#endif
@@ -1263,45 +1265,52 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-ECB-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( buf, 0, 16 );
- if( v == MBEDTLS_AES_DECRYPT )
+ if( mode == MBEDTLS_AES_DECRYPT )
{
- mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
-
- 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;
- }
+ ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_ecb_dec[u];
}
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 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
+ for( j = 0; j < 10000; j++ )
+ {
+ ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
+ if( ret != 0 )
goto exit;
- }
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1318,55 +1327,64 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-CBC-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( iv , 0, 16 );
memset( prv, 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 );
-
- 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;
- }
+ ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_cbc_dec[u];
}
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];
- mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
-
memcpy( tmp, prv, 16 );
memcpy( prv, buf, 16 );
memcpy( buf, tmp, 16 );
}
- if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
+ ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
+ if( ret != 0 )
goto exit;
- }
+
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1384,45 +1402,52 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
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;
- 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 );
- mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ aes_tests = aes_test_cfb128_pt;
}
else
{
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 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
+ ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
- ret = 1;
- goto exit;
- }
+ if( memcmp( buf, aes_tests, 64 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1440,51 +1465,41 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ mode = i & 1;
if( verbose != 0 )
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( key, aes_test_ctr_key[u], 16 );
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 );
-
- 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;
- }
+ aes_tests = aes_test_ctr_pt[u];
}
else
{
- len = aes_test_ctr_len[u];
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,
- buf, buf );
+ ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
+ stream_block, buf, buf );
+ if( ret != 0 )
+ goto exit;
- if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ if( memcmp( buf, aes_tests, len ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1498,6 +1513,9 @@
ret = 0;
exit:
+ if( ret != 0 && verbose != 0 )
+ mbedtls_printf( "failed\n" );
+
mbedtls_aes_free( &ctx );
return( ret );
diff --git a/library/ccm.c b/library/ccm.c
index 13a8fd1..9101e5f 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -49,6 +49,8 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+#if !defined(MBEDTLS_CCM_ALT)
+
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@@ -348,6 +350,7 @@
return( 0 );
}
+#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
diff --git a/library/cmac.c b/library/cmac.c
index 6df56aa..9dbff90 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -65,6 +65,8 @@
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */
+#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
+
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@@ -164,7 +166,9 @@
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,
const unsigned char *input2,
const size_t block_size )
@@ -468,6 +472,8 @@
}
#endif /* MBEDTLS_AES_C */
+#endif /* !MBEDTLS_CMAC_ALT */
+
#if defined(MBEDTLS_SELF_TEST)
/*
* CMAC test data for SP800-38B
diff --git a/library/error.c b/library/error.c
index 23e4953..151ca4e 100644
--- a/library/error.c
+++ b/library/error.c
@@ -520,6 +520,8 @@
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_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 */
#if defined(MBEDTLS_ASN1_PARSE_C)
diff --git a/library/gcm.c b/library/gcm.c
index fccb092..294a86d 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -46,6 +46,7 @@
#endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#include "mbedtls/aes.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -54,6 +55,8 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+#if !defined(MBEDTLS_GCM_ALT)
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -508,6 +511,8 @@
mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
}
+#endif /* !MBEDTLS_GCM_ALT */
+
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
* AES-GCM test vectors from:
@@ -744,34 +749,48 @@
int i, j, ret;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
- mbedtls_gcm_init( &ctx );
-
for( j = 0; j < 3; j++ )
{
int key_len = 128 + 64 * j;
for( i = 0; i < MAX_TESTS; i++ )
{
+ mbedtls_gcm_init( &ctx );
+
if( verbose != 0 )
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,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- pt[pt_index[i]], buf, 16, tag_buf );
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ pt[pt_index[i]], buf, 16, tag_buf );
+ if( ret != 0 )
+ goto exit;
- if( ret != 0 ||
- memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
+ ret = 1;
+ goto exit;
}
mbedtls_gcm_free( &ctx );
@@ -779,26 +798,31 @@
if( verbose != 0 )
mbedtls_printf( "passed\n" );
+ mbedtls_gcm_init( &ctx );
+
if( verbose != 0 )
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,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- ct[j * 6 + i], buf, 16, tag_buf );
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ ct[j * 6 + i], buf, 16, tag_buf );
- if( ret != 0 ||
- memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
+ ret = 1;
+ goto exit;
}
mbedtls_gcm_free( &ctx );
@@ -806,66 +830,51 @@
if( verbose != 0 )
mbedtls_printf( "passed\n" );
+ mbedtls_gcm_init( &ctx );
+
if( verbose != 0 )
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,
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i] );
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i] );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
buf + 32 );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
}
else
{
ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
}
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
- if( ret != 0 ||
- memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
+ ret = 1;
+ goto exit;
}
mbedtls_gcm_free( &ctx );
@@ -873,80 +882,75 @@
if( verbose != 0 )
mbedtls_printf( "passed\n" );
+ mbedtls_gcm_init( &ctx );
+
if( verbose != 0 )
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,
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
- buf + 32 );
+ buf + 32 );
if( ret != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
}
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( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ goto exit;
}
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
- if( ret != 0 ||
- memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
+ ret = 1;
+ goto exit;
}
mbedtls_gcm_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
-
}
}
if( verbose != 0 )
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 */
diff --git a/library/timing.c b/library/timing.c
index a7c7ff0..6df137d 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -244,21 +244,23 @@
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;
- QueryPerformanceCounter( &offset );
- QueryPerformanceFrequency( &hfreq );
-
- delta = (unsigned long)( ( 1000 *
- ( offset.QuadPart - t->start.QuadPart ) ) /
- hfreq.QuadPart );
-
if( reset )
+ {
QueryPerformanceCounter( &t->start );
-
- return( delta );
+ return( 0 );
+ }
+ 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 */
@@ -285,23 +287,22 @@
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;
- gettimeofday( &offset, NULL );
-
if( reset )
{
- t->start.tv_sec = offset.tv_sec;
- t->start.tv_usec = offset.tv_usec;
+ gettimeofday( &t->start, NULL );
return( 0 );
}
-
- delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
- + ( offset.tv_usec - t->start.tv_usec ) / 1000;
-
- return( delta );
+ else
+ {
+ unsigned long delta;
+ struct timeval now;
+ 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 )
@@ -315,6 +316,12 @@
mbedtls_timing_alarmed = 0;
signal( SIGALRM, sighandler );
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 */
@@ -378,13 +385,21 @@
(void) j;
}
-#define FAIL do \
-{ \
- if( verbose != 0 ) \
- mbedtls_printf( "failed\n" ); \
- \
- return( 1 ); \
-} while( 0 )
+#define FAIL do \
+ { \
+ if( verbose != 0 ) \
+ { \
+ mbedtls_printf( "failed at line %d\n", __LINE__ ); \
+ mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \
+ 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
@@ -394,22 +409,22 @@
*/
int mbedtls_timing_self_test( int verbose )
{
- unsigned long cycles, ratio;
- unsigned long millisecs, secs;
- int hardfail;
+ unsigned long cycles = 0, ratio = 0;
+ unsigned long millisecs = 0, secs = 0;
+ int hardfail = 0;
struct mbedtls_timing_hr_time hires;
- uint32_t a, b;
+ uint32_t a = 0, b = 0;
mbedtls_timing_delay_context ctx;
if( verbose != 0 )
mbedtls_printf( " TIMING tests note: will take some time!\n" );
-
if( verbose != 0 )
mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " );
- for( secs = 1; secs <= 3; secs++ )
{
+ secs = 1;
+
(void) mbedtls_timing_get_timer( &hires, 1 );
mbedtls_set_alarm( (int) secs );
@@ -421,12 +436,7 @@
/* For some reason on Windows it looks like alarm has an extra delay
* (maybe related to creating a new thread). Allow some room here. */
if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- return( 1 );
- }
+ FAIL;
}
if( verbose != 0 )
@@ -435,28 +445,22 @@
if( verbose != 0 )
mbedtls_printf( " TIMING test #2 (set/get_delay ): " );
- for( a = 200; a <= 400; a += 200 )
{
- for( b = 200; b <= 400; b += 200 )
- {
- mbedtls_timing_set_delay( &ctx, a, a + b );
+ a = 800;
+ b = 400;
+ mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */
- busy_msleep( a - a / 8 );
- if( mbedtls_timing_get_delay( &ctx ) != 0 )
- FAIL;
+ busy_msleep( a - a / 4 ); /* T = a - a/4 */
+ if( mbedtls_timing_get_delay( &ctx ) != 0 )
+ FAIL;
- busy_msleep( a / 4 );
- if( mbedtls_timing_get_delay( &ctx ) != 1 )
- FAIL;
+ busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */
+ if( mbedtls_timing_get_delay( &ctx ) != 1 )
+ FAIL;
- busy_msleep( b - a / 8 - b / 8 );
- if( mbedtls_timing_get_delay( &ctx ) != 1 )
- FAIL;
-
- busy_msleep( b / 4 );
- if( mbedtls_timing_get_delay( &ctx ) != 2 )
- FAIL;
- }
+ busy_msleep( b ); /* T = a + b + b/4 */
+ if( mbedtls_timing_get_delay( &ctx ) != 2 )
+ FAIL;
}
mbedtls_timing_set_delay( &ctx, 0, 0 );
@@ -475,7 +479,6 @@
* 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.
*/
- hardfail = 0;
hard_test:
if( hardfail > 1 )
diff --git a/library/version_features.c b/library/version_features.c
index 9bf6c61..cdb4161 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -96,12 +96,21 @@
#if defined(MBEDTLS_CAMELLIA_ALT)
"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)
"MBEDTLS_DES_ALT",
#endif /* MBEDTLS_DES_ALT */
#if defined(MBEDTLS_RSA_ALT)
"MBEDTLS_RSA_ALT",
#endif /* MBEDTLS_RSA_ALT */
+#if defined(MBEDTLS_GCM_ALT)
+ "MBEDTLS_GCM_ALT",
+#endif /* MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_XTEA_ALT)
"MBEDTLS_XTEA_ALT",
#endif /* MBEDTLS_XTEA_ALT */
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 1941ad0..72a3734 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -107,8 +107,8 @@
* self-test. If this fails, we attempt the test anyway, so no error is passed
* back.
*/
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_ENTROPY_C) && \
- defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_ENTROPY_C)
+#if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
static void create_entropy_seed_file( void )
{
int result;
@@ -136,9 +136,137 @@
}
#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 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)
unsigned char buf[1000000];
#endif
@@ -165,16 +293,24 @@
mbedtls_exit( MBEDTLS_EXIT_FAILURE );
}
- if( argc == 2 && ( strcmp( argv[1], "--quiet" ) == 0 ||
- strcmp( argv[1], "-q" ) == 0 ) )
+ for( argp = argv + ( argc >= 1 ? 1 : argc ); *argp != NULL; ++argp )
{
- 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
- {
- v = 1;
+
+ if( v != 0 )
mbedtls_printf( "\n" );
- }
#if defined(MBEDTLS_SELF_TEST)
@@ -182,246 +318,60 @@
mbedtls_memory_buffer_alloc_init( buf, sizeof(buf) );
#endif
-#if defined(MBEDTLS_MD2_C)
- if( mbedtls_md2_self_test( v ) != 0 )
+ if( *argp != NULL && exclude_mode == 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++;
-#endif
-
-#if defined(MBEDTLS_MD4_C)
- if( mbedtls_md4_self_test( v ) != 0 )
+ else
{
- 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
+ (void) exclude_mode;
mbedtls_printf( " MBEDTLS_SELF_TEST not defined.\n" );
#endif
diff --git a/scripts/config.pl b/scripts/config.pl
index 5a06a33..76ca470 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -45,7 +45,7 @@
my $usage = <<EOU;
$0 [-f <file> | --file <file>] [-o | --force]
[set <symbol> <value> | unset <symbol> | get <symbol> |
- full | realfull]
+ full | realfull | baremetal]
Commands
set <symbol> [<value>] - Uncomments or adds a #define for the <symbol> to
@@ -63,6 +63,7 @@
excluding some reserved symbols, until the
'Module configuration options' section
realfull - Uncomments all #define's with no exclusions
+ baremetal - Sets full configuration suitable for baremetal build.
Options
-f | --file <filename> - The file or file path for the configuration file
@@ -91,14 +92,38 @@
MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
MBEDTLS_ZLIB_SUPPORT
MBEDTLS_PKCS11_C
+MBEDTLS_NO_UDBL_DIVISION
_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
my @non_excluded = qw(
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
my $force_option = 0;
@@ -123,7 +148,7 @@
# ...else assume it's a command
$action = $arg;
- if ($action eq "full" || $action eq "realfull") {
+ if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
# No additional parameters
die $usage if @ARGV;
@@ -166,7 +191,12 @@
my @config_lines = <$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") {
$exclude_re = qr/^$/;
$no_exclude_re = qr/./;
@@ -174,6 +204,9 @@
$exclude_re = join '|', @excluded;
$no_exclude_re = join '|', @non_excluded;
}
+if ( $action eq "baremetal" ) {
+ $exclude_baremetal_re = join '|', @excluded_baremetal;
+}
my $config_write = undef;
if ($action ne "get") {
@@ -182,17 +215,19 @@
my $done;
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/) {
$done = 1;
}
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?!!;
}
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!^!//!;
}
} elsif ($action eq "unset") {
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index cfe305f..6ffd386 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -4,20 +4,78 @@
#
# 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
+# -------
#
# To run all tests possible or available on the platform.
#
+# Notes for users
+# ---------------
+#
# Warning: the test is destructive. It includes various build modes and
# configurations, and can and will arbitrarily change the current CMake
-# configuration. After this script has been run, the CMake cache will be lost
-# and CMake will no longer be initialised.
+# configuration. The following files must be committed into git:
+# * 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
-# ASan with gcc and MemSan with clang, or valgrind) are available, as well as
-# cmake and a "good" find.
+# The script assumes the presence of a number of tools:
+# * Basic Unix tools (Windows users note: a Unix-style find must be before
+# 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)
set -eu
@@ -35,7 +93,9 @@
MEMORY=0
FORCE=0
+KEEP_GOING=0
RELEASE=0
+RUN_ARMCC=1
YOTTA=1
# Default commands, can be overriden by the environment
@@ -56,28 +116,38 @@
usage()
{
- printf "Usage: $0\n"
- printf " -h|--help\t\tPrint this help.\n"
- printf " -m|--memory\t\tAdditional optional memory tests.\n"
- 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"
- printf " -r|--release-test\t\tRun this script in release mode. This fixes the seed value to 1.\n"
- printf " --no-yotta\t\tSkip yotta build\n"
- printf " --out-of-source-dir=<path>\t\tDirectory used for CMake out-of-source build tests."
- printf " --openssl=<OpenSSL_path>\t\tPath to OpenSSL executable to use for most tests.\n"
- printf " --openssl-legacy=<OpenSSL_path>\t\tPath to OpenSSL executable to use for legacy tests e.g. SSLv3.\n"
- printf " --gnutls-cli=<GnuTLS_cli_path>\t\tPath to GnuTLS client executable to use for most tests.\n"
- printf " --gnutls-serv=<GnuTLS_serv_path>\t\tPath to GnuTLS server executable to use for most tests.\n"
- printf " --gnutls-legacy-cli=<GnuTLS_cli_path>\t\tPath to GnuTLS client executable to use for legacy tests.\n"
- printf " --gnutls-legacy-serv=<GnuTLS_serv_path>\t\tPath to GnuTLS server executable to use for legacy tests.\n"
- printf " --armc5-bin-dir=<ARMC5_bin_dir_path>\t\tPath to the ARM Compiler 5 bin directory.\n"
- printf " --armc6-bin-dir=<ARMC6_bin_dir_path>\t\tPath to the ARM Compiler 6 bin directory.\n"
+ cat <<EOF
+Usage: $0 [OPTION]...
+ -h|--help Print this help.
+
+General options:
+ -f|--force Force the tests to overwrite any modified files.
+ -k|--keep-going Run all tests and report errors at the end.
+ -m|--memory Additional optional memory tests.
+ --armcc Run ARM Compiler builds (on by default).
+ --no-armcc Skip ARM Compiler builds.
+ --no-yotta Skip yotta module build.
+ --out-of-source-dir=<path> Directory used for CMake out-of-source build tests.
+ -r|--release-test Run this script in release mode. This fixes the seed value to 1.
+ -s|--seed Integer seed value to use for this test run.
+ --yotta Build yotta module (on by default).
+
+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
cleanup()
{
- make clean
+ command make clean
find . -name yotta -prune -o -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} \+
rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
@@ -89,7 +159,21 @@
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()
{
@@ -98,17 +182,20 @@
echo "* $1 "
printf "* "; date
echo "******************************************************************"
+ current_section=$1
}
-armc6_build_test()
-{
- FLAGS="$1"
+if [ $RUN_ARMCC -ne 0 ]; then
+ armc6_build_test()
+ {
+ FLAGS="$1"
- msg "build: ARM Compiler 6 ($FLAGS), make"
- ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \
- WARNING_CFLAGS='-xc -std=c99' make lib
- make clean
-}
+ msg "build: ARM Compiler 6 ($FLAGS), make"
+ ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \
+ WARNING_CFLAGS='-xc -std=c99' make lib
+ make clean
+ }
+fi
err_msg()
{
@@ -127,49 +214,8 @@
while [ $# -gt 0 ]; do
case "$1" in
- --memory|-m*)
- MEMORY=${1#-m}
- ;;
- --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"
+ --armcc)
+ RUN_ARMCC=1
;;
--armc5-bin-dir)
shift
@@ -179,9 +225,67 @@
shift
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
- 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
shift
@@ -195,7 +299,7 @@
cleanup
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'"
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"
@@ -210,7 +314,6 @@
fi
if ! git diff-files --quiet include/mbedtls/config.h; then
- echo $?
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 "script as: $0 --force"
@@ -218,6 +321,71 @@
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
# Fix the seed value to 1 to ensure that the tests are deterministic.
SEED=1
@@ -252,9 +420,17 @@
# Make sure the tools we need are available.
check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \
- "$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \
- "arm-none-eabi-gcc" "$ARMC5_CC" "$ARMC5_AR" "$ARMC6_CC" "$ARMC6_AR" \
- "i686-w64-mingw32-gcc"
+ "$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \
+ "arm-none-eabi-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
@@ -290,12 +466,18 @@
cleanup
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
cleanup
- tests/scripts/yotta-build.sh
+ record_status tests/scripts/yotta-build.sh
fi
msg "build: cmake, gcc, ASan" # ~ 1 min 50s
@@ -307,16 +489,16 @@
make test
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
-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
make
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
cleanup
@@ -329,11 +511,11 @@
make test
msg "build: SSLv3 - compat.sh (ASan build)" # ~ 6 min
-tests/compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2'
-OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3'
+if_build_succeeded tests/compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2'
+if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3'
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
cleanup
@@ -346,7 +528,7 @@
make test
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
cleanup
@@ -354,30 +536,30 @@
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
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
-CFLAGS='-Werror -Wall -Wextra' make test
+make CFLAGS='-Werror -Wall -Wextra' test
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
-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
cleanup
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
cleanup
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
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.
# This should catch missing mbedtls_printf definitions, and by disabling file
@@ -399,8 +581,8 @@
scripts/config.pl unset MBEDTLS_FS_IO
# 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
-CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' make lib programs
-CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' make test
+make CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
+make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' test
# catch compile bugs in _uninit functions
msg "build: full config with NO_STD_FUNCTION, make, gcc" # ~ 30s
@@ -409,21 +591,21 @@
scripts/config.pl full
scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
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
cleanup
cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full
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
cleanup
cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full
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,
# as that requires a POSIX platform (which isn't the same as C99).
@@ -433,7 +615,7 @@
scripts/config.pl full
scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc.
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
cleanup
@@ -443,7 +625,7 @@
make
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)"
cleanup
@@ -461,42 +643,42 @@
make test
if uname -a | grep -F Linux >/dev/null; then
-msg "build/test: make shared" # ~ 40s
-cleanup
-make SHARED=1 all check
+ msg "build/test: make shared" # ~ 40s
+ cleanup
+ make SHARED=1 all check
fi
if uname -a | grep -F x86_64 >/dev/null; then
-msg "build: i386, make, gcc" # ~ 30s
-cleanup
-CC=gcc CFLAGS='-Werror -Wall -Wextra -m32' make
+ msg "build: i386, make, gcc" # ~ 30s
+ cleanup
+ make CC=gcc CFLAGS='-Werror -Wall -Wextra -m32'
-msg "build: gcc, force 32-bit compilation"
-cleanup
-cp "$CONFIG_H" "$CONFIG_BAK"
-scripts/config.pl unset MBEDTLS_HAVE_ASM
-scripts/config.pl unset MBEDTLS_AESNI_C
-scripts/config.pl unset MBEDTLS_PADLOCK_C
-CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32' make
+ msg "build: gcc, force 32-bit compilation"
+ cleanup
+ cp "$CONFIG_H" "$CONFIG_BAK"
+ scripts/config.pl unset MBEDTLS_HAVE_ASM
+ scripts/config.pl unset MBEDTLS_AESNI_C
+ scripts/config.pl unset MBEDTLS_PADLOCK_C
+ make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32'
-msg "build: gcc, force 64-bit compilation"
-cleanup
-cp "$CONFIG_H" "$CONFIG_BAK"
-scripts/config.pl unset MBEDTLS_HAVE_ASM
-scripts/config.pl unset MBEDTLS_AESNI_C
-scripts/config.pl unset MBEDTLS_PADLOCK_C
-CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' make
+ msg "build: gcc, force 64-bit compilation"
+ cleanup
+ cp "$CONFIG_H" "$CONFIG_BAK"
+ scripts/config.pl unset MBEDTLS_HAVE_ASM
+ scripts/config.pl unset MBEDTLS_AESNI_C
+ scripts/config.pl unset MBEDTLS_PADLOCK_C
+ make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
-msg "test: gcc, force 64-bit compilation"
-make test
+ msg "test: gcc, force 64-bit compilation"
+ make test
-msg "build: gcc, force 64-bit compilation"
-cleanup
-cp "$CONFIG_H" "$CONFIG_BAK"
-scripts/config.pl unset MBEDTLS_HAVE_ASM
-scripts/config.pl unset MBEDTLS_AESNI_C
-scripts/config.pl unset MBEDTLS_PADLOCK_C
-CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' make
+ msg "build: gcc, force 64-bit compilation"
+ cleanup
+ cp "$CONFIG_H" "$CONFIG_BAK"
+ scripts/config.pl unset MBEDTLS_HAVE_ASM
+ scripts/config.pl unset MBEDTLS_AESNI_C
+ scripts/config.pl unset MBEDTLS_PADLOCK_C
+ make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
fi # x86_64
msg "build: arm-none-eabi-gcc, make" # ~ 10s
@@ -514,7 +696,7 @@
scripts/config.pl unset MBEDTLS_THREADING_C
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
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
cleanup
@@ -532,7 +714,7 @@
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
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"
! grep __aeabi_uldiv library/*.o
@@ -556,32 +738,34 @@
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
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
-make clean
+if [ $RUN_ARMCC -ne 0 ]; then
+ make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
+ make clean
-# ARM Compiler 6 - Target ARMv7-A
-armc6_build_test "--target=arm-arm-none-eabi -march=armv7-a"
+ # ARM Compiler 6 - Target ARMv7-A
+ armc6_build_test "--target=arm-arm-none-eabi -march=armv7-a"
-# ARM Compiler 6 - Target ARMv7-M
-armc6_build_test "--target=arm-arm-none-eabi -march=armv7-m"
+ # ARM Compiler 6 - Target ARMv7-M
+ armc6_build_test "--target=arm-arm-none-eabi -march=armv7-m"
-# ARM Compiler 6 - Target ARMv8-A - AArch32
-armc6_build_test "--target=arm-arm-none-eabi -march=armv8.2-a"
+ # ARM Compiler 6 - Target ARMv8-A - AArch32
+ armc6_build_test "--target=arm-arm-none-eabi -march=armv8.2-a"
-# ARM Compiler 6 - Target ARMv8-M
-armc6_build_test "--target=arm-arm-none-eabi -march=armv8-m.main"
+ # ARM Compiler 6 - Target ARMv8-M
+ armc6_build_test "--target=arm-arm-none-eabi -march=armv8-m.main"
-# ARM Compiler 6 - Target ARMv8-A - AArch64
-armc6_build_test "--target=aarch64-arm-none-eabi -march=armv8.2-a"
+ # ARM Compiler 6 - Target ARMv8-A - AArch64
+ armc6_build_test "--target=aarch64-arm-none-eabi -march=armv8.2-a"
+fi
msg "build: allow SHA1 in certificates by default"
cleanup
cp "$CONFIG_H" "$CONFIG_BAK"
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"
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"
cleanup
@@ -594,63 +778,63 @@
msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s
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
-CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 make tests
-WINDOWS_BUILD=1 make clean
+make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 tests
+make WINDOWS_BUILD=1 clean
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
-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
-WINDOWS_BUILD=1 make clean
+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
+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
+make WINDOWS_BUILD=1 clean
# MemSan currently only available on Linux 64 bits
if uname -a | grep 'Linux.*x86_64' >/dev/null; then
-msg "build: MSan (clang)" # ~ 1 min 20s
-cleanup
-cp "$CONFIG_H" "$CONFIG_BAK"
-scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm
-CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
-make
+ msg "build: MSan (clang)" # ~ 1 min 20s
+ cleanup
+ cp "$CONFIG_H" "$CONFIG_BAK"
+ scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm
+ CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
+ make
-msg "test: main suites (MSan)" # ~ 10s
-make test
+ msg "test: main suites (MSan)" # ~ 10s
+ make test
-msg "test: ssl-opt.sh (MSan)" # ~ 1 min
-tests/ssl-opt.sh
+ msg "test: ssl-opt.sh (MSan)" # ~ 1 min
+ if_build_succeeded tests/ssl-opt.sh
-# Optional part(s)
+ # Optional part(s)
-if [ "$MEMORY" -gt 0 ]; then
- msg "test: compat.sh (MSan)" # ~ 6 min 20s
- tests/compat.sh
-fi
+ if [ "$MEMORY" -gt 0 ]; then
+ msg "test: compat.sh (MSan)" # ~ 6 min 20s
+ if_build_succeeded tests/compat.sh
+ fi
else # no MemSan
-msg "build: Release (clang)"
-cleanup
-CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
-make
+ msg "build: Release (clang)"
+ cleanup
+ CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
+ make
-msg "test: main suites valgrind (Release)"
-make memcheck
+ msg "test: main suites valgrind (Release)"
+ make memcheck
-# Optional part(s)
-# Currently broken, programs don't seem to receive signals
-# under valgrind on OS X
+ # Optional part(s)
+ # Currently broken, programs don't seem to receive signals
+ # under valgrind on OS X
-if [ "$MEMORY" -gt 0 ]; then
- msg "test: ssl-opt.sh --memcheck (Release)"
- tests/ssl-opt.sh --memcheck
-fi
+ if [ "$MEMORY" -gt 0 ]; then
+ msg "test: ssl-opt.sh --memcheck (Release)"
+ if_build_succeeded tests/ssl-opt.sh --memcheck
+ fi
-if [ "$MEMORY" -gt 1 ]; then
- msg "test: compat.sh --memcheck (Release)"
- tests/compat.sh --memcheck
-fi
+ if [ "$MEMORY" -gt 1 ]; then
+ msg "test: compat.sh --memcheck (Release)"
+ if_build_succeeded tests/compat.sh --memcheck
+ fi
fi # MemSan
@@ -667,5 +851,13 @@
cd "$MBEDTLS_ROOT_DIR"
rm -rf "$OUT_OF_SOURCE_DIR"
+
+
+################################################################
+#### Termination
+################################################################
+
msg "Done, cleaning up"
cleanup
+
+final_report
diff --git a/tests/suites/test_suite_timing.data b/tests/suites/test_suite_timing.data
index 3ba79a4..4dddcf7 100644
--- a/tests/suites/test_suite_timing.data
+++ b/tests/suites/test_suite_timing.data
@@ -1,2 +1,41 @@
-Timing selftest
-timing_selftest:
+Timing: basic timer operation
+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:
diff --git a/tests/suites/test_suite_timing.function b/tests/suites/test_suite_timing.function
index 5882f85..1610155 100644
--- a/tests/suites/test_suite_timing.function
+++ b/tests/suites/test_suite_timing.function
@@ -1,5 +1,51 @@
/* 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"
+
+/* 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 */
/* BEGIN_DEPENDENCIES
@@ -7,9 +53,351 @@
* END_DEPENDENCIES
*/
-/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
-void timing_selftest()
+/* BEGIN_CASE */
+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 */