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 <piotr.nowicki@arm.com>
This commit is contained in:
Piotr Nowicki 2020-07-31 16:11:06 +02:00
parent 8656fc6525
commit 77b7a7754c
2 changed files with 75 additions and 54 deletions

View file

@ -51,9 +51,20 @@
#include <stddef.h>
#include <string.h>
/* 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)