Revise error types and codes
This commit is contained in:
parent
679c52c23b
commit
b771a82ea6
@ -22,3 +22,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
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::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 }
|
||||
|
12
src/dummy.rs
12
src/dummy.rs
@ -7,9 +7,13 @@
|
||||
// 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> {
|
||||
Err(UNAVAILABLE)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -7,11 +7,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for Emscripten
|
||||
use super::Error;
|
||||
use error::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 }
|
||||
|
66
src/error.rs
66
src/error.rs
@ -12,20 +12,25 @@ 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"
|
||||
pub const 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"
|
||||
pub const 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 +43,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 {
|
||||
UNKNOWN => Some("getrandom: unknown 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({})", self.0.get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {}", self.0.get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,22 +88,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(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);
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,10 @@
|
||||
//! Implementation for FreeBSD
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use error::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];
|
||||
@ -30,3 +31,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -9,9 +9,13 @@
|
||||
//! Implementation for Fuchsia Zircon
|
||||
extern crate fuchsia_cprng;
|
||||
|
||||
use super::Error;
|
||||
use std::num::NonZeroU32;
|
||||
use error::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 }
|
||||
|
@ -123,8 +123,7 @@ extern crate wasm_bindgen;
|
||||
target_arch = "wasm32",
|
||||
))]
|
||||
mod utils;
|
||||
mod error;
|
||||
pub use error::{Error, UNKNOWN_ERROR, UNAVAILABLE_ERROR};
|
||||
pub mod error;
|
||||
|
||||
|
||||
// System-specific implementations.
|
||||
@ -136,7 +135,7 @@ macro_rules! mod_use {
|
||||
#[$cond]
|
||||
mod $module;
|
||||
#[$cond]
|
||||
use $module::getrandom_inner;
|
||||
use $module::{getrandom_inner, error_msg_inner};
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +220,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::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);
|
||||
@ -80,3 +81,6 @@ fn is_getrandom_available() -> bool {
|
||||
|
||||
AVAILABLE.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -9,8 +9,9 @@
|
||||
//! Implementation for MacOS / iOS
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use error::Error;
|
||||
use std::io;
|
||||
use std::num::NonZeroU32;
|
||||
use self::libc::{c_int, size_t};
|
||||
|
||||
enum SecRandom {}
|
||||
@ -40,3 +41,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -8,11 +8,12 @@
|
||||
|
||||
//! Implementation for NetBSD
|
||||
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use error::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::Error;
|
||||
use std::io;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
@ -26,3 +27,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -7,11 +7,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for Redox
|
||||
use super::Error;
|
||||
use super::utils::use_init;
|
||||
use error::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 }
|
||||
|
@ -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(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 }
|
||||
|
@ -19,11 +19,12 @@
|
||||
//! libc::dlsym.
|
||||
extern crate libc;
|
||||
|
||||
use super::Error;
|
||||
use error::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")]
|
||||
@ -97,3 +98,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 }
|
||||
|
@ -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::Error;
|
||||
use core::cell::RefCell;
|
||||
use core::ops::DerefMut;
|
||||
|
||||
|
@ -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::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,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, UNKNOWN};
|
||||
use utils::use_init;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum RngSource {
|
||||
@ -65,7 +66,7 @@ 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
|
||||
Err(UNAVAILABLE) // TODO: forward err
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,8 +101,11 @@ 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
|
||||
return Err(UNKNOWN) // TODO: forward err
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
@ -13,7 +13,8 @@ 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::Error;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
let ret = unsafe {
|
||||
@ -22,3 +23,6 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
if ret == 0 { return Err(io::Error::last_os_error().into()); }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
|
||||
|
Loading…
x
Reference in New Issue
Block a user