Botan  2.13.0
Crypto and TLS for C++11
rdrand_rng.cpp
Go to the documentation of this file.
1 /*
2 * RDRAND RNG
3 * (C) 2016,2019 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/rdrand_rng.h>
9 #include <botan/loadstor.h>
10 #include <botan/cpuid.h>
11 
12 #if !defined(BOTAN_USE_GCC_INLINE_ASM)
13  #include <immintrin.h>
14 #endif
15 
16 namespace Botan {
17 
18 namespace {
19 
20 #if defined(BOTAN_TARGET_ARCH_IS_X86_64)
21  typedef uint64_t rdrand_output;
22 #else
23  typedef uint32_t rdrand_output;
24 #endif
25 
26 BOTAN_FUNC_ISA("rdrnd")
27 rdrand_output read_rdrand()
28  {
29  /*
30  * According to Intel, RDRAND is guaranteed to generate a random
31  * number within 10 retries on a working CPU
32  */
33  const size_t RDRAND_RETRIES = 10;
34 
35  for(size_t i = 0; i < RDRAND_RETRIES; ++i)
36  {
37  rdrand_output r = 0;
38  int cf = 0;
39 
40 #if defined(BOTAN_USE_GCC_INLINE_ASM)
41  // same asm seq works for 32 and 64 bit
42  asm("rdrand %0; adcl $0,%1" :
43  "=r" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
44 #elif defined(BOTAN_TARGET_ARCH_IS_X86_64)
45  cf = _rdrand64_step(&r);
46 #else
47  cf = _rdrand32_step(&r);
48 #endif
49  if(1 == cf)
50  {
51  return r;
52  }
53  }
54 
55  throw PRNG_Unseeded("RDRAND read failed");
56  }
57 
58 }
59 
60 void RDRAND_RNG::randomize(uint8_t out[], size_t out_len)
61  {
62  while(out_len >= sizeof(rdrand_output))
63  {
64  const rdrand_output r = read_rdrand();
65  store_le(r, out);
66  out += sizeof(rdrand_output);
67  out_len -= sizeof(rdrand_output);
68  }
69 
70  if(out_len > 0) // at most sizeof(rdrand_output)-1
71  {
72  const rdrand_output r = read_rdrand();
73  for(size_t i = 0; i != out_len; ++i)
74  out[i] = get_byte(i, r);
75  }
76  }
77 
79  {
81  throw Invalid_State("Current CPU does not support RDRAND instruction");
82  }
83 
84 //static
86  {
87  return CPUID::has_rdrand();
88  }
89 
90 //static
92  {
93  return static_cast<uint32_t>(read_rdrand());
94  }
95 
96 //static
97 BOTAN_FUNC_ISA("rdrnd")
98 uint32_t RDRAND_RNG::rdrand_status(bool& ok)
99  {
100  ok = false;
101 
102  try
103  {
104  const uint32_t r = static_cast<uint32_t>(read_rdrand());
105  ok = true;
106  return r;
107  }
108  catch(PRNG_Unseeded&) {}
109 
110  return 0;
111  }
112 
113 }
static bool available()
Definition: rdrand_rng.cpp:85
void randomize(uint8_t out[], size_t out_len) override
Definition: rdrand_rng.cpp:60
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
#define BOTAN_FUNC_ISA(isa)
Definition: compiler.h:71
Definition: alg_id.cpp:13
static uint32_t rdrand()
Definition: rdrand_rng.cpp:91
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:454