1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Interfaces to the operating system provided random number
14 pub use self::imp::OsRng;
16 #[cfg(unix, not(target_os = "ios"))]
18 use io::{IoResult, File};
21 use rand::reader::ReaderRng;
22 use result::{Ok, Err};
24 /// A random number generator that retrieves randomness straight from
25 /// the operating system. Platform sources:
27 /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
29 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
30 /// service provider with the `PROV_RSA_FULL` type.
31 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
32 /// This does not block.
35 inner: ReaderRng<File>
39 /// Create a new `OsRng`.
40 pub fn new() -> IoResult<OsRng> {
41 let reader = try!(File::open(&Path::new("/dev/urandom")));
42 let reader_rng = ReaderRng::new(reader);
44 Ok(OsRng { inner: reader_rng })
49 fn next_u32(&mut self) -> u32 {
52 fn next_u64(&mut self) -> u64 {
55 fn fill_bytes(&mut self, v: &mut [u8]) {
56 self.inner.fill_bytes(v)
61 #[cfg(target_os = "ios")]
65 use collections::Collection;
72 use self::libc::{c_int, size_t};
73 use slice::MutableVector;
75 /// A random number generator that retrieves randomness straight from
76 /// the operating system. Platform sources:
78 /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
80 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
81 /// service provider with the `PROV_RSA_FULL` type.
82 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
83 /// This does not block.
85 marker: marker::NoCopy
90 static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
92 #[link(name = "Security", kind = "framework")]
94 fn SecRandomCopyBytes(rnd: *const SecRandom,
95 count: size_t, bytes: *mut u8) -> c_int;
99 /// Create a new `OsRng`.
100 pub fn new() -> IoResult<OsRng> {
101 Ok(OsRng {marker: marker::NoCopy} )
106 fn next_u32(&mut self) -> u32 {
107 let mut v = [0u8, .. 4];
109 unsafe { mem::transmute(v) }
111 fn next_u64(&mut self) -> u64 {
112 let mut v = [0u8, .. 8];
114 unsafe { mem::transmute(v) }
116 fn fill_bytes(&mut self, v: &mut [u8]) {
118 SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
121 fail!("couldn't generate random bytes: {}", os::last_os_error());
131 use core_collections::Collection;
132 use io::{IoResult, IoError};
137 use result::{Ok, Err};
139 use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
140 use self::libc::types::os::arch::extra::{LONG_PTR};
141 use slice::MutableVector;
143 type HCRYPTPROV = LONG_PTR;
145 /// A random number generator that retrieves randomness straight from
146 /// the operating system. Platform sources:
148 /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
150 /// - Windows: calls `CryptGenRandom`, using the default cryptographic
151 /// service provider with the `PROV_RSA_FULL` type.
153 /// This does not block.
155 hcryptprov: HCRYPTPROV
158 static PROV_RSA_FULL: DWORD = 1;
159 static CRYPT_SILENT: DWORD = 64;
160 static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
161 static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
163 #[allow(non_snake_case_functions)]
165 fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
166 pszContainer: LPCSTR,
169 dwFlags: DWORD) -> BOOL;
170 fn CryptGenRandom(hProv: HCRYPTPROV,
172 pbBuffer: *mut BYTE) -> BOOL;
173 fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
177 /// Create a new `OsRng`.
178 pub fn new() -> IoResult<OsRng> {
180 let mut ret = unsafe {
181 CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
183 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
187 // It turns out that if we can't acquire a context with the
188 // NTE_BAD_SIGNATURE error code, the documentation states:
190 // The provider DLL signature could not be verified. Either the
191 // DLL or the digital signature has been tampered with.
193 // Sounds fishy, no? As it turns out, our signature can be bad
194 // because our Thread Information Block (TIB) isn't exactly what it
195 // expects. As to why, I have no idea. The only data we store in the
196 // TIB is the stack limit for each thread, but apparently that's
197 // enough to make the signature valid.
199 // Furthermore, this error only happens the *first* time we call
200 // CryptAcquireContext, so we don't have to worry about future
203 // Anyway, the fix employed here is that if we see this error, we
204 // pray that we're not close to the end of the stack, temporarily
205 // set the stack limit to 0 (what the TIB originally was), acquire a
206 // context, and then reset the stack limit.
208 // Again, I'm not sure why this is the fix, nor why we're getting
209 // this error. All I can say is that this seems to allow libnative
210 // to progress where it otherwise would be hindered. Who knew?
211 if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
213 let limit = stack::get_sp_limit();
214 stack::record_sp_limit(0);
215 ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
217 CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
218 stack::record_sp_limit(limit);
223 Err(IoError::last_error())
225 Ok(OsRng { hcryptprov: hcp })
231 fn next_u32(&mut self) -> u32 {
232 let mut v = [0u8, .. 4];
234 unsafe { mem::transmute(v) }
236 fn next_u64(&mut self) -> u64 {
237 let mut v = [0u8, .. 8];
239 unsafe { mem::transmute(v) }
241 fn fill_bytes(&mut self, v: &mut [u8]) {
243 CryptGenRandom(self.hcryptprov, v.len() as DWORD,
247 fail!("couldn't generate random bytes: {}", os::last_os_error());
252 impl Drop for OsRng {
255 CryptReleaseContext(self.hcryptprov, 0)
258 fail!("couldn't release context: {}", os::last_os_error());
274 let mut r = OsRng::new().unwrap();
279 let mut v = [0u8, .. 1000];
284 fn test_os_rng_tasks() {
286 let mut txs = vec!();
287 for _ in range(0u, 20) {
288 let (tx, rx) = channel();
291 // wait until all the tasks are ready to go.
294 // deschedule to attempt to interleave things as much
295 // as possible (XXX: is this a good test?)
296 let mut r = OsRng::new().unwrap();
298 let mut v = [0u8, .. 1000];
300 for _ in range(0u, 100) {
311 // start all the tasks
312 for tx in txs.iter() {