/ src / crypto / crypto_true_random.cpp
crypto_true_random.cpp
 1  #include "crypto_true_random.h"
 2  
 3  #include "app_error.h"
 4  #include "nrf_assert.h"
 5  #include "nrf_crypto_rng.h"
 6  
 7  #include "crypto_shared.h"
 8  
 9  #include "crypto_log_module.ii"
10  
11  #ifndef __BYTE_ORDER__
12  #error __BYTE_ORDER must be defined to __ORDER_LITTLE_ENDIAN__ or __ORDER_BIG_ENDIAN__
13  #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
14  #define IS_LITTLE_ENDIAN
15  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
16  #define IS_BIG_ENDIAN
17  #endif // __BYTE_ORDER
18  
19  namespace crypto
20  {
21  	void TrueRandom::Bytes(uint8_t* output, size_t size)
22  	{
23  		ret_code_t ret = nrf_crypto_rng_vector_generate(output, size);
24  		CryptoErrorCheck(ret);
25  	}
26  
27  	uint32_t TrueRandom::Range(uint32_t min, uint32_t max)
28  	{
29  		static_assert(sizeof(uint32_t) == 4);
30  		uint32_t result = 0;
31  
32  		// nrf_crypto_rng_vector_generate_in_range expects min/max to be big endian
33  #if defined(IS_LITTLE_ENDIAN)
34  		min = __builtin_bswap32(min);
35  		max = __builtin_bswap32(max);
36  #endif //IS_LITTLE_ENDIAN
37  
38  		ret_code_t ret = nrf_crypto_rng_vector_generate_in_range((uint8_t*)&result, (const uint8_t*)&min, (const uint8_t*)&max, sizeof(uint32_t));
39  
40  #if defined(IS_LITTLE_ENDIAN)
41  		min = __builtin_bswap32(min);
42  		max = __builtin_bswap32(max);
43  		result = __builtin_bswap32(result);
44  #endif //IS_LITTLE_ENDIAN
45  
46  		ASSERT(result >= min && result <= max);
47  
48  		CryptoErrorCheck(ret);
49  
50  		return result;
51  	}
52  
53  	float TrueRandom::Range(float min, float max)
54  	{
55  		// we will generate 32 bits of randomness
56  		// via the uint32 Range(), to use
57  		// as our scale for our float.
58  		uint32_t randomUint = Range(0, UINT32_MAX);
59  
60  		// get the magnitude of our random value, as floating point math please.
61  		float magnitude = ((float)randomUint / UINT32_MAX);
62  
63  		// short circuit for 0-1!
64  		if (min == 0.0f && max == 1.0f)
65  		{
66  			return magnitude;
67  		}
68  
69  		// scale our resultant random by our range min/max
70  		// (just a normal lerp with our new magnitude!)
71  		return ((1.0f - magnitude) * min) + (max * magnitude);
72  	}
73  
74  	float TrueRandom::Value()
75  	{
76  		return Range(0.0f, 1.0f);
77  	}
78  } // namespace crypto
79  
80  extern "C" uint32_t crypto_true_random_range(uint32_t min, uint32_t max)
81  {
82  	return crypto::TrueRandom::Range(min, max);
83  }