11
11
//! Interfaces to the operating system provided random number
12
12
//! generators.
13
13
14
- use std:: io ;
14
+ use std:: { io , mem } ;
15
15
use Rng ;
16
16
17
17
/// A random number generator that retrieves randomness straight from
@@ -40,18 +40,31 @@ impl Rng for OsRng {
40
40
fn fill_bytes ( & mut self , v : & mut [ u8 ] ) { self . 0 . fill_bytes ( v) }
41
41
}
42
42
43
+ fn next_u32 ( mut fill_buf : & mut FnMut ( & mut [ u8 ] ) ) -> u32 {
44
+ let mut buf: [ u8 ; 4 ] = [ 0 ; 4 ] ;
45
+ fill_buf ( & mut buf) ;
46
+ unsafe { mem:: transmute :: < [ u8 ; 4 ] , u32 > ( buf) }
47
+ }
48
+
49
+ fn next_u64 ( mut fill_buf : & mut FnMut ( & mut [ u8 ] ) ) -> u64 {
50
+ let mut buf: [ u8 ; 8 ] = [ 0 ; 8 ] ;
51
+ fill_buf ( & mut buf) ;
52
+ unsafe { mem:: transmute :: < [ u8 ; 8 ] , u64 > ( buf) }
53
+ }
54
+
43
55
#[ cfg( all( unix, not( target_os = "ios" ) ,
44
- not( target_os = "nacl" ) ) ) ]
56
+ not( target_os = "nacl" ) ,
57
+ not( target_os = "freebsd" ) ) ) ]
45
58
mod imp {
46
59
extern crate libc;
47
60
61
+ use super :: { next_u32, next_u64} ;
48
62
use self :: OsRngInner :: * ;
49
63
50
64
use std:: io;
51
65
use std:: fs:: File ;
52
66
use Rng ;
53
67
use read:: ReadRng ;
54
- use std:: mem;
55
68
56
69
#[ cfg( all( target_os = "linux" ,
57
70
any( target_arch = "x86_64" ,
@@ -106,18 +119,6 @@ mod imp {
106
119
}
107
120
}
108
121
109
- fn getrandom_next_u32 ( ) -> u32 {
110
- let mut buf: [ u8 ; 4 ] = [ 0u8 ; 4 ] ;
111
- getrandom_fill_bytes ( & mut buf) ;
112
- unsafe { mem:: transmute :: < [ u8 ; 4 ] , u32 > ( buf) }
113
- }
114
-
115
- fn getrandom_next_u64 ( ) -> u64 {
116
- let mut buf: [ u8 ; 8 ] = [ 0u8 ; 8 ] ;
117
- getrandom_fill_bytes ( & mut buf) ;
118
- unsafe { mem:: transmute :: < [ u8 ; 8 ] , u64 > ( buf) }
119
- }
120
-
121
122
#[ cfg( all( target_os = "linux" ,
122
123
any( target_arch = "x86_64" ,
123
124
target_arch = "x86" ,
@@ -179,13 +180,13 @@ mod imp {
179
180
impl Rng for OsRng {
180
181
fn next_u32 ( & mut self ) -> u32 {
181
182
match self . inner {
182
- OsGetrandomRng => getrandom_next_u32 ( ) ,
183
+ OsGetrandomRng => next_u32 ( & mut getrandom_fill_bytes ) ,
183
184
OsReadRng ( ref mut rng) => rng. next_u32 ( ) ,
184
185
}
185
186
}
186
187
fn next_u64 ( & mut self ) -> u64 {
187
188
match self . inner {
188
- OsGetrandomRng => getrandom_next_u64 ( ) ,
189
+ OsGetrandomRng => next_u64 ( & mut getrandom_fill_bytes ) ,
189
190
OsReadRng ( ref mut rng) => rng. next_u64 ( ) ,
190
191
}
191
192
}
@@ -202,8 +203,9 @@ mod imp {
202
203
mod imp {
203
204
extern crate libc;
204
205
206
+ use super :: { next_u32, next_u64} ;
207
+
205
208
use std:: io;
206
- use std:: mem;
207
209
use Rng ;
208
210
use self :: libc:: { c_int, size_t} ;
209
211
@@ -228,14 +230,10 @@ mod imp {
228
230
229
231
impl Rng for OsRng {
230
232
fn next_u32 ( & mut self ) -> u32 {
231
- let mut v = [ 0u8 ; 4 ] ;
232
- self . fill_bytes ( & mut v) ;
233
- unsafe { mem:: transmute ( v) }
233
+ next_u32 ( & mut |v| self . fill_bytes ( v) )
234
234
}
235
235
fn next_u64 ( & mut self ) -> u64 {
236
- let mut v = [ 0u8 ; 8 ] ;
237
- self . fill_bytes ( & mut v) ;
238
- unsafe { mem:: transmute ( v) }
236
+ next_u64 ( & mut |v| self . fill_bytes ( v) )
239
237
}
240
238
fn fill_bytes ( & mut self , v : & mut [ u8 ] ) {
241
239
let ret = unsafe {
@@ -248,13 +246,57 @@ mod imp {
248
246
}
249
247
}
250
248
249
+ #[ cfg( target_os = "freebsd" ) ]
250
+ mod imp {
251
+ extern crate libc;
252
+
253
+ use std:: { io, ptr} ;
254
+ use Rng ;
255
+
256
+ use super :: { next_u32, next_u64} ;
257
+
258
+ pub struct OsRng ;
259
+
260
+ impl OsRng {
261
+ pub fn new ( ) -> io:: Result < OsRng > {
262
+ Ok ( OsRng )
263
+ }
264
+ }
265
+
266
+ impl Rng for OsRng {
267
+ fn next_u32 ( & mut self ) -> u32 {
268
+ next_u32 ( & mut |v| self . fill_bytes ( v) )
269
+ }
270
+ fn next_u64 ( & mut self ) -> u64 {
271
+ next_u64 ( & mut |v| self . fill_bytes ( v) )
272
+ }
273
+ fn fill_bytes ( & mut self , v : & mut [ u8 ] ) {
274
+ let mib = [ libc:: CTL_KERN , libc:: KERN_ARND ] ;
275
+ // kern.arandom permits a maximum buffer size of 256 bytes
276
+ for s in v. chunks_mut ( 256 ) {
277
+ let mut s_len = s. len ( ) ;
278
+ let ret = unsafe {
279
+ libc:: sysctl ( mib. as_ptr ( ) , mib. len ( ) as libc:: c_uint ,
280
+ s. as_mut_ptr ( ) as * mut _ , & mut s_len,
281
+ ptr:: null ( ) , 0 )
282
+ } ;
283
+ if ret == -1 || s_len != s. len ( ) {
284
+ panic ! ( "kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})" ,
285
+ ret, s. len( ) , s_len) ;
286
+ }
287
+ }
288
+ }
289
+ }
290
+ }
291
+
251
292
#[ cfg( windows) ]
252
293
mod imp {
253
294
use std:: io;
254
- use std:: mem;
255
295
use std:: ptr;
256
296
use Rng ;
257
297
298
+ use super :: { next_u32, next_u64} ;
299
+
258
300
type BOOL = i32 ;
259
301
type LPCSTR = * const i8 ;
260
302
type DWORD = u32 ;
@@ -301,14 +343,10 @@ mod imp {
301
343
302
344
impl Rng for OsRng {
303
345
fn next_u32 ( & mut self ) -> u32 {
304
- let mut v = [ 0u8 ; 4 ] ;
305
- self . fill_bytes ( & mut v) ;
306
- unsafe { mem:: transmute ( v) }
346
+ next_u32 ( & mut |v| self . fill_bytes ( v) )
307
347
}
308
348
fn next_u64 ( & mut self ) -> u64 {
309
- let mut v = [ 0u8 ; 8 ] ;
310
- self . fill_bytes ( & mut v) ;
311
- unsafe { mem:: transmute ( v) }
349
+ next_u64 ( & mut |v| self . fill_bytes ( v) )
312
350
}
313
351
fn fill_bytes ( & mut self , v : & mut [ u8 ] ) {
314
352
// CryptGenRandom takes a DWORD (u32) for the length so we need to
@@ -347,6 +385,8 @@ mod imp {
347
385
use std:: mem;
348
386
use Rng ;
349
387
388
+ use super :: { next_u32, next_u64} ;
389
+
350
390
pub struct OsRng ( extern fn ( dest : * mut libc:: c_void ,
351
391
bytes : libc:: size_t ,
352
392
read : * mut libc:: size_t ) -> libc:: c_int ) ;
@@ -390,14 +430,10 @@ mod imp {
390
430
391
431
impl Rng for OsRng {
392
432
fn next_u32 ( & mut self ) -> u32 {
393
- let mut v = [ 0u8 ; 4 ] ;
394
- self . fill_bytes ( & mut v) ;
395
- unsafe { mem:: transmute ( v) }
433
+ next_u32 ( & mut |v| self . fill_bytes ( v) )
396
434
}
397
435
fn next_u64 ( & mut self ) -> u64 {
398
- let mut v = [ 0u8 ; 8 ] ;
399
- self . fill_bytes ( & mut v) ;
400
- unsafe { mem:: transmute ( v) }
436
+ next_u64 ( & mut |v| self . fill_bytes ( v) )
401
437
}
402
438
fn fill_bytes ( & mut self , v : & mut [ u8 ] ) {
403
439
let mut read = 0 ;
0 commit comments