From 8350ac6afb2d678b74581000a6aafe1994b72231 Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Wed, 16 Jan 2019 17:26:30 -0800 Subject: Update nitrokey crate to 0.3.3 This change updates the nitrokey crate to version 0.3.3. Along with that change we update rand to 0.6.4 because rand 0.6.1 does not yet contain a publicly accessible rand_os. Note that we no longer require all crates in rand's workspace, but only rand_os and rand_core, which is a significant reduction in the number of lines of code compiled. Import subrepo nitrokey/:nitrokey at 7cf747d56ddc0b7eeedc3caf36dcc909907a171c Import subrepo rand/:rand at 4336232dda03323634b10ec72ddf27914aebc3a2 --- rand/rand_os/src/random_device.rs | 70 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 rand/rand_os/src/random_device.rs (limited to 'rand/rand_os/src/random_device.rs') diff --git a/rand/rand_os/src/random_device.rs b/rand/rand_os/src/random_device.rs new file mode 100644 index 0000000..5da9194 --- /dev/null +++ b/rand/rand_os/src/random_device.rs @@ -0,0 +1,70 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Helper functions to read from a random device such as `/dev/urandom`. +//! +//! All instances use a single internal file handle, to prevent possible +//! exhaustion of file descriptors. +use rand_core::{Error, ErrorKind}; +use std::fs::File; +use std::io; +use std::io::Read; +use std::sync::{Once, Mutex, ONCE_INIT}; + +// TODO: remove outer Option when `Mutex::new(None)` is a constant expression +static mut READ_RNG_FILE: Option>> = None; +static READ_RNG_ONCE: Once = ONCE_INIT; + +#[allow(unused)] +pub fn open(path: &'static str, open_fn: F) -> Result<(), Error> + where F: Fn(&'static str) -> Result +{ + READ_RNG_ONCE.call_once(|| { + unsafe { READ_RNG_FILE = Some(Mutex::new(None)) } + }); + + // We try opening the file outside the `call_once` fn because we cannot + // clone the error, thus we must retry on failure. + + let mutex = unsafe { READ_RNG_FILE.as_ref().unwrap() }; + let mut guard = mutex.lock().unwrap(); + if (*guard).is_none() { + info!("OsRng: opening random device {}", path); + let file = open_fn(path).map_err(map_err)?; + *guard = Some(file); + }; + Ok(()) +} + +pub fn read(dest: &mut [u8]) -> Result<(), Error> { + // We expect this function only to be used after `random_device::open` + // was succesful. Therefore we can assume that our memory was set with a + // valid object. + let mutex = unsafe { READ_RNG_FILE.as_ref().unwrap() }; + let mut guard = mutex.lock().unwrap(); + let file = (*guard).as_mut().unwrap(); + + // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. + file.read_exact(dest).map_err(|err| { + Error::with_cause(ErrorKind::Unavailable, + "error reading random device", err) + }) + +} + +pub fn map_err(err: io::Error) -> Error { + match err.kind() { + io::ErrorKind::Interrupted => + Error::new(ErrorKind::Transient, "interrupted"), + io::ErrorKind::WouldBlock => + Error::with_cause(ErrorKind::NotReady, + "OS RNG not yet seeded", err), + _ => Error::with_cause(ErrorKind::Unavailable, + "error while opening random device", err) + } +} -- cgit v1.2.1