1313
1414pub use self :: imp:: OsRng ;
1515
16- #[ cfg( all( unix, not( target_os = "ios" ) ) ) ]
16+ #[ cfg( all( unix, not( target_os = "ios" ) , not ( target_os = "openbsd" ) ) ) ]
1717mod imp {
1818 use self :: OsRngInner :: * ;
1919
@@ -131,6 +131,7 @@ mod imp {
131131 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
132132 /// service provider with the `PROV_RSA_FULL` type.
133133 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
134+ /// - OpenBSD: uses the `getentropy(2)` system call.
134135 ///
135136 /// This does not block.
136137 pub struct OsRng {
@@ -178,6 +179,63 @@ mod imp {
178179 }
179180}
180181
182+ #[ cfg( target_os = "openbsd" ) ]
183+ mod imp {
184+ use io;
185+ use mem;
186+ use libc:: c_long;
187+ use sys:: os:: errno;
188+ use rand:: Rng ;
189+
190+ /// A random number generator that retrieves randomness straight from
191+ /// the operating system. Platform sources:
192+ ///
193+ /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
194+ /// `/dev/urandom`, or from `getrandom(2)` system call if available.
195+ /// - Windows: calls `CryptGenRandom`, using the default cryptographic
196+ /// service provider with the `PROV_RSA_FULL` type.
197+ /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
198+ /// - OpenBSD: uses the `getentropy(2)` system call.
199+ ///
200+ /// This does not block.
201+ pub struct OsRng {
202+ // dummy field to ensure that this struct cannot be constructed outside
203+ // of this module
204+ _dummy : ( ) ,
205+ }
206+
207+ impl OsRng {
208+ /// Create a new `OsRng`.
209+ pub fn new ( ) -> io:: Result < OsRng > {
210+ Ok ( OsRng { _dummy : ( ) } )
211+ }
212+ }
213+
214+ impl Rng for OsRng {
215+ fn next_u32 ( & mut self ) -> u32 {
216+ let mut v = [ 0 ; 4 ] ;
217+ self . fill_bytes ( & mut v) ;
218+ unsafe { mem:: transmute ( v) }
219+ }
220+ fn next_u64 ( & mut self ) -> u64 {
221+ let mut v = [ 0 ; 8 ] ;
222+ self . fill_bytes ( & mut v) ;
223+ unsafe { mem:: transmute ( v) }
224+ }
225+ fn fill_bytes ( & mut self , v : & mut [ u8 ] ) {
226+ // getentropy(2) permits a maximum buffer size of 256 bytes
227+ for s in v. chunks_mut ( 256 ) {
228+ let ret = unsafe {
229+ libc:: syscall ( libc:: NR_GETENTROPY , s. as_mut_ptr ( ) , s. len ( ) )
230+ } ;
231+ if ret == -1 {
232+ panic ! ( "unexpected getentropy error: {}" , errno( ) ) ;
233+ }
234+ }
235+ }
236+ }
237+ }
238+
181239#[ cfg( target_os = "ios" ) ]
182240mod imp {
183241 #[ cfg( stage0) ] use prelude:: v1:: * ;
@@ -196,6 +254,7 @@ mod imp {
196254 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
197255 /// service provider with the `PROV_RSA_FULL` type.
198256 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
257+ /// - OpenBSD: uses the `getentropy(2)` system call.
199258 ///
200259 /// This does not block.
201260 pub struct OsRng {
@@ -261,6 +320,7 @@ mod imp {
261320 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
262321 /// service provider with the `PROV_RSA_FULL` type.
263322 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
323+ /// - OpenBSD: uses the `getentropy(2)` system call.
264324 ///
265325 /// This does not block.
266326 pub struct OsRng {
0 commit comments