Skip to content

Commit 71a3cb8

Browse files
committed
first commit
1 parent c9440a2 commit 71a3cb8

20 files changed

+809
-4
lines changed

Cargo.toml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
[package]
22
name = "getrandom"
3-
version = "0.0.0"
3+
version = "0.1.0"
44
authors = ["The Rand Project Developers"]
5-
license = "MIT/Apache-2.0"
6-
edition = "2015"
5+
license = "MIT OR Apache-2.0"
76
description = "A small cross-platform library to securely get random data (entropy)"
87

9-
[dependencies]
8+
[badges]
9+
travis-ci = { repository = "rust-random/getrandom" }
10+
appveyor = { repository = "rust-random/getrandom" }
11+
12+
[target.'cfg(unix)'.dependencies]
13+
libc = "0.2"
14+
15+
[target.'cfg(windows)'.dependencies]
16+
winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "winnt"] }
17+
18+
[target.wasm32-unknown-unknown.dependencies]
19+
wasm-bindgen = { version = "0.2.12", optional = true }
20+
stdweb = { version = "0.4", optional = true }

src/cloudabi.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
use error::Error;
9+
10+
extern "C" {
11+
fn cloudabi_sys_random_get(buf: *mut u8, len: usize) -> u16;
12+
}
13+
14+
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
15+
let errno = unsafe { cloudabi_sys_random_get(dest.as_ptr(), dest.len()) };
16+
if errno == 0 {
17+
Ok(())
18+
} else {
19+
Err(Error::Unknown)
20+
}
21+
}

src/dragonfly_haiku.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! Implementation for DragonFly / Haiku
10+
use super::Error;
11+
use std::fs::File;
12+
use std::io::Read;
13+
use std::cell::RefCell;
14+
use std::ops::DerefMut;
15+
16+
thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
17+
18+
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
19+
RNG_FILE.with(|f| {
20+
let mut f = f.borrow_mut();
21+
let f: &mut Option<File> = f.deref_mut();
22+
if let Some(f) = f {
23+
f.read_exact(dest)
24+
} else {
25+
let mut rng_file = File::open("/dev/random")?;
26+
rng_file.read_exact(dest)?;
27+
*f = Some(rng_file);
28+
Ok(())
29+
}
30+
}).map_err(|_| Error::Unknown)
31+
}

src/dummy.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! A dummy implementation for unsupported targets which always returns
10+
//! `Err(Error::Unavailable)`
11+
use super::Error;
12+
13+
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
14+
Err(Error::Unavailable)
15+
}

src/emscripten.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! Implementation for DragonFly / Haiku / Emscripten
10+
use super::Error;
11+
use std::fs::File;
12+
use std::io::Read;
13+
use std::cell::RefCell;
14+
use std::ops::DerefMut;
15+
16+
thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
17+
18+
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
19+
// `Crypto.getRandomValues` documents `dest` should be at most 65536
20+
// bytes. `crypto.randomBytes` documents: "To minimize threadpool
21+
// task length variation, partition large randomBytes requests when
22+
// doing so as part of fulfilling a client request.
23+
for chunk in dest.chunks_mut(65536) {
24+
RNG_FILE.with(|f| {
25+
let mut f = f.borrow_mut();
26+
let f: &mut Option<File> = f.deref_mut();
27+
if let Some(f) = f {
28+
f.read_exact(chunk)
29+
} else {
30+
let mut rng_file = File::open("/dev/random")?;
31+
rng_file.read_exact(chunk)?;
32+
*f = Some(rng_file);
33+
Ok(())
34+
}
35+
}).map_err(|_| Error::Unknown)?;
36+
}
37+
Ok(())
38+
}

src/error.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
10+
pub enum Error {
11+
/// Call was interrupted.
12+
///
13+
/// Typically it can be retried.
14+
Interrupted,
15+
/// RNG source is unavailable on a given system.
16+
Unavailable,
17+
/// Unknown error.
18+
Unknown,
19+
#[doc(hidden)]
20+
__Nonexhaustive,
21+
}

src/freebsd.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! Implementation for FreeBSD
10+
extern crate libc;
11+
12+
use super::Error;
13+
use std::ptr;
14+
15+
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
16+
let mib = [libc::CTL_KERN, libc::KERN_ARND];
17+
// kern.arandom permits a maximum buffer size of 256 bytes
18+
for chunk in dest.chunks_mut(256) {
19+
let mut len = chunk.len();
20+
let ret = unsafe {
21+
libc::sysctl(
22+
mib.as_ptr(), mib.len() as libc::c_uint,
23+
chunk.as_mut_ptr() as *mut _, &mut len, ptr::null(), 0,
24+
)
25+
};
26+
if ret == -1 || len != chunk.len() {
27+
return Err(Error::Unknown);
28+
}
29+
}
30+
Ok(())
31+
}

src/fuchsia.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! Implementation for Fuchsia Zircon
10+
use super::Error;
11+
12+
#[link(name = "zircon")]
13+
extern {
14+
fn zx_cprng_draw(buffer: *mut u8, len: usize);
15+
}
16+
17+
pub fn getrandom(&mut self, dest: &mut [u8]) -> Result<(), Error> {
18+
for chunk in dest.chunks(256) {
19+
unsafe { zx_cprng_draw(chunk.as_mut_ptr(), chunk.len()) };
20+
}
21+
Ok(())
22+
}

