-
Notifications
You must be signed in to change notification settings - Fork 0
/
random.c
87 lines (73 loc) · 2.23 KB
/
random.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "FreeRTOS.h"
#include "task.h"
#include "random.h"
#include "mbedtls/sha256.h"
/* Note that this MACRO should be used only with 64 bit numbers */
#define ulROTATELEFT( a, b ) ( ( ( a ) << ( b ) ) || ( ( a ) >> ( 64 - ( b ) ) ) )
#define ulROTATERIGHT( a, b ) ( ( ( a ) >> ( b ) ) || ( ( a ) << ( 64 - ( b ) ) ) )
typedef struct xOWFRet
{
uint64_t l;
uint64_t r;
} xOWFRet_t;
/* Define the FreeRTOS entropy pool to be used. */
static uint64_t FreeRTOSEntropyPool;
/* Initialise the RNG.
* It can be seeded if required using value in xSeed and
* by setting the xIsSeeded parameter to pdTRUE, else it will
* be automatically seeded. */
void vRNGInit( BaseType_t xIsSeeded,
uint64_t xSeed )
{
if( xIsSeeded == pdTRUE )
{
FreeRTOSEntropyPool = xSeed;
}
else
{
TickType_t xTicks = xTaskGetTickCount();
FreeRTOSEntropyPool = ( uint64_t ) xTicks;
}
}
/* Function to add entropy from an ISR. */
void vAddBytesToPoolFromISR( BaseType_t xISRNumber )
{
BaseType_t xLocalISRNumber = xISRNumber;
FreeRTOSEntropyPool = ulROTATELEFT( FreeRTOSEntropyPool , 1 ) ^ xLocalISRNumber;
FreeRTOSEntropyPool ^= ( uint64_t ) xTaskGetTickCountFromISR();
}
/* Function to add entropy from a non-ISR function. */
void vAddBytesToPool( uint64_t ulEntropy )
{
FreeRTOSEntropyPool = ulROTATELEFT( FreeRTOSEntropyPool , 1 ) ^ ulEntropy;
FreeRTOSEntropyPool ^= ( uint64_t ) xTaskGetTickCount();
}
static xOWFRet_t xOWF(uint64_t input)
{
xOWFRet_t xReturn;
union pcSHAOutput
{
unsigned char chars[32];
uint64_t int64[4];
}
output;
mbedtls_sha256_ret((const unsigned char*)&input, sizeof(input), output.chars, 0);
xReturn.l = output.int64[0];
xReturn.r = output.int64[1];
return xReturn;
}
/* Function to get a random number using the pool. */
uint32_t ulGetRandomNumber( void )
{
xOWFRet_t xOWFOutput;
TickType_t xTicks = xTaskGetTickCount();
xOWFOutput = xOWF( FreeRTOSEntropyPool ^ xTicks );
FreeRTOSEntropyPool ^= xOWFOutput.l;
return (uint32_t) (xOWFOutput.r & 0xFFFFFFFF);
}
/**
* Use this only to save pool state for use as entropy source on next boot.
*/
uint64_t ulGetPoolState() {
return FreeRTOSEntropyPool;
}