1*58b9f456SAndroid Build Coastguard Worker //===-------------------------- random.cpp --------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker
10*58b9f456SAndroid Build Coastguard Worker #include <__config>
11*58b9f456SAndroid Build Coastguard Worker
12*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_USING_WIN32_RANDOM)
13*58b9f456SAndroid Build Coastguard Worker // Must be defined before including stdlib.h to enable rand_s().
14*58b9f456SAndroid Build Coastguard Worker #define _CRT_RAND_S
15*58b9f456SAndroid Build Coastguard Worker #endif // defined(_LIBCPP_USING_WIN32_RANDOM)
16*58b9f456SAndroid Build Coastguard Worker
17*58b9f456SAndroid Build Coastguard Worker #include "random"
18*58b9f456SAndroid Build Coastguard Worker #include "system_error"
19*58b9f456SAndroid Build Coastguard Worker
20*58b9f456SAndroid Build Coastguard Worker #if defined(__sun__)
21*58b9f456SAndroid Build Coastguard Worker #define rename solaris_headers_are_broken
22*58b9f456SAndroid Build Coastguard Worker #endif // defined(__sun__)
23*58b9f456SAndroid Build Coastguard Worker
24*58b9f456SAndroid Build Coastguard Worker #include <errno.h>
25*58b9f456SAndroid Build Coastguard Worker #include <stdio.h>
26*58b9f456SAndroid Build Coastguard Worker #include <stdlib.h>
27*58b9f456SAndroid Build Coastguard Worker
28*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_USING_GETENTROPY)
29*58b9f456SAndroid Build Coastguard Worker #include <sys/random.h>
30*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_DEV_RANDOM)
31*58b9f456SAndroid Build Coastguard Worker #include <fcntl.h>
32*58b9f456SAndroid Build Coastguard Worker #include <unistd.h>
33*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_NACL_RANDOM)
34*58b9f456SAndroid Build Coastguard Worker #include <nacl/nacl_random.h>
35*58b9f456SAndroid Build Coastguard Worker #endif
36*58b9f456SAndroid Build Coastguard Worker
37*58b9f456SAndroid Build Coastguard Worker
38*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
39*58b9f456SAndroid Build Coastguard Worker
40*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_USING_GETENTROPY)
41*58b9f456SAndroid Build Coastguard Worker
random_device(const string & __token)42*58b9f456SAndroid Build Coastguard Worker random_device::random_device(const string& __token)
43*58b9f456SAndroid Build Coastguard Worker {
44*58b9f456SAndroid Build Coastguard Worker if (__token != "/dev/urandom")
45*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
46*58b9f456SAndroid Build Coastguard Worker }
47*58b9f456SAndroid Build Coastguard Worker
~random_device()48*58b9f456SAndroid Build Coastguard Worker random_device::~random_device()
49*58b9f456SAndroid Build Coastguard Worker {
50*58b9f456SAndroid Build Coastguard Worker }
51*58b9f456SAndroid Build Coastguard Worker
52*58b9f456SAndroid Build Coastguard Worker unsigned
operator ()()53*58b9f456SAndroid Build Coastguard Worker random_device::operator()()
54*58b9f456SAndroid Build Coastguard Worker {
55*58b9f456SAndroid Build Coastguard Worker unsigned r;
56*58b9f456SAndroid Build Coastguard Worker size_t n = sizeof(r);
57*58b9f456SAndroid Build Coastguard Worker int err = getentropy(&r, n);
58*58b9f456SAndroid Build Coastguard Worker if (err)
59*58b9f456SAndroid Build Coastguard Worker __throw_system_error(errno, "random_device getentropy failed");
60*58b9f456SAndroid Build Coastguard Worker return r;
61*58b9f456SAndroid Build Coastguard Worker }
62*58b9f456SAndroid Build Coastguard Worker
63*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_ARC4_RANDOM)
64*58b9f456SAndroid Build Coastguard Worker
65*58b9f456SAndroid Build Coastguard Worker random_device::random_device(const string& __token)
66*58b9f456SAndroid Build Coastguard Worker {
67*58b9f456SAndroid Build Coastguard Worker if (__token != "/dev/urandom")
68*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
69*58b9f456SAndroid Build Coastguard Worker }
70*58b9f456SAndroid Build Coastguard Worker
71*58b9f456SAndroid Build Coastguard Worker random_device::~random_device()
72*58b9f456SAndroid Build Coastguard Worker {
73*58b9f456SAndroid Build Coastguard Worker }
74*58b9f456SAndroid Build Coastguard Worker
75*58b9f456SAndroid Build Coastguard Worker unsigned
76*58b9f456SAndroid Build Coastguard Worker random_device::operator()()
77*58b9f456SAndroid Build Coastguard Worker {
78*58b9f456SAndroid Build Coastguard Worker return arc4random();
79*58b9f456SAndroid Build Coastguard Worker }
80*58b9f456SAndroid Build Coastguard Worker
81*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_DEV_RANDOM)
82*58b9f456SAndroid Build Coastguard Worker
83*58b9f456SAndroid Build Coastguard Worker random_device::random_device(const string& __token)
84*58b9f456SAndroid Build Coastguard Worker : __f_(open(__token.c_str(), O_RDONLY))
85*58b9f456SAndroid Build Coastguard Worker {
86*58b9f456SAndroid Build Coastguard Worker if (__f_ < 0)
87*58b9f456SAndroid Build Coastguard Worker __throw_system_error(errno, ("random_device failed to open " + __token).c_str());
88*58b9f456SAndroid Build Coastguard Worker }
89*58b9f456SAndroid Build Coastguard Worker
90*58b9f456SAndroid Build Coastguard Worker random_device::~random_device()
91*58b9f456SAndroid Build Coastguard Worker {
92*58b9f456SAndroid Build Coastguard Worker close(__f_);
93*58b9f456SAndroid Build Coastguard Worker }
94*58b9f456SAndroid Build Coastguard Worker
95*58b9f456SAndroid Build Coastguard Worker unsigned
96*58b9f456SAndroid Build Coastguard Worker random_device::operator()()
97*58b9f456SAndroid Build Coastguard Worker {
98*58b9f456SAndroid Build Coastguard Worker unsigned r;
99*58b9f456SAndroid Build Coastguard Worker size_t n = sizeof(r);
100*58b9f456SAndroid Build Coastguard Worker char* p = reinterpret_cast<char*>(&r);
101*58b9f456SAndroid Build Coastguard Worker while (n > 0)
102*58b9f456SAndroid Build Coastguard Worker {
103*58b9f456SAndroid Build Coastguard Worker ssize_t s = read(__f_, p, n);
104*58b9f456SAndroid Build Coastguard Worker if (s == 0)
105*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ENODATA, "random_device got EOF");
106*58b9f456SAndroid Build Coastguard Worker if (s == -1)
107*58b9f456SAndroid Build Coastguard Worker {
108*58b9f456SAndroid Build Coastguard Worker if (errno != EINTR)
109*58b9f456SAndroid Build Coastguard Worker __throw_system_error(errno, "random_device got an unexpected error");
110*58b9f456SAndroid Build Coastguard Worker continue;
111*58b9f456SAndroid Build Coastguard Worker }
112*58b9f456SAndroid Build Coastguard Worker n -= static_cast<size_t>(s);
113*58b9f456SAndroid Build Coastguard Worker p += static_cast<size_t>(s);
114*58b9f456SAndroid Build Coastguard Worker }
115*58b9f456SAndroid Build Coastguard Worker return r;
116*58b9f456SAndroid Build Coastguard Worker }
117*58b9f456SAndroid Build Coastguard Worker
118*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_NACL_RANDOM)
119*58b9f456SAndroid Build Coastguard Worker
120*58b9f456SAndroid Build Coastguard Worker random_device::random_device(const string& __token)
121*58b9f456SAndroid Build Coastguard Worker {
122*58b9f456SAndroid Build Coastguard Worker if (__token != "/dev/urandom")
123*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
124*58b9f456SAndroid Build Coastguard Worker int error = nacl_secure_random_init();
125*58b9f456SAndroid Build Coastguard Worker if (error)
126*58b9f456SAndroid Build Coastguard Worker __throw_system_error(error, ("random device failed to open " + __token).c_str());
127*58b9f456SAndroid Build Coastguard Worker }
128*58b9f456SAndroid Build Coastguard Worker
129*58b9f456SAndroid Build Coastguard Worker random_device::~random_device()
130*58b9f456SAndroid Build Coastguard Worker {
131*58b9f456SAndroid Build Coastguard Worker }
132*58b9f456SAndroid Build Coastguard Worker
133*58b9f456SAndroid Build Coastguard Worker unsigned
134*58b9f456SAndroid Build Coastguard Worker random_device::operator()()
135*58b9f456SAndroid Build Coastguard Worker {
136*58b9f456SAndroid Build Coastguard Worker unsigned r;
137*58b9f456SAndroid Build Coastguard Worker size_t n = sizeof(r);
138*58b9f456SAndroid Build Coastguard Worker size_t bytes_written;
139*58b9f456SAndroid Build Coastguard Worker int error = nacl_secure_random(&r, n, &bytes_written);
140*58b9f456SAndroid Build Coastguard Worker if (error != 0)
141*58b9f456SAndroid Build Coastguard Worker __throw_system_error(error, "random_device failed getting bytes");
142*58b9f456SAndroid Build Coastguard Worker else if (bytes_written != n)
143*58b9f456SAndroid Build Coastguard Worker __throw_runtime_error("random_device failed to obtain enough bytes");
144*58b9f456SAndroid Build Coastguard Worker return r;
145*58b9f456SAndroid Build Coastguard Worker }
146*58b9f456SAndroid Build Coastguard Worker
147*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USING_WIN32_RANDOM)
148*58b9f456SAndroid Build Coastguard Worker
149*58b9f456SAndroid Build Coastguard Worker random_device::random_device(const string& __token)
150*58b9f456SAndroid Build Coastguard Worker {
151*58b9f456SAndroid Build Coastguard Worker if (__token != "/dev/urandom")
152*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
153*58b9f456SAndroid Build Coastguard Worker }
154*58b9f456SAndroid Build Coastguard Worker
155*58b9f456SAndroid Build Coastguard Worker random_device::~random_device()
156*58b9f456SAndroid Build Coastguard Worker {
157*58b9f456SAndroid Build Coastguard Worker }
158*58b9f456SAndroid Build Coastguard Worker
159*58b9f456SAndroid Build Coastguard Worker unsigned
160*58b9f456SAndroid Build Coastguard Worker random_device::operator()()
161*58b9f456SAndroid Build Coastguard Worker {
162*58b9f456SAndroid Build Coastguard Worker unsigned r;
163*58b9f456SAndroid Build Coastguard Worker errno_t err = rand_s(&r);
164*58b9f456SAndroid Build Coastguard Worker if (err)
165*58b9f456SAndroid Build Coastguard Worker __throw_system_error(err, "random_device rand_s failed.");
166*58b9f456SAndroid Build Coastguard Worker return r;
167*58b9f456SAndroid Build Coastguard Worker }
168*58b9f456SAndroid Build Coastguard Worker
169*58b9f456SAndroid Build Coastguard Worker #else
170*58b9f456SAndroid Build Coastguard Worker #error "Random device not implemented for this architecture"
171*58b9f456SAndroid Build Coastguard Worker #endif
172*58b9f456SAndroid Build Coastguard Worker
173*58b9f456SAndroid Build Coastguard Worker double
entropy() const174*58b9f456SAndroid Build Coastguard Worker random_device::entropy() const _NOEXCEPT
175*58b9f456SAndroid Build Coastguard Worker {
176*58b9f456SAndroid Build Coastguard Worker return 0;
177*58b9f456SAndroid Build Coastguard Worker }
178*58b9f456SAndroid Build Coastguard Worker
179*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
180