+14
@@ -37,6 +37,9 @@ matrix:
|
||||
- rm -rf target/doc
|
||||
- cargo doc --no-deps --all --all-features
|
||||
- cargo deadlinks --dir target/doc
|
||||
# also test minimum dependency versions are usable
|
||||
- cargo generate-lockfile -Z minimal-versions
|
||||
- cargo test
|
||||
|
||||
- rust: nightly
|
||||
os: osx
|
||||
@@ -52,6 +55,9 @@ matrix:
|
||||
- rm -rf target/doc
|
||||
- cargo doc --no-deps --all --all-features
|
||||
- cargo deadlinks --dir target/doc
|
||||
# also test minimum dependency versions are usable
|
||||
- cargo generate-lockfile -Z minimal-versions
|
||||
- cargo test
|
||||
|
||||
- rust: nightly
|
||||
env: DESCRIPTION="WASM via emscripten, stdweb and wasm-bindgen"
|
||||
@@ -97,6 +103,14 @@ matrix:
|
||||
#- cargo build --target=x86_64-unknown-fuchsia --all-features
|
||||
- cargo build --target=x86_64-unknown-netbsd --all-features
|
||||
- cargo build --target=x86_64-unknown-redox --all-features
|
||||
# also test minimum dependency versions are usable
|
||||
- cargo generate-lockfile -Z minimal-versions
|
||||
- cargo build --target=x86_64-sun-solaris --all-features
|
||||
- cargo build --target=x86_64-unknown-cloudabi --all-features
|
||||
- cargo build --target=x86_64-unknown-freebsd --all-features
|
||||
#- cargo build --target=x86_64-unknown-fuchsia --all-features
|
||||
- cargo build --target=x86_64-unknown-netbsd --all-features
|
||||
- cargo build --target=x86_64-unknown-redox --all-features
|
||||
|
||||
# Trust cross-built/emulated targets. We must repeat all non-default values.
|
||||
- rust: stable
|
||||
|
||||
+8
-4
@@ -14,11 +14,15 @@ members = [
|
||||
"tests/wasm_bindgen",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4", optional = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
# In general, we need at least 0.2.27. On Solaris, we need some unknown newer version.
|
||||
libc = "0.2.50"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "winnt"] }
|
||||
winapi = { version = "0.3.6", features = ["minwindef", "ntsecapi", "winnt"] }
|
||||
|
||||
[target.'cfg(target_os = "cloudabi")'.dependencies]
|
||||
cloudabi = "0.0.3"
|
||||
@@ -27,5 +31,5 @@ cloudabi = "0.0.3"
|
||||
fuchsia-cprng = "0.1"
|
||||
|
||||
[target.wasm32-unknown-unknown.dependencies]
|
||||
wasm-bindgen = { version = "0.2.12", optional = true }
|
||||
stdweb = { version = "0.4", optional = true }
|
||||
wasm-bindgen = { version = "0.2.29", optional = true }
|
||||
stdweb = { version = "0.4.9", optional = true }
|
||||
|
||||
@@ -38,6 +38,9 @@ fn get_random_buf() -> Result<[u8; 32], getrandom::Error> {
|
||||
|
||||
This library is `no_std` compatible on SGX but requires `std` on most platforms.
|
||||
|
||||
The `log` library is supported as an optional dependency. If enabled, error
|
||||
reporting will be improved on some platforms.
|
||||
|
||||
For WebAssembly (`wasm32`), Enscripten targets are supported directly; otherwise
|
||||
one of the following features must be enabled:
|
||||
|
||||
|
||||
+5
-1
@@ -11,7 +11,7 @@
|
||||
extern crate cloudabi;
|
||||
|
||||
use core::num::NonZeroU32;
|
||||
use error::Error;
|
||||
use Error;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
let errno = unsafe { cloudabi::random_get(dest) };
|
||||
@@ -19,6 +19,10 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
} else {
|
||||
let code = NonZeroU32::new(errno as u32).unwrap();
|
||||
error!("cloudabi::random_get syscall failed with code {}", code);
|
||||
Err(Error::from(code))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for DragonFly / Haiku
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use Error;
|
||||
use utils::use_init;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
|
||||
|
||||
@@ -23,3 +24,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+9
-4
@@ -7,9 +7,14 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! A dummy implementation for unsupported targets which always returns
|
||||
//! `Err(UNAVAILABLE_ERROR)`
|
||||
use super::UNAVAILABLE_ERROR;
|
||||
//! `Err(ERROR_UNAVAILABLE)`
|
||||
use std::num::NonZeroU32;
|
||||
use {Error, ERROR_UNAVAILABLE};
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
Err(UNAVAILABLE_ERROR)
|
||||
pub fn getrandom_inner(_: &mut [u8]) -> Result<(), Error> {
|
||||
error!("no support for this platform");
|
||||
Err(ERROR_UNAVAILABLE)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-2
@@ -7,11 +7,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for Emscripten
|
||||
use super::Error;
|
||||
use Error;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::cell::RefCell;
|
||||
use super::utils::use_init;
|
||||
use std::num::NonZeroU32;
|
||||
use utils::use_init;
|
||||
|
||||
thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
|
||||
|
||||
@@ -29,3 +30,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+54
-16
@@ -12,20 +12,29 @@ use core::fmt;
|
||||
#[cfg(not(target_env = "sgx"))]
|
||||
use std::{io, error};
|
||||
|
||||
// A randomly-chosen 16-bit prefix for our codes
|
||||
pub(crate) const CODE_PREFIX: u32 = 0x57f40000;
|
||||
const CODE_UNKNOWN: u32 = CODE_PREFIX | 0;
|
||||
const CODE_UNAVAILABLE: u32 = CODE_PREFIX | 1;
|
||||
|
||||
/// An unknown error.
|
||||
pub const UNKNOWN_ERROR: Error = Error(unsafe {
|
||||
NonZeroU32::new_unchecked(0x756e6b6e) // "unkn"
|
||||
///
|
||||
/// This is the following constant: 57F40000 (hex) / 1475608576 (decimal).
|
||||
pub const ERROR_UNKNOWN: Error = Error(unsafe {
|
||||
NonZeroU32::new_unchecked(CODE_UNKNOWN)
|
||||
});
|
||||
|
||||
/// No generator is available.
|
||||
pub const UNAVAILABLE_ERROR: Error = Error(unsafe {
|
||||
NonZeroU32::new_unchecked(0x4e416e61) // "NAna"
|
||||
///
|
||||
/// This is the following constant: 57F40001 (hex) / 1475608577 (decimal).
|
||||
pub const ERROR_UNAVAILABLE: Error = Error(unsafe {
|
||||
NonZeroU32::new_unchecked(CODE_UNAVAILABLE)
|
||||
});
|
||||
|
||||
/// The error type.
|
||||
///
|
||||
/// This type is small and no-std compatible.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct Error(NonZeroU32);
|
||||
|
||||
impl Error {
|
||||
@@ -38,14 +47,34 @@ impl Error {
|
||||
pub fn code(&self) -> NonZeroU32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn msg(&self) -> Option<&'static str> {
|
||||
if let Some(msg) = super::error_msg_inner(self.0) {
|
||||
Some(msg)
|
||||
} else {
|
||||
match *self {
|
||||
ERROR_UNKNOWN => Some("getrandom: unknown error"),
|
||||
ERROR_UNAVAILABLE => Some("getrandom: unavailable"),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self.msg() {
|
||||
Some(msg) => write!(f, "Error(\"{}\")", msg),
|
||||
None => write!(f, "Error(0x{:08X})", self.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
UNKNOWN_ERROR => write!(f, "Getrandom Error: unknown"),
|
||||
UNAVAILABLE_ERROR => write!(f, "Getrandom Error: unavailable"),
|
||||
code => write!(f, "Getrandom Error: {}", code.0.get()),
|
||||
match self.msg() {
|
||||
Some(msg) => write!(f, "{}", msg),
|
||||
None => write!(f, "getrandom: unknown code 0x{:08X}", self.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,22 +92,31 @@ impl From<io::Error> for Error {
|
||||
.and_then(|code| NonZeroU32::new(code as u32))
|
||||
.map(|code| Error(code))
|
||||
// in practice this should never happen
|
||||
.unwrap_or(UNKNOWN_ERROR)
|
||||
.unwrap_or(ERROR_UNKNOWN)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_env = "sgx"))]
|
||||
impl From<Error> for io::Error {
|
||||
fn from(err: Error) -> Self {
|
||||
match err {
|
||||
UNKNOWN_ERROR => io::Error::new(io::ErrorKind::Other,
|
||||
"getrandom error: unknown"),
|
||||
UNAVAILABLE_ERROR => io::Error::new(io::ErrorKind::Other,
|
||||
"getrandom error: entropy source is unavailable"),
|
||||
code => io::Error::from_raw_os_error(code.0.get() as i32),
|
||||
match err.msg() {
|
||||
Some(msg) => io::Error::new(io::ErrorKind::Other, msg),
|
||||
None => io::Error::from_raw_os_error(err.0.get() as i32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_env = "sgx"))]
|
||||
impl error::Error for Error { }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::mem::size_of;
|
||||
use super::Error;
|
||||
|
||||
#[test]
|
||||
fn test_size() {
|
||||
assert_eq!(size_of::<Error>(), 4);
|
||||
assert_eq!(size_of::<Result<(), Error>>(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -9,9 +9,10 @@
|
||||
//! Implementation for FreeBSD
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use Error;
|
||||
use core::ptr;
|
||||
use std::io;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
let mib = [libc::CTL_KERN, libc::KERN_ARND];
|
||||
@@ -25,8 +26,12 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
)
|
||||
};
|
||||
if ret == -1 || len != chunk.len() {
|
||||
error!("freebsd: kern.arandom syscall failed");
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+5
-1
@@ -9,9 +9,13 @@
|
||||
//! Implementation for Fuchsia Zircon
|
||||
extern crate fuchsia_cprng;
|
||||
|
||||
use super::Error;
|
||||
use std::num::NonZeroU32;
|
||||
use Error;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
fuchsia_cprng::cprng_draw(dest);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+7
-4
@@ -111,6 +111,10 @@ extern crate wasm_bindgen;
|
||||
feature = "stdweb"))]
|
||||
#[macro_use] extern crate stdweb;
|
||||
|
||||
#[cfg(feature = "log")] #[macro_use] extern crate log;
|
||||
#[allow(unused)]
|
||||
#[cfg(not(feature = "log"))] macro_rules! error { ($($x:tt)*) => () }
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "netbsd",
|
||||
@@ -124,8 +128,7 @@ extern crate wasm_bindgen;
|
||||
))]
|
||||
mod utils;
|
||||
mod error;
|
||||
pub use error::{Error, UNKNOWN_ERROR, UNAVAILABLE_ERROR};
|
||||
|
||||
pub use error::{Error, ERROR_UNKNOWN, ERROR_UNAVAILABLE};
|
||||
|
||||
// System-specific implementations.
|
||||
//
|
||||
@@ -136,7 +139,7 @@ macro_rules! mod_use {
|
||||
#[$cond]
|
||||
mod $module;
|
||||
#[$cond]
|
||||
use $module::getrandom_inner;
|
||||
use $module::{getrandom_inner, error_msg_inner};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +224,7 @@ mod_use!(
|
||||
/// In general, `getrandom` will be fast enough for interactive usage, though
|
||||
/// significantly slower than a user-space CSPRNG; for the latter consider
|
||||
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
|
||||
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
|
||||
getrandom_inner(dest)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
//! Implementation for Linux / Android
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use Error;
|
||||
use utils::use_init;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
static RNG_INIT: AtomicBool = AtomicBool::new(false);
|
||||
@@ -33,6 +34,7 @@ fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> {
|
||||
libc::syscall(libc::SYS_getrandom, dest.as_mut_ptr(), dest.len(), 0)
|
||||
};
|
||||
if ret < 0 || (ret as usize) != dest.len() {
|
||||
error!("Linux getrandom syscall failed with return value {}", ret);
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
@@ -80,3 +82,6 @@ fn is_getrandom_available() -> bool {
|
||||
|
||||
AVAILABLE.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-1
@@ -9,8 +9,9 @@
|
||||
//! Implementation for MacOS / iOS
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use Error;
|
||||
use std::io;
|
||||
use std::num::NonZeroU32;
|
||||
use self::libc::{c_int, size_t};
|
||||
|
||||
enum SecRandom {}
|
||||
@@ -35,8 +36,12 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
)
|
||||
};
|
||||
if ret == -1 {
|
||||
error!("SecRandomCopyBytes call failed");
|
||||
Err(io::Error::last_os_error().into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-2
@@ -8,11 +8,12 @@
|
||||
|
||||
//! Implementation for NetBSD
|
||||
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use Error;
|
||||
use utils::use_init;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
static RNG_INIT: AtomicBool = AtomicBool::new(false);
|
||||
@@ -32,3 +33,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
}, |f| f.read_exact(dest).map_err(From::from))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
//! Implementation for OpenBSD / Bitrig
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use Error;
|
||||
use std::io;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
@@ -21,8 +22,12 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
)
|
||||
};
|
||||
if ret == -1 {
|
||||
error!("libc::getentropy call failed");
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-2
@@ -7,11 +7,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for Redox
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use Error;
|
||||
use utils::use_init;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
|
||||
|
||||
@@ -23,3 +24,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
)
|
||||
}).map_err(From::from)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-2
@@ -7,10 +7,11 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for SGX using RDRAND instruction
|
||||
use super::{Error, UNKNOWN_ERROR};
|
||||
use {Error, ERROR_UNKNOWN};
|
||||
|
||||
use core::{mem, ptr};
|
||||
use core::arch::x86_64::_rdrand64_step;
|
||||
use core::num::NonZeroU32;
|
||||
|
||||
#[cfg(not(target_feature = "rdrand"))]
|
||||
compile_error!("enable rdrand target feature!");
|
||||
@@ -26,7 +27,7 @@ fn get_rand_u64() -> Result<u64, Error> {
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(UNKNOWN_ERROR)
|
||||
Err(ERROR_UNKNOWN)
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(mut dest: &mut [u8]) -> Result<(), Error> {
|
||||
@@ -46,3 +47,6 @@ pub fn getrandom_inner(mut dest: &mut [u8]) -> Result<(), Error> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+6
-1
@@ -19,11 +19,12 @@
|
||||
//! libc::dlsym.
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use Error;
|
||||
use std::cell::RefCell;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::num::NonZeroU32;
|
||||
use utils::use_init;
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
@@ -44,6 +45,7 @@ fn libc_getrandom(rand: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> {
|
||||
let ret = unsafe { rand(dest.as_mut_ptr(), dest.len(), 0) as libc::ssize_t };
|
||||
|
||||
if ret == -1 || ret != dest.len() as libc::ssize_t {
|
||||
error!("getrandom syscall failed with ret={}", ret);
|
||||
Err(io::Error::last_os_error().into())
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -97,3 +99,6 @@ fn fetch_getrandom() -> Option<GetRandomFn> {
|
||||
let ptr = FPTR.load(Ordering::SeqCst);
|
||||
unsafe { mem::transmute::<usize, Option<GetRandomFn>>(ptr) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
use super::Error;
|
||||
use Error;
|
||||
use core::cell::RefCell;
|
||||
use core::ops::DerefMut;
|
||||
|
||||
|
||||
+22
-7
@@ -10,13 +10,17 @@
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::mem;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use super::__wbg_shims::*;
|
||||
use super::{Error, UNAVAILABLE_ERROR};
|
||||
use super::utils::use_init;
|
||||
use __wbg_shims::*;
|
||||
use Error;
|
||||
use utils::use_init;
|
||||
|
||||
const CODE_PREFIX: u32 = ::error::CODE_PREFIX | 0x8e00;
|
||||
const CODE_CRYPTO_UNDEF: u32 = CODE_PREFIX | 1;
|
||||
const CODE_GRV_UNDEF: u32 = CODE_PREFIX | 2;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum RngSource {
|
||||
@@ -75,18 +79,29 @@ fn getrandom_init() -> Result<RngSource, Error> {
|
||||
// we're in an older web browser and the OS RNG isn't available.
|
||||
let crypto = this.crypto();
|
||||
if crypto.is_undefined() {
|
||||
let msg = "self.crypto is undefined";
|
||||
return Err(UNAVAILABLE_ERROR) // TODO: report msg
|
||||
return Err(Error::from(unsafe {
|
||||
NonZeroU32::new_unchecked(CODE_CRYPTO_UNDEF)
|
||||
}));
|
||||
}
|
||||
|
||||
// Test if `crypto.getRandomValues` is undefined as well
|
||||
let crypto: BrowserCrypto = crypto.into();
|
||||
if crypto.get_random_values_fn().is_undefined() {
|
||||
let msg = "crypto.getRandomValues is undefined";
|
||||
return Err(UNAVAILABLE_ERROR) // TODO: report msg
|
||||
return Err(Error::from(unsafe {
|
||||
NonZeroU32::new_unchecked(CODE_GRV_UNDEF)
|
||||
}));
|
||||
}
|
||||
|
||||
// Ok! `self.crypto.getRandomValues` is a defined value, so let's
|
||||
// assume we can do browser crypto.
|
||||
Ok(RngSource::Browser(crypto))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(n: NonZeroU32) -> Option<&'static str> {
|
||||
match n.get() {
|
||||
CODE_CRYPTO_UNDEF => Some("getrandom: self.crypto is undefined"),
|
||||
CODE_GRV_UNDEF => Some("crypto.getRandomValues is undefined"),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -10,12 +10,13 @@
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::mem;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use stdweb::unstable::TryInto;
|
||||
use stdweb::web::error::Error as WebError;
|
||||
|
||||
use super::{Error, UNAVAILABLE_ERROR, UNKNOWN_ERROR};
|
||||
use super::utils::use_init;
|
||||
use {Error, ERROR_UNAVAILABLE, ERROR_UNKNOWN};
|
||||
use utils::use_init;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum RngSource {
|
||||
@@ -65,7 +66,8 @@ fn getrandom_init() -> Result<RngSource, Error> {
|
||||
else { unreachable!() }
|
||||
} else {
|
||||
let err: WebError = js!{ return @{ result }.error }.try_into().unwrap();
|
||||
Err(UNAVAILABLE_ERROR) // TODO: forward err
|
||||
error!("getrandom unavailable: {}", err);
|
||||
Err(ERROR_UNAVAILABLE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +102,12 @@ fn getrandom_fill(source: &mut RngSource, dest: &mut [u8]) -> Result<(), Error>
|
||||
|
||||
if js!{ return @{ result.as_ref() }.success } != true {
|
||||
let err: WebError = js!{ return @{ result }.error }.try_into().unwrap();
|
||||
return Err(UNKNOWN_ERROR) // TODO: forward err
|
||||
error!("getrandom failed: {}", err);
|
||||
return Err(ERROR_UNKNOWN)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
+9
-2
@@ -13,12 +13,19 @@ use self::winapi::shared::minwindef::ULONG;
|
||||
use self::winapi::um::ntsecapi::RtlGenRandom;
|
||||
use self::winapi::um::winnt::PVOID;
|
||||
use std::io;
|
||||
use super::Error;
|
||||
use std::num::NonZeroU32;
|
||||
use Error;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
let ret = unsafe {
|
||||
RtlGenRandom(dest.as_mut_ptr() as PVOID, dest.len() as ULONG)
|
||||
};
|
||||
if ret == 0 { return Err(io::Error::last_os_error().into()); }
|
||||
if ret == 0 {
|
||||
error!("RtlGenRandom call failed");
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
||||
Reference in New Issue
Block a user