new error

This commit is contained in:
newpavlov 2019-02-06 14:51:04 +03:00
parent f860bde8d8
commit 1e2a5aa75e
17 changed files with 106 additions and 51 deletions

View File

@ -21,3 +21,7 @@ fuchsia-cprng = "0.1"
[target.wasm32-unknown-unknown.dependencies]
wasm-bindgen = { version = "0.2.12", optional = true }
stdweb = { version = "0.4", optional = true }
[features]
# Forces syscall usage on Linux, Android and Solaris
force_syscall = []

View File

@ -16,6 +16,8 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
if errno == 0 {
Ok(())
} else {
Err(Error::Unknown)
Err(Error(unsafe {
NonZeroU32::new_unchecked(errno as u32)
}))
}
}

View File

@ -17,6 +17,9 @@ thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
RNG_FILE.with(|f| {
use_init(f, || File::open("/dev/random"), |f| f.read_exact(dest))
}).map_err(|_| Error::Unknown)
use_init(f,
|| File::open("/dev/random").map_err(From::from),
|f| f.read_exact(dest).map_err(From::from),
)
})
}

View File

@ -7,9 +7,9 @@
// except according to those terms.
//! A dummy implementation for unsupported targets which always returns
//! `Err(Error::Unavailable)`
use super::Error;
//! `Err(UNAVAILABLE_ERROR)`
use super::UNAVAILABLE_ERROR;
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
Err(Error::Unavailable)
Err(UNAVAILABLE_ERROR)
}

View File

@ -21,11 +21,11 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
// task length variation, partition large randomBytes requests when
// doing so as part of fulfilling a client request.
RNG_FILE.with(|f| {
use_init(f, || File::open("/dev/random"), |f| {
use_init(f, || File::open("/dev/random").map_err(From::from), |f| {
for chunk in dest.chunks_mut(65536) {
f.read_exact(chunk)?;
}
Ok(())
})
}).map_err(|_| Error::Unknown)
})
}

View File

@ -6,16 +6,64 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::num::NonZeroU32;
use core::convert::From;
use core::fmt;
#[cfg(not(target_env = "sgx"))]
use std::{io, error};
pub const UNKNOWN_ERROR: Error = Error(unsafe {
NonZeroU32::new_unchecked(0x756e6b6e) // "unkn"
});
pub const UNAVAILABLE_ERROR: Error = Error(unsafe {
NonZeroU32::new_unchecked(0x4e416e61) // "NAna"
});
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Error {
/// Call was interrupted.
///
/// Typically it can be retried.
Interrupted,
/// RNG source is unavailable on a given system.
Unavailable,
/// Unknown error.
Unknown,
#[doc(hidden)]
__Nonexhaustive,
pub struct Error(NonZeroU32);
impl Error {
pub fn code(&self) -> NonZeroU32 {
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()),
}
}
}
#[cfg(not(target_env = "sgx"))]
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
err.raw_os_error()
.map(|code| Error(unsafe {
// all supported targets use 0 as success code
NonZeroU32::new_unchecked(code as u32)
}))
// in practice this should never happen
.unwrap_or(UNKNOWN_ERROR)
}
}
#[cfg(not(target_env = "sgx"))]
impl Into<io::Error> for Error {
fn into(self) -> io::Error {
match self {
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),
}
}
}
#[cfg(not(target_env = "sgx"))]
impl error::Error for Error { }

View File

@ -11,6 +11,7 @@ extern crate libc;
use super::Error;
use core::ptr;
use std::io;
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
let mib = [libc::CTL_KERN, libc::KERN_ARND];
@ -24,7 +25,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
)
};
if ret == -1 || len != chunk.len() {
return Err(Error::Unknown);
return Err(io::Error::last_os_error().into());
}
}
Ok(())

View File

@ -7,16 +7,7 @@
// except according to those terms.
#![no_std]
#[cfg(any(
target_os = "android",
target_os = "netbsd",
target_os = "solaris",
target_os = "redox",
target_os = "dragonfly",
target_os = "haiku",
target_os = "emscripten",
target_os = "linux",
))]
#[cfg(not(target_env = "sgx"))]
#[macro_use] extern crate std;
#[cfg(any(
@ -31,7 +22,7 @@
))]
mod utils;
mod error;
pub use error::Error;
pub use error::{Error, UNKNOWN_ERROR, UNAVAILABLE_ERROR};
macro_rules! mod_use {
($cond:meta, $module:ident) => {

View File

@ -58,8 +58,8 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
match f {
RngSource::GetRandom => syscall_getrandom(dest),
RngSource::Device(f) => f.read_exact(dest),
}
}).map_err(|_| Error::Unknown)
}.map_err(From::from)
})
})
}

