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 }