From fb30b178aff914ff260015f43030e284abb5daf8 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 19 Apr 2017 11:00:45 -0700 Subject: [PATCH] Implement true random number generator on posix platform. (#1614) --- examples/platforms/posix/random.c | 62 ++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/examples/platforms/posix/random.c b/examples/platforms/posix/random.c index 970d2f022..26ddc0d92 100644 --- a/examples/platforms/posix/random.c +++ b/examples/platforms/posix/random.c @@ -30,10 +30,11 @@ * @file * This file implements a pseudo-random number generator. * - * @warning - * This implementation is not a true random number generator and does @em satisfy the Thread requirements. */ +#include +#include + #include "platform-posix.h" #include "openthread/types.h" @@ -41,12 +42,24 @@ #include -static uint32_t s_state = 1; +static uint32_t sState = 1; void platformRandomInit(void) { +#if __SANITIZE_ADDRESS__ == 0 + + ThreadError error; + uint16_t length; + + error = otPlatRandomSecureGet(sizeof(sState), (uint8_t *)&sState, &length); + assert(error == kThreadError_None); + +#else // __SANITIZE_ADDRESS__ + // Multiplying NODE_ID assures that no two nodes gets the same seed within an hour. - s_state = (uint32_t)time(NULL) + (3600 * NODE_ID); + sState = (uint32_t)time(NULL) + (3600 * NODE_ID); + +#endif // __SANITIZE_ADDRESS__ } uint32_t otPlatRandomGet(void) @@ -54,7 +67,7 @@ uint32_t otPlatRandomGet(void) uint32_t mlcg, p, q; uint64_t tmpstate; - tmpstate = (uint64_t)33614 * (uint64_t)s_state; + tmpstate = (uint64_t)33614 * (uint64_t)sState; q = tmpstate & 0xffffffff; q = q >> 1; p = tmpstate >> 32; @@ -66,7 +79,7 @@ uint32_t otPlatRandomGet(void) mlcg++; } - s_state = mlcg; + sState = mlcg; return mlcg; } @@ -75,6 +88,40 @@ ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint1 { ThreadError error = kThreadError_None; +#if __SANITIZE_ADDRESS__ == 0 + + FILE *file = NULL; + size_t readLength; + + *aOutputLength = 0; + + otEXPECT_ACTION(aOutput && aOutputLength, error = kThreadError_InvalidArgs); + + file = fopen("/dev/urandom", "rb"); + otEXPECT_ACTION(file != NULL, error = kThreadError_Failed); + + readLength = fread(aOutput, 1, aInputLength, file); + otEXPECT_ACTION(readLength == aInputLength, error = kThreadError_Failed); + + *aOutputLength = aInputLength; + +exit: + + if (file != NULL) + { + fclose(file); + } + +#else // __SANITIZE_ADDRESS__ + + /* + * THE IMPLEMENTATION BELOW IS NOT COMPLIANT WITH THE THREAD SPECIFICATION. + * + * Address Sanitizer triggers test failures when reading random + * values from /dev/urandom. The pseudo-random number generator + * implementation below is only used to enable continuous + * integration checks with Address Sanitizer enabled. + */ otEXPECT_ACTION(aOutput && aOutputLength, error = kThreadError_InvalidArgs); for (uint16_t length = 0; length < aInputLength; length++) @@ -85,5 +132,8 @@ ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint1 *aOutputLength = aInputLength; exit: + +#endif // __SANITIZE_ADDRESS__ + return error; }