src/lib.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,153 @@
55
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
8+
9+
10+
#![no_std]
11+
12+
#[cfg(any(
13+
target_os = "android",
14+
target_os = "netbsd",
15+
target_os = "solaris",
16+
target_os = "redox",
17+
target_os = "dragonfly",
18+
target_os = "haiku",
19+
target_os = "emscripten",
20+
target_os = "linux",
21+
))]
22+
#[macro_use] extern crate std;
23+
24+
mod error;
25+
pub use error::Error;
26+
27+
macro_rules! mod_use {
28+
($cond:meta, $module:ident) => {
29+
#[$cond]
30+
mod $module;
31+
#[$cond]
32+
pub use $module::getrandom;
33+
}
34+
}
35+
36+
mod_use!(cfg(target_os = "android"), linux_android);
37+
mod_use!(cfg(target_os = "bitrig"), openbsd_bitrig);
38+
mod_use!(cfg(target_os = "cloudabi"), cloudabi);
39+
mod_use!(cfg(target_os = "dragonfly"), dragonfly_haiku);
40+
mod_use!(cfg(target_os = "emscripten"), emscripten);
41+
mod_use!(cfg(target_os = "freebsd"), freebsd);
42+
mod_use!(cfg(target_os = "fuchsia"), fuchsia);
43+
mod_use!(cfg(target_os = "haiku"), dragonfly_haiku);
44+
mod_use!(cfg(target_os = "ios"), macos);
45+
mod_use!(cfg(target_os = "linux"), linux_android);
46+
mod_use!(cfg(target_os = "macos"), macos);
47+
mod_use!(cfg(target_os = "netbsd"), netbsd);
48+
mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig);
49+
mod_use!(cfg(target_os = "redox"), redox);
50+
mod_use!(cfg(target_os = "solaris"), solaris);
51+
mod_use!(cfg(windows), windows);
52+
mod_use!(cfg(target_env = "sgx"), sgx);
53+
54+
mod_use!(
55+
cfg(all(
56+
target_arch = "wasm32",
57+
not(target_os = "emscripten"),
58+
feature = "wasm-bindgen"
59+
)),
60+
wasm32_bindgen
61+
);
62+
63+
mod_use!(
64+
cfg(all(
65+
target_arch = "wasm32",
66+
not(target_os = "emscripten"),
67+
not(feature = "wasm-bindgen"),
68+
feature = "stdweb",
69+
)),
70+
wasm32_stdweb
71+
);
72+
73+
mod_use!(
74+
cfg(not(any(
75+
target_os = "android",
76+
target_os = "bitrig",
77+
target_os = "cloudabi",
78+
target_os = "dragonfly",
79+
target_os = "emscripten",
80+
target_os = "freebsd",
81+
target_os = "fuchsia",
82+
target_os = "haiku",
83+
target_os = "ios",
84+
target_os = "linux",
85+
target_os = "macos",
86+
target_os = "netbsd",
87+
target_os = "openbsd",
88+
target_os = "redox",
89+
target_os = "solaris",
90+
target_env = "sgx",
91+
windows,
92+
all(
93+
target_arch = "wasm32",
94+
any(
95+
target_os = "emscripten",
96+
feature = "wasm-bindgen",
97+
feature = "stdweb",
98+
),
99+
),
100+
))),
101+
dummy
102+
);
103+
104+
// Due to rustwasm/wasm-bindgen#201 this can't be defined in the inner os
105+
// modules, so hack around it for now and place it at the root.
106+
#[cfg(all(feature = "wasm-bindgen", target_arch = "wasm32"))]
107+
#[doc(hidden)]
108+
#[allow(missing_debug_implementations)]
109+
pub mod __wbg_shims {
110+
111+
// `extern { type Foo; }` isn't supported on 1.22 syntactically, so use a
112+
// macro to work around that.
113+
macro_rules! rust_122_compat {
114+
($($t:tt)*) => ($($t)*)
115+
}
116+
117+
rust_122_compat! {
118+
extern crate wasm_bindgen;
119+
120+
pub use wasm_bindgen::prelude::*;
121+
122+
#[wasm_bindgen]
123+
extern "C" {
124+
pub type Function;
125+
#[wasm_bindgen(constructor)]
126+
pub fn new(s: &str) -> Function;
127+
#[wasm_bindgen(method)]
128+
pub fn call(this: &Function, self_: &JsValue) -> JsValue;
129+
130+
pub type This;
131+
#[wasm_bindgen(method, getter, structural, js_name = self)]
132+
pub fn self_(me: &This) -> JsValue;
133+
#[wasm_bindgen(method, getter, structural)]
134+
pub fn crypto(me: &This) -> JsValue;
135+
136+
#[derive(Clone, Debug)]
137+
pub type BrowserCrypto;
138+
139+
// TODO: these `structural` annotations here ideally wouldn't be here to
140+
// avoid a JS shim, but for now with feature detection they're
141+
// unavoidable.
142+
#[wasm_bindgen(method, js_name = getRandomValues, structural, getter)]
143+
pub fn get_random_values_fn(me: &BrowserCrypto) -> JsValue;
144+
#[wasm_bindgen(method, js_name = getRandomValues, structural)]
145+
pub fn get_random_values(me: &BrowserCrypto, buf: &mut [u8]);
146+
147+
#[wasm_bindgen(js_name = require)]
148+
pub fn node_require(s: &str) -> NodeCrypto;
149+
150+
#[derive(Clone, Debug)]
151+
pub type NodeCrypto;
152+
153+
#[wasm_bindgen(method, js_name = randomFillSync, structural)]
154+
pub fn random_fill_sync(me: &NodeCrypto, buf: &mut [u8]);
155+
}
156+
}
157+
}

0 commit comments

Comments
 (0)