My Project 2.4.4
C++ Distributed Hash Table
Loading...
Searching...
No Matches
rng.h
1/*
2 * Copyright (C) 2014-2022 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#include <thread>
25#include <stdexcept>
26
27namespace dht {
28namespace crypto {
29
30#ifndef _MSC_VER
31#ifdef _WIN32
32
37class random_device {
38public:
39 using result_type = std::random_device::result_type;
40 using pseudo_engine = std::mt19937_64;
41
47 static_assert(
48 sizeof(result_type) == 2 ||
49 sizeof(result_type) == 4 ||
50 sizeof(result_type) == 8,
51 "result_type must be 16, 32 or 64 bits");
52
53 random_device();
54
55 result_type operator()();
56
57 static constexpr result_type min() {
58 return std::numeric_limits<result_type>::lowest();
59 }
60
61 static constexpr result_type max() {
62 return std::numeric_limits<result_type>::max();
63 }
64
65 double entropy() const {
66 if (hasRdrand() or hasRdseed())
67 return 1.;
68 return 0.;
69 }
70
71 static bool hasRdrand() {
72 static const bool hasrdrand = _hasRdrand();
73 return hasrdrand;
74 }
75
76 static bool hasRdseed() {
77 static const bool hasrdseed = _hasRdseed();
78 return hasrdseed;
79 }
80
81private:
82 random_device& operator=(random_device&) = delete;
83
84 pseudo_engine gen;
85 std::uniform_int_distribution<result_type> dis {};
86
87 static bool hasIntelCpu();
88 static bool _hasRdrand();
89 static bool _hasRdseed();
90
91 struct CPUIDinfo {
92 unsigned int EAX;
93 unsigned int EBX;
94 unsigned int ECX;
95 unsigned int EDX;
96 CPUIDinfo(const unsigned int func, const unsigned int subfunc);
97 };
98 bool rdrandStep(result_type* r);
99 bool rdrand(result_type* r);
100 bool rdseedStep(result_type* r);
101 bool rdseed(result_type* r);
102};
103
104#else
105
106using random_device = std::random_device;
107
108#endif
109#else
110using random_device = std::random_device;
111#endif
112
113template<class T = std::mt19937, std::size_t N = T::state_size>
114auto getSeededRandomEngine () -> typename std::enable_if<!!N, T>::type {
115 typename T::result_type random_data[N];
116 for (unsigned i=0; i<256; i++) {
117 try {
118 random_device source;
119 std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
120 std::seed_seq seeds(std::begin(random_data), std::end(random_data));
121 T seededEngine (seeds);
122 return seededEngine;
123 } catch (...) {
124 std::this_thread::sleep_for(std::chrono::milliseconds(1));
125 }
126 }
127 throw std::runtime_error("Can't seed random engine");
128}
129
130}} // dht::crypto
Definition: callbacks.h:35