From 8656fc65251e720874605304d56ded0a540184c5 Mon Sep 17 00:00:00 2001 From: Piotr Nowicki Date: Tue, 23 Jun 2020 12:30:40 +0200 Subject: [PATCH 1/4] Change the value type in the mbedtls_platform_random_in_range() Signed-off-by: Piotr Nowicki --- include/mbedtls/platform_util.h | 2 +- library/platform_util.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h index 81d0f0f07..a5b95ae7b 100644 --- a/include/mbedtls/platform_util.h +++ b/include/mbedtls/platform_util.h @@ -264,7 +264,7 @@ uint32_t mbedtls_platform_random_uint32( void ); * * \return The generated random number. */ -uint32_t mbedtls_platform_random_in_range( size_t num ); +uint32_t mbedtls_platform_random_in_range( uint32_t num ); /** * \brief Random delay function. diff --git a/library/platform_util.c b/library/platform_util.c index 24c7b4109..bd8585d56 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -96,7 +96,7 @@ void mbedtls_platform_zeroize( void *buf, size_t len ) void *mbedtls_platform_memset( void *ptr, int value, size_t num ) { /* Randomize start offset. */ - size_t start_offset = (size_t) mbedtls_platform_random_in_range( num ); + size_t start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); /* Randomize data */ uint32_t data = mbedtls_platform_random_in_range( 256 ); @@ -113,7 +113,7 @@ void *mbedtls_platform_memset( void *ptr, int value, size_t num ) void *mbedtls_platform_memcpy( void *dst, const void *src, size_t num ) { /* Randomize start offset. */ - size_t start_offset = (size_t) mbedtls_platform_random_in_range( num ); + size_t start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); /* Randomize initial data to prevent leakage while copying */ uint32_t data = mbedtls_platform_random_in_range( 256 ); @@ -152,7 +152,7 @@ int mbedtls_platform_memequal( const void *buf1, const void *buf2, size_t num ) /* Start from a random location and check the correct number of iterations */ size_t i, flow_counter = 0; - size_t start_offset = (size_t) mbedtls_platform_random_in_range( num ); + size_t start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); for( i = start_offset; i < num; i++ ) { @@ -186,7 +186,7 @@ uint32_t mbedtls_platform_random_uint32( ) #endif } -uint32_t mbedtls_platform_random_in_range( size_t num ) +uint32_t mbedtls_platform_random_in_range( uint32_t num ) { #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) (void) num; @@ -216,7 +216,7 @@ void mbedtls_platform_random_delay( void ) #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) return; #else - size_t rn_1, rn_2, rn_3; + uint32_t rn_1, rn_2, rn_3; volatile size_t i = 0; uint8_t shift; @@ -232,9 +232,9 @@ void mbedtls_platform_random_delay( void ) * of its behaviour */ shift = rn_2 & 0x07; if ( i % 2 ) - rn_2 = (uint32_t)( rn_2 >> shift | rn_2 << ( 32 - shift ) ); + rn_2 = ( rn_2 >> shift ) | ( rn_2 << ( 32 - shift ) ); else - rn_3 = (uint32_t)( rn_3 << shift | rn_3 >> ( 32 - shift ) ); + rn_3 = ( rn_3 << shift ) | ( rn_3 >> ( 32 - shift ) ); rn_2 ^= rn_3; } while( i < rn_1 || rn_2 == 0 || rn_3 == 0 ); From 77b7a7754c09a5f2cc48007fefa12cf7adbc2d05 Mon Sep 17 00:00:00 2001 From: Piotr Nowicki Date: Fri, 31 Jul 2020 16:11:06 +0200 Subject: [PATCH 2/4] Expanded the random number generator in the `platform_util.c` file The earlier implementation had two problems: the random generator always returned 0 if the MBEDTLS_ENTROPY_HARDWARE_ALT flag was not defined and there was no protection needed if the HW RNG was malfunctioning. Both these problems have been solved in this commit by adding the linear congruential generator algorithm. Signed-off-by: Piotr Nowicki --- include/mbedtls/platform_util.h | 35 ++++-------- library/platform_util.c | 94 +++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 54 deletions(-) diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h index a5b95ae7b..6f0920963 100644 --- a/include/mbedtls/platform_util.h +++ b/include/mbedtls/platform_util.h @@ -167,11 +167,10 @@ void mbedtls_platform_zeroize( void *buf, size_t len ); /** * \brief Secure memset * - * This is a constant-time version of memset(). If - * MBEDTLS_ENTROPY_HARDWARE_ALT is defined, the buffer is - * initialised with random data and the order is also - * randomised using the hardware RNG in order to further harden - * against side-channel attacks. + * This is a constant-time version of memset(). The buffer is + * initialised with random data and the order is also randomised + * using the RNG in order to further harden against side-channel + * attacks. * * \param ptr Buffer to be set. * \param value Value to be used when setting the buffer. @@ -184,11 +183,10 @@ void *mbedtls_platform_memset( void *ptr, int value, size_t num ); /** * \brief Secure memcpy * - * This is a constant-time version of memcpy(). If - * MBEDTLS_ENTROPY_HARDWARE_ALT is defined, the buffer is - * initialised with random data and the order is also - * randomised using the hardware RNG in order to further harden - * against side-channel attacks. + * This is a constant-time version of memcpy(). The buffer is + * initialised with random data and the order is also randomised + * using the RNG in order to further harden against side-channel + * attacks. * * \param dst Destination buffer where the data is being copied to. * \param src Source buffer where the data is being copied from. @@ -218,9 +216,8 @@ int mbedtls_platform_memmove( void *dst, const void *src, size_t num ); * \brief Secure check if the buffers have the same data. * * This is a constant-time version of memcmp(), but without checking - * if the bytes are greater or lower. If MBEDTLS_ENTROPY_HARDWARE_ALT - * is defined, the order is also randomised using the hardware RNG in - * order to further harden against side-channel attacks. + * if the bytes are greater or lower. The order is also randomised + * using the RNG in order to further harden against side-channel attacks. * * \param buf1 First buffer to compare. * \param buf2 Second buffer to compare against. @@ -234,11 +231,6 @@ int mbedtls_platform_memequal( const void *buf1, const void *buf2, size_t num ); /** * \brief RNG-function for getting a random 32-bit integer. * - * - * \note Currently the function is dependent of hardware providing an - * rng with MBEDTLS_ENTROPY_HARDWARE_ALT. By default, 0 is - * returned. - * * \return The generated random number. */ uint32_t mbedtls_platform_random_uint32( void ); @@ -253,10 +245,6 @@ uint32_t mbedtls_platform_random_uint32( void ); * cryptographically secure RNG, but provide an RNG for utility * functions. * - * \note Currently the function is dependent of hardware providing an - * rng with MBEDTLS_ENTROPY_HARDWARE_ALT. By default, 0 is - * returned. - * * \note If the given range is [0, 0), 0 is returned. * * \param num Max-value for the generated random number, exclusive. @@ -274,9 +262,6 @@ uint32_t mbedtls_platform_random_in_range( uint32_t num ); * * Duration of the delay is random as number of variable increments * is randomized. - * - * \note Currently the function is dependent of hardware providing an - * rng with MBEDTLS_ENTROPY_HARDWARE_ALT. */ void mbedtls_platform_random_delay( void ); diff --git a/library/platform_util.c b/library/platform_util.c index bd8585d56..641172ad9 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -51,9 +51,20 @@ #include #include -/* Max number of loops for mbedtls_platform_random_delay */ +/* Max number of loops for mbedtls_platform_random_delay. */ #define MAX_RAND_DELAY 100 +/* Parameters for the linear congruential generator used as a non-cryptographic + * random number generator. The same parameters are used by e.g. ANSI C. */ +#define RAND_MULTIPLIER 1103515245 +#define RAND_INCREMENT 12345 +#define RAND_MODULUS 0x80000000 + +/* The number of iterations after which the seed of the non-cryptographic + * random number generator will be changed. This is used only if the + * MBEDTLS_ENTROPY_HARDWARE_ALT option is enabled. */ +#define RAND_SEED_LIFE 10000 + #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) /* * This implementation should never be optimized out by the compiler @@ -172,50 +183,78 @@ int mbedtls_platform_memequal( const void *buf1, const void *buf2, size_t num ) return( (int) diff | (int) ( flow_counter ^ num ) ); } -uint32_t mbedtls_platform_random_uint32( ) +/* This function implements a non-cryptographic random number generator based + * on the linear congruential generator algorithm. Additionally, if the + * MBEDTLS_ENTROPY_HARDWARE_ALT flag is defined, the seed is set at the first + * call of this function with using a hardware random number generator and + * changed every RAND_SEED_LIFE number of iterations. + * + * The value of the returned number is in the range [0; 0xffff]. + * + * Note: The range of values with a 16-bit precision is related to the modulo + * parameter of the generator and the fact that the function does not return the + * full value of the internal state of the generator. + */ +static uint32_t mbedtls_platform_random_uint16( void ) { -#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - return 0; -#else - uint32_t result = 0; - size_t olen = 0; + /* Set random_state - the first random value should not be zero. */ + static uint32_t random_state = RAND_INCREMENT; - mbedtls_hardware_poll( NULL, (unsigned char *) &result, sizeof( result ), - &olen ); - return( result ); -#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + + static uint32_t random_seed_life = 0; + + if( 0 < random_seed_life ) + { + --random_seed_life; + } + else + { + size_t olen = 0; + uint32_t hw_random; + mbedtls_hardware_poll( NULL, + (unsigned char *) &hw_random, sizeof( hw_random ), + &olen ); + if( olen == sizeof( hw_random ) ) + { + random_state ^= hw_random; + random_seed_life = RAND_SEED_LIFE; + } + } + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + + random_state = ( ( random_state * RAND_MULTIPLIER ) + RAND_INCREMENT ) % RAND_MODULUS; + + /* Do not return the entire random_state to hide generator predictability for + * the next iteration */ + return( ( random_state >> 15 ) & 0xffff ); +} + +uint32_t mbedtls_platform_random_uint32( void ) +{ + return( ( mbedtls_platform_random_uint16() << 16 ) | + mbedtls_platform_random_uint16() ); } uint32_t mbedtls_platform_random_in_range( uint32_t num ) { -#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - (void) num; - return 0; -#else - uint32_t result = 0; - size_t olen = 0; + uint32_t result; - mbedtls_hardware_poll( NULL, (unsigned char *) &result, sizeof( result ), - &olen ); - - if( num == 0 ) + if( num <= 1 ) { result = 0; } else { - result %= num; + result = mbedtls_platform_random_uint32() % num; } return( result ); -#endif } void mbedtls_platform_random_delay( void ) { -#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - return; -#else uint32_t rn_1, rn_2, rn_3; volatile size_t i = 0; uint8_t shift; @@ -237,9 +276,6 @@ void mbedtls_platform_random_delay( void ) rn_3 = ( rn_3 << shift ) | ( rn_3 >> ( 32 - shift ) ); rn_2 ^= rn_3; } while( i < rn_1 || rn_2 == 0 || rn_3 == 0 ); - - return; -#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ } #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) From 057daa3b284d9be70484d8689b2f4896cf450c52 Mon Sep 17 00:00:00 2001 From: Piotr Nowicki Date: Mon, 3 Aug 2020 13:08:33 +0200 Subject: [PATCH 3/4] Random delay can be disabled in configuration Use random delay depending on whether MBEDTLS_FI_COUNTERMEASURES is defined Signed-off-by: Piotr Nowicki --- include/mbedtls/platform_util.h | 4 ++++ library/platform_util.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h index 6f0920963..8d00eba9f 100644 --- a/include/mbedtls/platform_util.h +++ b/include/mbedtls/platform_util.h @@ -262,6 +262,10 @@ uint32_t mbedtls_platform_random_in_range( uint32_t num ); * * Duration of the delay is random as number of variable increments * is randomized. + * + * \note This function works only if the MBEDTLS_FI_COUNTERMEASURES flag + * is defined in the configuration. Otherwise, the function does + * nothing. */ void mbedtls_platform_random_delay( void ); diff --git a/library/platform_util.c b/library/platform_util.c index 641172ad9..3fa943738 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -255,6 +255,7 @@ uint32_t mbedtls_platform_random_in_range( uint32_t num ) void mbedtls_platform_random_delay( void ) { +#if defined(MBEDTLS_FI_COUNTERMEASURES) uint32_t rn_1, rn_2, rn_3; volatile size_t i = 0; uint8_t shift; @@ -276,6 +277,9 @@ void mbedtls_platform_random_delay( void ) rn_3 = ( rn_3 << shift ) | ( rn_3 >> ( 32 - shift ) ); rn_2 ^= rn_3; } while( i < rn_1 || rn_2 == 0 || rn_3 == 0 ); + +#endif /* MBEDTLS_FI_COUNTERMEASURES */ + return; } #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) From 26c33692b0acae11ab260277713d5fabf950e658 Mon Sep 17 00:00:00 2001 From: Piotr Nowicki Date: Tue, 11 Aug 2020 13:58:47 +0200 Subject: [PATCH 4/4] Fix CI failure. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For ASanDbg tests of the earlier implementation of the mbedtls_platform_random_in_range(), there was no case where ‘shift’ value was zero. Such a case generated a bit shift of 32, which is treated as an error by ASanDbg. Increasing the ‘shift’ value by one ensures that it will always be non-zero. Signed-off-by: Piotr Nowicki --- library/platform_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/platform_util.c b/library/platform_util.c index 3fa943738..5e938f9c9 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -269,8 +269,8 @@ void mbedtls_platform_random_delay( void ) i++; /* Dummy calculations to increase the time between iterations and * make side channel attack more difficult by reducing predictability - * of its behaviour */ - shift = rn_2 & 0x07; + * of its behaviour. */ + shift = ( rn_2 & 0x07 ) + 1; if ( i % 2 ) rn_2 = ( rn_2 >> shift ) | ( rn_2 << ( 32 - shift ) ); else