]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/windows/rand.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / libstd / sys / windows / rand.rs
1 // Copyright 2013-2015 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.
4 //
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.
10
11
12 use io;
13 use mem;
14 use rand::Rng;
15 use sys::c;
16
17 pub struct OsRng {
18 hcryptprov: c::HCRYPTPROV
19 }
20
21 impl OsRng {
22 /// Create a new `OsRng`.
23 pub fn new() -> io::Result<OsRng> {
24 let mut hcp = 0;
25 let ret = unsafe {
26 c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
27 c::PROV_RSA_FULL,
28 c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
29 };
30
31 if ret == 0 {
32 Err(io::Error::last_os_error())
33 } else {
34 Ok(OsRng { hcryptprov: hcp })
35 }
36 }
37 }
38
39 impl Rng for OsRng {
40 fn next_u32(&mut self) -> u32 {
41 let mut v = [0; 4];
42 self.fill_bytes(&mut v);
43 unsafe { mem::transmute(v) }
44 }
45 fn next_u64(&mut self) -> u64 {
46 let mut v = [0; 8];
47 self.fill_bytes(&mut v);
48 unsafe { mem::transmute(v) }
49 }
50 fn fill_bytes(&mut self, v: &mut [u8]) {
51 // CryptGenRandom takes a DWORD (u32) for the length so we need to
52 // split up the buffer.
53 for slice in v.chunks_mut(<c::DWORD>::max_value() as usize) {
54 let ret = unsafe {
55 c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
56 slice.as_mut_ptr())
57 };
58 if ret == 0 {
59 panic!("couldn't generate random bytes: {}",
60 io::Error::last_os_error());
61 }
62 }
63 }
64 }
65
66 impl Drop for OsRng {
67 fn drop(&mut self) {
68 let ret = unsafe {
69 c::CryptReleaseContext(self.hcryptprov, 0)
70 };
71 if ret == 0 {
72 panic!("couldn't release context: {}",
73 io::Error::last_os_error());
74 }
75 }
76 }