C++ Distributed Hash Table
rng.h
1 /*
2  * Copyright (C) 2014-2017 Savoir-faire Linux Inc.
3  * Author : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <random>
22 #include <algorithm>
23 #include <functional>
24 
25 namespace dht {
26 namespace crypto {
27 
28 #ifndef _MSC_VER
29 #ifdef _WIN32
30 
35 class random_device {
36 public:
37  using result_type = std::random_device::result_type;
38  using pseudo_engine = std::mt19937_64;
39 
45  static_assert(
46  sizeof(result_type) == 2 ||
47  sizeof(result_type) == 4 ||
48  sizeof(result_type) == 8,
49  "result_type must be 16, 32 or 64 bits");
50 
51  random_device();
52 
53  result_type operator()();
54 
55  static constexpr result_type min() {
56  return std::numeric_limits<result_type>::lowest();
57  }
58 
59  static constexpr result_type max() {
60  return std::numeric_limits<result_type>::max();
61  }
62 
63  double entropy() const {
64  if (hasRdrand() or hasRdseed())
65  return 1.;
66  return 0.;
67  }
68 
69  static bool hasRdrand() {
70  static const bool hasrdrand = _hasRdrand();
71  return hasrdrand;
72  }
73 
74  static bool hasRdseed() {
75  static const bool hasrdseed = _hasRdseed();
76  return hasrdseed;
77  }
78 
79 private:
80  random_device& operator=(random_device&) = delete;
81 
82  pseudo_engine gen;
83  std::uniform_int_distribution<result_type> dis {};
84 
85  static bool hasIntelCpu();
86  static bool _hasRdrand();
87  static bool _hasRdseed();
88 
89  struct CPUIDinfo {
90  unsigned int EAX;
91  unsigned int EBX;
92  unsigned int ECX;
93  unsigned int EDX;
94  CPUIDinfo(const unsigned int func, const unsigned int subfunc);
95  };
96  bool rdrandStep(result_type* r);
97  bool rdrand(result_type* r);
98  bool rdseedStep(result_type* r);
99  bool rdseed(result_type* r);
100 };
101 
102 #else
103 
104 using random_device = std::random_device;
105 
106 #endif
107 #else
108 using random_device = std::random_device;
109 #endif
110 
111 template<class T = std::mt19937, std::size_t N = T::state_size>
112 auto getSeededRandomEngine () -> typename std::enable_if<!!N, T>::type {
113  typename T::result_type random_data[N];
114  random_device source;
115  std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
116  std::seed_seq seeds(std::begin(random_data), std::end(random_data));
117  T seededEngine (seeds);
118  return seededEngine;
119 }
120 
121 }} // dht::crypto
Definition: callbacks.h:34