4598
|
1 |
"{ Encoding: utf8 }"
|
|
2 |
|
4322
|
3 |
"
|
|
4 |
COPYRIGHT (c) 2014 Claus Gittinger
|
4667
|
5 |
All Rights Reserved
|
4322
|
6 |
|
|
7 |
This software is furnished under a license and may be used
|
|
8 |
only in accordance with the terms of that license and with the
|
|
9 |
inclusion of the above copyright notice. This software may not
|
|
10 |
be provided or otherwise made available to, or used by, any
|
|
11 |
other person. No title to or ownership of the software is
|
|
12 |
hereby transferred.
|
|
13 |
"
|
3405
|
14 |
"{ Package: 'stx:libbasic2' }"
|
|
15 |
|
4322
|
16 |
"{ NameSpace: Smalltalk }"
|
|
17 |
|
3405
|
18 |
Object subclass:#RandomRDRand
|
4926
|
19 |
instanceVariableNames:''
|
3405
|
20 |
classVariableNames:''
|
|
21 |
poolDictionaries:''
|
4595
|
22 |
category:'Magnitude-Numbers-Random'
|
3405
|
23 |
!
|
|
24 |
|
|
25 |
!RandomRDRand class methodsFor:'documentation'!
|
|
26 |
|
4322
|
27 |
copyright
|
|
28 |
"
|
|
29 |
COPYRIGHT (c) 2014 Claus Gittinger
|
4667
|
30 |
All Rights Reserved
|
4322
|
31 |
|
|
32 |
This software is furnished under a license and may be used
|
|
33 |
only in accordance with the terms of that license and with the
|
|
34 |
inclusion of the above copyright notice. This software may not
|
|
35 |
be provided or otherwise made available to, or used by, any
|
|
36 |
other person. No title to or ownership of the software is
|
|
37 |
hereby transferred.
|
|
38 |
"
|
|
39 |
!
|
|
40 |
|
3405
|
41 |
documentation
|
|
42 |
"
|
4598
|
43 |
This generator uses the rdgen random generator which is built into modern intel chips.
|
|
44 |
Before using, you should check via the isSupported query.
|
|
45 |
|
4667
|
46 |
Warning:
|
5067
|
47 |
there have been discussions about the security of the intel rdgen instruction
|
|
48 |
and whether there are NSA backdoors built into it.
|
|
49 |
Linus Torwalds refuses to use it for /dev/urandom in the linux kernel, for that very reason.
|
|
50 |
Be sure you know what you are doing, if you use this generator for sensitive cryptographic stuff.
|
|
51 |
We recommend using one of the libcrypt-based generators and use this only to get additional
|
|
52 |
entropy for the seed.
|
3405
|
53 |
|
5067
|
54 |
Warning2:
|
|
55 |
the initial release of the AMD Ryzen3000 (without BIOS update) has a bug in returning the same
|
|
56 |
(all 1s) random number every time.
|
|
57 |
The code here checks for that an raises an error in the constructor if that bug is detected.
|
|
58 |
Be sure to catch this exception in your code and fall back to another random generator if raised.
|
|
59 |
|
3405
|
60 |
NO WARRANTY
|
|
61 |
|
5080
|
62 |
[usage:]
|
|
63 |
RandomRDRand new nextInteger
|
3405
|
64 |
|
|
65 |
[see also:]
|
5067
|
66 |
RandomGenerator - the default; uses the machine's /dev/random if available
|
|
67 |
Random - fast, but generates less quality random numbers
|
|
68 |
RandomTT800 - another random generator
|
|
69 |
RandomParkMiller - another random generator
|
|
70 |
RandomMT19937 - another random generator
|
|
71 |
RandomKISS - another random generator
|
|
72 |
exept:libcrypt - a library containing more stuff based on hashes and cyphers
|
3405
|
73 |
|
|
74 |
[author:]
|
5067
|
75 |
Claus Gittinger.
|
3405
|
76 |
"
|
|
77 |
! !
|
|
78 |
|
|
79 |
!RandomRDRand class methodsFor:'instance creation'!
|
|
80 |
|
|
81 |
new
|
|
82 |
self isSupported ifFalse:[ self error:'this generator needs a cpu with rdgen instruction' ].
|
4598
|
83 |
^ self basicNew initialize
|
|
84 |
|
|
85 |
"
|
|
86 |
self new nextInteger
|
|
87 |
"
|
3405
|
88 |
!
|
|
89 |
|
|
90 |
new:seed
|
4598
|
91 |
"seed is actually ignored"
|
3405
|
92 |
|
|
93 |
self isSupported ifFalse:[ self error:'this generator needs a cpu with rdgen instruction' ].
|
4598
|
94 |
^ self basicNew initialize; seed:seed
|
3405
|
95 |
! !
|
|
96 |
|
|
97 |
!RandomRDRand class methodsFor:'queries'!
|
|
98 |
|
|
99 |
isSupported
|
|
100 |
"true if this architecture supports hardware random numbers"
|
|
101 |
|
4925
|
102 |
^ (OperatingSystem getSystemInfo at:#extendedInstructions ifAbsent:#())
|
|
103 |
includes:#rdmd
|
3405
|
104 |
|
|
105 |
"
|
|
106 |
self isSupported
|
|
107 |
"
|
4925
|
108 |
|
|
109 |
"Modified: / 28-03-2019 / 10:59:32 / Stefan Vogel"
|
3405
|
110 |
! !
|
|
111 |
|
|
112 |
!RandomRDRand methodsFor:'initialization'!
|
|
113 |
|
4926
|
114 |
initialize
|
5067
|
115 |
"check for Ryzen RDRAND bug (returning the same all-ones everytime)"
|
|
116 |
|
|
117 |
|i1 i2|
|
|
118 |
|
|
119 |
i1 := self nextInteger.
|
|
120 |
i2 := self nextInteger.
|
|
121 |
(i1 = i2) ifTrue:[
|
|
122 |
self error:'Ryzen RDRand bug detected'
|
|
123 |
].
|
|
124 |
|
|
125 |
"
|
|
126 |
self new
|
|
127 |
"
|
|
128 |
|
|
129 |
"Modified (comment): / 25-07-2019 / 13:30:28 / Claus Gittinger"
|
4926
|
130 |
!
|
|
131 |
|
3405
|
132 |
seed:seed
|
|
133 |
"/ ignored
|
|
134 |
! !
|
|
135 |
|
|
136 |
!RandomRDRand methodsFor:'random numbers'!
|
|
137 |
|
|
138 |
nextBoolean
|
3416
|
139 |
"generates a boolean random"
|
3405
|
140 |
|
4927
|
141 |
^ self nextInteger bitTest:1
|
4926
|
142 |
|
|
143 |
"
|
|
144 |
|bag rng|
|
|
145 |
|
|
146 |
rng := self new.
|
|
147 |
bag := Bag new.
|
|
148 |
100000 timesRepeat:[
|
|
149 |
bag add:rng nextBoolean.
|
|
150 |
].
|
|
151 |
bag
|
|
152 |
"
|
3405
|
153 |
!
|
|
154 |
|
|
155 |
nextInteger
|
4926
|
156 |
"generates the next integer in 0..MAXINT.
|
3405
|
157 |
Notice, it may raise an illegal instruction exception on some cpu chips,
|
|
158 |
even though the cpuid instruction says that it is available"
|
|
159 |
|
4667
|
160 |
|cfStillSet|
|
|
161 |
|
3405
|
162 |
%{
|
4598
|
163 |
unsigned INT r = 0;
|
4926
|
164 |
unsigned char cf;
|
4667
|
165 |
int count = 50;
|
3405
|
166 |
|
|
167 |
do {
|
4598
|
168 |
#ifdef USE_DRAND64
|
4887
|
169 |
cf = _rdrand64_step(&r);
|
4925
|
170 |
#elif defined(USE_DRAND32)
|
4887
|
171 |
cf = _rdrand32_step(&r);
|
4925
|
172 |
#elif defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2)
|
4887
|
173 |
// Encoding of rdrand %eax
|
4926
|
174 |
asm(".byte 0x0F, 0xC7, 0xF0; setc %1"
|
4887
|
175 |
: "=a" (r), "=r" (cf)
|
|
176 |
: "0" (r), "1" (cf)
|
|
177 |
: "cc");
|
4598
|
178 |
|
4925
|
179 |
#elif defined(__x86_64__) && defined(__GNUC__) && (__GNUC__ >= 2)
|
4887
|
180 |
// Encoding of rdrand %rax
|
4926
|
181 |
asm(".byte 0x48, 0x0F, 0xC7, 0xF0; setc %1"
|
4887
|
182 |
: "=a" (r), "=r" (cf)
|
|
183 |
: "0" (r), "1" (cf)
|
|
184 |
: "cc");
|
4667
|
185 |
|
4925
|
186 |
#else
|
4887
|
187 |
goto unsupported;
|
3405
|
188 |
#endif
|
4926
|
189 |
} while ((cf == 0) && (--count > 0));
|
|
190 |
if (cf != 0) {
|
4887
|
191 |
RETURN (__MKUINT(r));
|
4667
|
192 |
}
|
|
193 |
cfStillSet = true;
|
3405
|
194 |
unsupported: ;
|
|
195 |
%}.
|
4887
|
196 |
cfStillSet == true ifTrue:[
|
4927
|
197 |
self primitiveFailed:'carry flag not set after 50 tries'
|
4667
|
198 |
].
|
3405
|
199 |
self primitiveFailed:'unsupported on this architecture'
|
|
200 |
|
|
201 |
"
|
|
202 |
self new nextInteger
|
|
203 |
"
|
4925
|
204 |
|
|
205 |
"Modified: / 28-03-2019 / 10:46:29 / Stefan Vogel"
|
3405
|
206 |
! !
|
|
207 |
|
|
208 |
!RandomRDRand class methodsFor:'documentation'!
|
|
209 |
|
|
210 |
version
|
4322
|
211 |
^ '$Header$'
|
3405
|
212 |
!
|
|
213 |
|
|
214 |
version_CVS
|
4322
|
215 |
^ '$Header$'
|
3405
|
216 |
! !
|
4887
|
217 |
|