aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-08-27 20:04:51 -0400
committerJack Lloyd <[email protected]>2019-08-27 20:04:51 -0400
commitff416dcc98f2952792419410b6afff4c87abd489 (patch)
tree29fe6ebf915639c3754dcbd41b94b4a52158008c
parentb4543c801cde2874b982bbaccba471bd14c27810 (diff)
parenta9c3413bcd155a6a70a8b8c64a073f5db19cd86c (diff)
Merge GH #2026 Add support for POWER9 hardware RNG
-rw-r--r--src/build-data/arch/ppc64.txt1
-rw-r--r--src/build-data/buildh.in2
-rw-r--r--src/build-data/cc/gcc.txt1
-rw-r--r--src/lib/entropy/entropy_srcs.cpp11
-rw-r--r--src/lib/entropy/p9_darn/info.txt11
-rw-r--r--src/lib/entropy/p9_darn/p9_darn.cpp65
-rw-r--r--src/lib/entropy/p9_darn/p9_darn.h23
-rw-r--r--src/lib/utils/cpuid/cpuid.cpp1
-rw-r--r--src/lib/utils/cpuid/cpuid.h7
-rw-r--r--src/lib/utils/cpuid/cpuid_ppc.cpp3
10 files changed, 124 insertions, 1 deletions
diff --git a/src/build-data/arch/ppc64.txt b/src/build-data/arch/ppc64.txt
index 23d3bb2a1..470bee2db 100644
--- a/src/build-data/arch/ppc64.txt
+++ b/src/build-data/arch/ppc64.txt
@@ -13,4 +13,5 @@ ppc64el
<isa_extensions>
altivec
ppccrypto
+power9
</isa_extensions>
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index caa160eb0..425d06498 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -181,7 +181,7 @@
* broken system RNG.
*/
#define BOTAN_ENTROPY_DEFAULT_SOURCES \
- { "rdseed", "rdrand", "getentropy", "dev_random", \
+ { "rdseed", "rdrand", "p9_darn", "getentropy", "dev_random", \
"system_rng", "proc_walk", "system_stats" }
/* Multiplier on a block cipher's native parallelism */
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index f495af4e6..cc3ce99e1 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -63,6 +63,7 @@ sha -> "-msha"
altivec -> "-maltivec"
ppccrypto -> "-mcrypto"
+power9 -> "-mcpu=power9"
arm64:armv8crypto -> ""
arm64:armv8sm3 -> "-march=armv8.2-a+sm4"
diff --git a/src/lib/entropy/entropy_srcs.cpp b/src/lib/entropy/entropy_srcs.cpp
index 85e0b6dc5..ba60ed62d 100644
--- a/src/lib/entropy/entropy_srcs.cpp
+++ b/src/lib/entropy/entropy_srcs.cpp
@@ -20,6 +20,10 @@
#include <botan/internal/rdseed.h>
#endif
+#if defined(BOTAN_HAS_ENTROPY_SRC_DARN)
+ #include <botan/internal/p9_darn.h>
+#endif
+
#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
#include <botan/internal/dev_random.h>
#endif
@@ -83,6 +87,13 @@ std::unique_ptr<Entropy_Source> Entropy_Source::create(const std::string& name)
}
#endif
+#if defined(BOTAN_HAS_ENTROPY_SRC_DARN)
+ if(name == "p9_darn")
+ {
+ return std::unique_ptr<Entropy_Source>(new POWER9_DARN);
+ }
+#endif
+
#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
if(name == "getentropy")
{
diff --git a/src/lib/entropy/p9_darn/info.txt b/src/lib/entropy/p9_darn/info.txt
new file mode 100644
index 000000000..47d99aa3d
--- /dev/null
+++ b/src/lib/entropy/p9_darn/info.txt
@@ -0,0 +1,11 @@
+<defines>
+ENTROPY_SRC_DARN -> 20180610
+</defines>
+
+<header:internal>
+p9_darn.h
+</header:internal>
+
+<arch>
+ppc64
+</arch>
diff --git a/src/lib/entropy/p9_darn/p9_darn.cpp b/src/lib/entropy/p9_darn/p9_darn.cpp
new file mode 100644
index 000000000..8731b94e1
--- /dev/null
+++ b/src/lib/entropy/p9_darn/p9_darn.cpp
@@ -0,0 +1,65 @@
+/*
+* (C) 2019 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/p9_darn.h>
+#include <botan/cpuid.h>
+
+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;
+ seed.reserve(DARN_BYTES / 8);
+
+ for(size_t p = 0; p != DARN_BYTES / 8; ++p)
+ {
+ if(!read_darn(seed))
+ break;
+ }
+
+ 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;
+ }
+
+}
diff --git a/src/lib/entropy/p9_darn/p9_darn.h b/src/lib/entropy/p9_darn/p9_darn.h
new file mode 100644
index 000000000..9d8c508a1
--- /dev/null
+++ b/src/lib/entropy/p9_darn/p9_darn.h
@@ -0,0 +1,23 @@
+/*
+* (C) 2019 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_DARN_H_
+#define BOTAN_ENTROPY_SRC_DARN_H_
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+class POWER9_DARN final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "p9_darn"; }
+ size_t poll(RandomNumberGenerator& rng) override;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/cpuid/cpuid.cpp b/src/lib/utils/cpuid/cpuid.cpp
index e890af061..18ccff419 100644
--- a/src/lib/utils/cpuid/cpuid.cpp
+++ b/src/lib/utils/cpuid/cpuid.cpp
@@ -63,6 +63,7 @@ std::string CPUID::to_string()
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
CPUID_PRINT(altivec);
CPUID_PRINT(ppc_crypto);
+ CPUID_PRINT(darn_rng);
#endif
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
diff --git a/src/lib/utils/cpuid/cpuid.h b/src/lib/utils/cpuid/cpuid.h
index d278a8fcc..256c6cc57 100644
--- a/src/lib/utils/cpuid/cpuid.h
+++ b/src/lib/utils/cpuid/cpuid.h
@@ -107,6 +107,7 @@ class BOTAN_PUBLIC_API(2,1) CPUID final
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
CPUID_ALTIVEC_BIT = (1ULL << 0),
CPUID_PPC_CRYPTO_BIT = (1ULL << 1),
+ CPUID_DARN_BIT = (1ULL << 2),
#endif
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
@@ -138,6 +139,12 @@ class BOTAN_PUBLIC_API(2,1) CPUID final
static bool has_ppc_crypto()
{ return has_cpuid_bit(CPUID_PPC_CRYPTO_BIT); }
+ /**
+ * Check if the processor supports POWER9 DARN RNG
+ */
+ static bool has_darn_rng()
+ { return has_cpuid_bit(CPUID_DARN_BIT); }
+
#endif
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
diff --git a/src/lib/utils/cpuid/cpuid_ppc.cpp b/src/lib/utils/cpuid/cpuid_ppc.cpp
index 08a04cafd..ff528d88e 100644
--- a/src/lib/utils/cpuid/cpuid_ppc.cpp
+++ b/src/lib/utils/cpuid/cpuid_ppc.cpp
@@ -58,6 +58,7 @@ uint64_t CPUID::CPUID_Data::detect_cpu_features(size_t* cache_line_size)
enum PPC_hwcap_bit {
ALTIVEC_bit = (1 << 28),
CRYPTO_bit = (1 << 25),
+ DARN_bit = (1 << 21),
ARCH_hwcap_altivec = 16, // AT_HWCAP
ARCH_hwcap_crypto = 26, // AT_HWCAP2
@@ -72,6 +73,8 @@ uint64_t CPUID::CPUID_Data::detect_cpu_features(size_t* cache_line_size)
const unsigned long hwcap_crypto = OS::get_auxval(PPC_hwcap_bit::ARCH_hwcap_crypto);
if(hwcap_crypto & PPC_hwcap_bit::CRYPTO_bit)
detected_features |= CPUID::CPUID_PPC_CRYPTO_BIT;
+ if(hwcap_crypto & PPC_hwcap_bit::DARN_bit)
+ detected_features |= CPUID::CPUID_DARN_BIT;
return detected_features;