diff options
author | Jack Lloyd <[email protected]> | 2019-08-27 09:38:59 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2019-08-27 09:42:34 -0400 |
commit | a9c3413bcd155a6a70a8b8c64a073f5db19cd86c (patch) | |
tree | d811fc2cedd003e1a3d69a5854d9d439d40ab8ba /src/lib/entropy | |
parent | 308bdc190f4e6a3606f801390d191988a0438557 (diff) |
Use inline asm to avoid GCC bug. Handle RNG failure
Diffstat (limited to 'src/lib/entropy')
-rw-r--r-- | src/lib/entropy/p9_darn/info.txt | 8 | ||||
-rw-r--r-- | src/lib/entropy/p9_darn/p9_darn.cpp | 47 |
2 files changed, 42 insertions, 13 deletions
diff --git a/src/lib/entropy/p9_darn/info.txt b/src/lib/entropy/p9_darn/info.txt index 30f76603b..47d99aa3d 100644 --- a/src/lib/entropy/p9_darn/info.txt +++ b/src/lib/entropy/p9_darn/info.txt @@ -6,14 +6,6 @@ ENTROPY_SRC_DARN -> 20180610 p9_darn.h </header:internal> -<cc> -gcc:7.0 -</cc> - -<isa> -power9 -</isa> - <arch> ppc64 </arch> diff --git a/src/lib/entropy/p9_darn/p9_darn.cpp b/src/lib/entropy/p9_darn/p9_darn.cpp index aa88b8301..8731b94e1 100644 --- a/src/lib/entropy/p9_darn/p9_darn.cpp +++ b/src/lib/entropy/p9_darn/p9_darn.cpp @@ -9,19 +9,56 @@ namespace Botan { +namespace { + +bool read_darn(secure_vector<uint64_t>& seed) + { + const size_t DARN_RETRIES = 512; + + for(size_t i = 0; i != DARN_RETRIES; ++i) + { + uint64_t r = 0; + + // DARN 0: 32-bit conditioned, 1: 64-bit condition, 2: 64-bit raw (ala RDSEED) + asm volatile("darn %0, 2" : "=r" (r)); + + // DARN indicates error by 0xFF..FF, ie is biased (!?!?) + if((~r) != 0) + { + seed.push_back(r); + return true; + } + } + + return false; // failed to produce an output after many attempts + } + +} + size_t POWER9_DARN::poll(RandomNumberGenerator& rng) { + const size_t DARN_BYTES = 1024; + static_assert(DARN_BYTES % 8 == 0, "Bad DARN configuration"); + if(CPUID::has_darn_rng()) { - secure_vector<uint64_t> seed(64); + secure_vector<uint64_t> seed; + seed.reserve(DARN_BYTES / 8); - for(size_t i = 0; i != seed.size(); ++i) - seed[i] = __builtin_darn_raw(); + for(size_t p = 0; p != DARN_BYTES / 8; ++p) + { + if(!read_darn(seed)) + break; + } - rng.add_entropy(reinterpret_cast<const uint8_t*>(seed.data()), - seed.size() * sizeof(uint64_t)); + if(seed.size() > 0) + { + rng.add_entropy(reinterpret_cast<const uint8_t*>(seed.data()), + seed.size() * sizeof(uint32_t)); + } } + // DARN is used but not trusted return 0; } |