View File

@ -8,6 +8,7 @@
//! Implementation for MacOS / iOS
use super::Error;
use std::io;
// TODO: check correctness
#[allow(non_upper_case_globals)]
@ -29,7 +30,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
)
};
if ret == -1 {
Err(Error::Unknown)
Err(io::Error::last_os_error().into())
} else {
Ok(())
}

View File

@ -28,7 +28,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
File::open("/dev/random")?.read_exact(&mut [0u8; 1])?;
RNG_INIT.store(true, Ordering::Relaxed)
}
File::open("/dev/urandom")
}, |f| f.read_exact(dest))
}).map_err(|_| Error::Unknown)
File::open("/dev/urandom").map_err(From::from)
}, |f| f.read_exact(dest).map_err(From::from))
})
}

View File

@ -10,6 +10,7 @@
extern crate libc;
use super::Error;
use std::io;
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
for chunk in dest.chunks_mut(256) {
@ -20,7 +21,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
)
};
if ret == -1 {
return Err(Error::Unknown);
return Err(io::Error::last_os_error().into());
}
}
Ok(())

View File

@ -17,6 +17,9 @@ thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
RNG_FILE.with(|f| {
use_init(f, || File::open("rand:"), |f| f.read_exact(dest))
}).map_err(|_| Error::Unknown)
use_init(f,
|| File::open("rand:").map_err(From::from),
|f| f.read_exact(dest).map_err(From::from),
)
}).map_err(From::from)
}

View File

@ -7,7 +7,7 @@
// except according to those terms.
//! Implementation for SGX using RDRAND instruction
use super::Error;
use super::{Error, UNKNOWN_ERROR};
use core::{mem, ptr};
use core::arch::x86_64::_rdrand64_step;
@ -26,7 +26,7 @@ fn get_rand_u64() -> Result<u64, Error> {
}
};
}
Err(Error::Unknown)
Err(UNKNOWN_ERROR)
}
pub fn getrandom(mut dest: &mut [u8]) -> Result<(), Error> {

View File

@ -36,7 +36,7 @@ thread_local!(
static RNG_SOURCE: RefCell<Option<RngSource>> = RefCell::new(None);
);
fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> {
fn syscall_getrandom(dest: &mut [u8]) -> Result<(), Error> {
// repalce with libc?
const SYS_GETRANDOM: libc::c_long = 143;
@ -48,7 +48,7 @@ fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> {
syscall(SYS_GETRANDOM, dest.as_mut_ptr(), dest.len(), 0)
};
if ret == -1 || ret != dest.len() as i64 {
return Err(io::Error::last_os_error());
return Err(io::Error::last_os_error().from());
}
Ok(())
}
@ -71,7 +71,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
syscall_getrandom(chunk)
},
RngSource::Device(f) => for chunk in dest.chunks_mut(1040) {
f.read_exact(dest)
f.read_exact(dest).map_err(From::from)
},
}
})

View File

@ -5,16 +5,16 @@
// <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 std::cell::RefCell;
use std::ops::DerefMut;
use std::io;
use super::Error;
use core::cell::RefCell;
use core::ops::DerefMut;
/// If `f` contains `Some(T)` call `use_f` using contents of `f` as an argument,
/// otherwise initialize `f` value using `init_f`, store resulting value in `f`
/// and call `use_f`.
pub(crate) fn use_init<T, F, U>(f: &RefCell<Option<T>>, init_f: F, mut use_f: U)
-> io::Result<()>
where F: FnOnce() -> io::Result<T>, U: FnMut(&mut T) -> io::Result<()>
-> Result<(), Error>
where F: FnOnce() -> Result<T, Error>, U: FnMut(&mut T) -> Result<(), Error>
{
let mut f = f.borrow_mut();
let f: &mut Option<T> = f.deref_mut();

View File

@ -12,12 +12,13 @@ extern crate winapi;
use self::winapi::shared::minwindef::ULONG;
use self::winapi::um::ntsecapi::RtlGenRandom;
use self::winapi::um::winnt::PVOID;
use std::io;
use super::Error;
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
let ret = unsafe {
RtlGenRandom(dest.as_mut_ptr() as PVOID, dest.len() as ULONG)
};
if ret == 0 { return Err(Error::Unknown); }
if ret == 0 { return Err(io::Error::last_os_error().into()); }
Ok(())
}