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)