Botan  2.4.0
Crypto and TLS for C++11
rdrand_rng.cpp
Go to the documentation of this file.
1 /*
2 * RDRAND RNG
3 * (C) 2016 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 
19  {
20  if(!CPUID::has_rdrand())
21  throw Exception("Current CPU does not support RDRAND instruction");
22  }
23 
24 //static
26  {
27  for(;;)
28  {
29  bool ok = false;
30  uint32_t r = rdrand_status(ok);
31  if(ok)
32  return r;
33  }
34  }
35 
36 //static
37 BOTAN_FUNC_ISA("rdrnd")
38 uint32_t RDRAND_RNG::rdrand_status(bool& ok)
39  {
40  ok = false;
41  uint32_t r = 0;
42 
43  for(size_t i = 0; i != BOTAN_ENTROPY_RDRAND_RETRIES; ++i)
44  {
45 #if defined(BOTAN_USE_GCC_INLINE_ASM)
46  int cf = 0;
47 
48  // Encoding of rdrand %eax
49  asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" :
50  "=a" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
51 #else
52  int cf = _rdrand32_step(&r);
53 #endif
54  if(1 == cf)
55  {
56  ok = true;
57  break;
58  }
59  }
60 
61  return r;
62  }
63 
64 void RDRAND_RNG::randomize(uint8_t out[], size_t out_len)
65  {
66  while(out_len >= 4)
67  {
68  uint32_t r = RDRAND_RNG::rdrand();
69 
70  store_le(r, out);
71  out += 4;
72  out_len -= 4;
73  }
74 
75  if(out_len) // between 1 and 3 trailing bytes
76  {
77  uint32_t r = RDRAND_RNG::rdrand();
78  for(size_t i = 0; i != out_len; ++i)
79  out[i] = get_byte(i, r);
80  }
81  }
82 
83 }
void randomize(uint8_t out[], size_t out_len) override
Definition: rdrand_rng.cpp:64
static uint32_t rdrand_status(bool &ok)
Definition: rdrand_rng.cpp:38
#define BOTAN_FUNC_ISA(isa)
Definition: compiler.h:75
Definition: alg_id.cpp:13
static uint32_t rdrand()
Definition: rdrand_rng.cpp:25
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:450