From 2f760075a78f1d735cafb2aec750a100e52a5ea2 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Mon, 11 Feb 2019 15:43:29 +0100 Subject: [PATCH] Utility for using the RDRAND instruction On some x86_64 hardware the RDRAND instruction returns 64bits of entropy from an on-chip random number generator. RDRAND is not recommended as an exclusive source of entropy for cryptographic applications. https://en.wikipedia.org/wiki/RdRand --- include/spec/x86_64/world/rdrand.h | 56 ++++++++++++++++++++++++++++++ include/world/rdrand.h | 33 ++++++++++++++++++ recipes/pkg/test-rdrand/README | 1 + recipes/pkg/test-rdrand/archives | 1 + recipes/pkg/test-rdrand/hash | 1 + recipes/pkg/test-rdrand/runtime | 16 +++++++++ recipes/src/test-rdrand/content.mk | 7 ++++ recipes/src/test-rdrand/hash | 1 + recipes/src/test-rdrand/used_apis | 1 + src/test/rdrand/main.cc | 43 +++++++++++++++++++++++ src/test/rdrand/target.mk | 3 ++ 11 files changed, 163 insertions(+) create mode 100644 include/spec/x86_64/world/rdrand.h create mode 100644 include/world/rdrand.h create mode 100644 recipes/pkg/test-rdrand/README create mode 100644 recipes/pkg/test-rdrand/archives create mode 100644 recipes/pkg/test-rdrand/hash create mode 100644 recipes/pkg/test-rdrand/runtime create mode 100644 recipes/src/test-rdrand/content.mk create mode 100644 recipes/src/test-rdrand/hash create mode 100644 recipes/src/test-rdrand/used_apis create mode 100644 src/test/rdrand/main.cc create mode 100644 src/test/rdrand/target.mk diff --git a/include/spec/x86_64/world/rdrand.h b/include/spec/x86_64/world/rdrand.h new file mode 100644 index 0000000..a2f50df --- /dev/null +++ b/include/spec/x86_64/world/rdrand.h @@ -0,0 +1,56 @@ +/* + * \brief Utility for reading hardware RNG + * \date 2019-02-05 + * \author Emery Hemingway + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__X86_64__OS__RDRAND_H_ +#define _INCLUDE__SPEC__X86_64__OS__RDRAND_H_ + +#include +#include + +namespace Genode { namespace Rdrand { + + bool supported() + { + unsigned int info[4] = {0, 0, 0, 0}; + + asm volatile("cpuid":"=a"(info[0]),"=b"(info[1]),"=c"(info[2]),"=d"(info[3]):"a"(1),"c"(0)); + + enum { RDRAND_MASK = 0x40000000 }; + return (info[2] & RDRAND_MASK); + } + +# define _rdrand_step(x) \ + ({ \ + unsigned char err; \ + asm volatile("rdrand %0; setc %1":"=r"(x), "=qm"(err)); \ + err; \ + }) \ + + uint64_t random64() + { + uint64_t result = 0; + + enum { RETRIES = 8 }; + for (int i = 0; i < RETRIES; i++) + if (_rdrand_step(result)) + return result; + + error("RDRAND failure"); + throw Exception(); + } + +# undef _rdrand_step + +} } + +#endif /* _INCLUDE__SPEC__X86_64__OS__RDRAND_H_ */ diff --git a/include/world/rdrand.h b/include/world/rdrand.h new file mode 100644 index 0000000..30f42e8 --- /dev/null +++ b/include/world/rdrand.h @@ -0,0 +1,33 @@ +/* + * \brief Utility for reading hardware RNG + * \date 2019-02-05 + * \author Emery Hemingway + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__OS__RDRAND_H_ +#define _INCLUDE__OS__RDRAND_H_ + +#include +#include + +namespace Genode { namespace Rdrand { + + constexpr + bool supported() { return false; } + + uint64_t random64() + { + error("RDRAND not available on this architecture"); + throw Exception(); + } + +} } + +#endif /* _INCLUDE__OS__RDRAND_H_ */ diff --git a/recipes/pkg/test-rdrand/README b/recipes/pkg/test-rdrand/README new file mode 100644 index 0000000..e6111cb --- /dev/null +++ b/recipes/pkg/test-rdrand/README @@ -0,0 +1 @@ +Test for the RDRAND utility. diff --git a/recipes/pkg/test-rdrand/archives b/recipes/pkg/test-rdrand/archives new file mode 100644 index 0000000..baae4fc --- /dev/null +++ b/recipes/pkg/test-rdrand/archives @@ -0,0 +1 @@ +_/src/test-rdrand diff --git a/recipes/pkg/test-rdrand/hash b/recipes/pkg/test-rdrand/hash new file mode 100644 index 0000000..fd8a133 --- /dev/null +++ b/recipes/pkg/test-rdrand/hash @@ -0,0 +1 @@ +2019-02-05-b c847249e6a9161857212672d571d51e9ab537081 diff --git a/recipes/pkg/test-rdrand/runtime b/recipes/pkg/test-rdrand/runtime new file mode 100644 index 0000000..63b038a --- /dev/null +++ b/recipes/pkg/test-rdrand/runtime @@ -0,0 +1,16 @@ + + + + + --- RDRAND test finished --- + Error: + + + + + + + + + + diff --git a/recipes/src/test-rdrand/content.mk b/recipes/src/test-rdrand/content.mk new file mode 100644 index 0000000..d5ce335 --- /dev/null +++ b/recipes/src/test-rdrand/content.mk @@ -0,0 +1,7 @@ +SRC_DIR = src/test/rdrand +include $(GENODE_DIR)/repos/base/recipes/src/content.inc + +content: include/spec/x86_64/os/rdrand.h + +include/spec/x86_64/os/rdrand.h: + $(mirror_from_rep_dir) diff --git a/recipes/src/test-rdrand/hash b/recipes/src/test-rdrand/hash new file mode 100644 index 0000000..b85ebd6 --- /dev/null +++ b/recipes/src/test-rdrand/hash @@ -0,0 +1 @@ +2019-02-05-b 31ff420db86cb7010d3ffefa98ffbb6d1c1adc5c diff --git a/recipes/src/test-rdrand/used_apis b/recipes/src/test-rdrand/used_apis new file mode 100644 index 0000000..df967b9 --- /dev/null +++ b/recipes/src/test-rdrand/used_apis @@ -0,0 +1 @@ +base diff --git a/src/test/rdrand/main.cc b/src/test/rdrand/main.cc new file mode 100644 index 0000000..a44cff9 --- /dev/null +++ b/src/test/rdrand/main.cc @@ -0,0 +1,43 @@ +/* + * \brief RDRAND test + * \author Emery Hemingway + * \date 2019-02-05 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include + +using namespace Genode; + +void Component::construct(Genode::Env &env) +{ + log("--- RDRAND test started ---"); + + if (!Rdrand::supported()) { + log("RDRAND instruction not supported"); + } else { + uint64_t accumulator = 0; + + for (int i = 0; i < 32; i++) { + auto random = Rdrand::random64(); + log("RDRAND ", (Hex)random); + accumulator |= random; + } + + if (accumulator < (uint64_t(1)<<32)) { + error("RDRAND returned only 32 bits of entropy"); + env.parent().exit(~0); + } + } + + log("--- RDRAND test finished ---"); + env.parent().exit(0); +} diff --git a/src/test/rdrand/target.mk b/src/test/rdrand/target.mk new file mode 100644 index 0000000..52cb96a --- /dev/null +++ b/src/test/rdrand/target.mk @@ -0,0 +1,3 @@ +TARGET = test-rdrand +SRC_CC = main.cc +LIBS = base