aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/entropy
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-08-27 09:38:59 -0400
committerJack Lloyd <[email protected]>2019-08-27 09:42:34 -0400
commita9c3413bcd155a6a70a8b8c64a073f5db19cd86c (patch)
treed811fc2cedd003e1a3d69a5854d9d439d40ab8ba /src/lib/entropy
parent308bdc190f4e6a3606f801390d191988a0438557 (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.txt8
-rw-r--r--src/lib/entropy/p9_darn/p9_darn.cpp47
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;
}