getrandom-0.1.6/CHANGELOG.md010064400017500001750000000045171350603621100135340ustar0000000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.1.6] - 2019-06-30 ### Changed - Minor change of RDRAND AMD bug handling. [#48] [#43]: https://github.com/rust-random/getrandom/pull/43 ## [0.1.5] - 2019-06-29 ### Fixed - Use shared `File` instead of shared file descriptor. [#44] - Workaround for RDRAND hardware bug present on some AMD CPUs. [#43] ### Changed - Try `getentropy` and then fallback to `/dev/random` on macOS. [#38] [#38]: https://github.com/rust-random/getrandom/issues/38 [#43]: https://github.com/rust-random/getrandom/pull/43 [#44]: https://github.com/rust-random/getrandom/issues/44 ## [0.1.4] - 2019-06-28 ### Added - Add support for `x86_64-unknown-uefi` target by using RDRAND with CPUID feature detection. [#30] ### Fixed - Fix long buffer issues on Windows and Linux. [#31] [#32] - Check `EPERM` in addition to `ENOSYS` on Linux. [#37] ### Changed - Improve efficiency by sharing file descriptor across threads. [#13] - Remove `cloudabi`, `winapi`, and `fuchsia-cprng` dependencies. [#40] - Improve RDRAND implementation. [#24] - Don't block during syscall detection on Linux. [#26] - Increase consistency with libc implementation on FreeBSD. [#36] - Apply `rustfmt`. [#39] [#30]: https://github.com/rust-random/getrandom/pull/30 [#13]: https://github.com/rust-random/getrandom/issues/13 [#40]: https://github.com/rust-random/getrandom/pull/40 [#26]: https://github.com/rust-random/getrandom/pull/26 [#24]: https://github.com/rust-random/getrandom/pull/24 [#39]: https://github.com/rust-random/getrandom/pull/39 [#36]: https://github.com/rust-random/getrandom/pull/36 [#31]: https://github.com/rust-random/getrandom/issues/31 [#32]: https://github.com/rust-random/getrandom/issues/32 [#37]: https://github.com/rust-random/getrandom/issues/37 ## [0.1.3] - 2019-05-15 - Update for `wasm32-unknown-wasi` being renamed to `wasm32-wasi`, and for WASI being categorized as an OS. ## [0.1.2] - 2019-04-06 - Add support for `wasm32-unknown-wasi` target. ## [0.1.1] - 2019-04-05 - Enable std functionality for CloudABI by default. ## [0.1.0] - 2019-03-23 Publish initial implementation. ## [0.0.0] - 2019-01-19 Publish an empty template library. getrandom-0.1.6/Cargo.toml.orig010064400017500001750000000022151350603623100146050ustar0000000000000000[package] name = "getrandom" version = "0.1.6" edition = "2018" authors = ["The Rand Project Developers"] license = "MIT OR Apache-2.0" description = "A small cross-platform library for retrieving random data from system source" documentation = "https://docs.rs/getrandom" repository = "https://github.com/rust-random/getrandom" categories = ["os", "no-std"] exclude = ["utils/*", ".*", "appveyor.yml"] [badges] travis-ci = { repository = "rust-random/getrandom" } appveyor = { repository = "rust-random/getrandom" } [workspace] members = ["tests/wasm_bindgen"] [dependencies] log = { version = "0.4", optional = true } [target.'cfg(any(unix, target_os = "wasi"))'.dependencies] libc = "0.2.54" # For holding file descriptors [target.'cfg(any(unix, target_os = "redox"))'.dependencies] lazy_static = "1.3.0" # For caching result of CPUID check for RDRAND [target.'cfg(target_os = "uefi")'.dependencies] lazy_static = { version = "1.3.0", features = ["spin_no_std"] } [target.wasm32-unknown-unknown.dependencies] wasm-bindgen = { version = "0.2.29", optional = true } stdweb = { version = "0.4.9", optional = true } lazy_static = "1.3.0" [features] std = [] getrandom-0.1.6/Cargo.toml0000644000000031630000000000000110600ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "getrandom" version = "0.1.6" authors = ["The Rand Project Developers"] exclude = ["utils/*", ".*", "appveyor.yml"] description = "A small cross-platform library for retrieving random data from system source" documentation = "https://docs.rs/getrandom" categories = ["os", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-random/getrandom" [dependencies.log] version = "0.4" optional = true [features] std = [] [target."cfg(any(unix, target_os = \"redox\"))".dependencies.lazy_static] version = "1.3.0" [target."cfg(any(unix, target_os = \"wasi\"))".dependencies.libc] version = "0.2.54" [target."cfg(target_os = \"uefi\")".dependencies.lazy_static] version = "1.3.0" features = ["spin_no_std"] [target.wasm32-unknown-unknown.dependencies.lazy_static] version = "1.3.0" [target.wasm32-unknown-unknown.dependencies.stdweb] version = "0.4.9" optional = true [target.wasm32-unknown-unknown.dependencies.wasm-bindgen] version = "0.2.29" optional = true [badges.appveyor] repository = "rust-random/getrandom" [badges.travis-ci] repository = "rust-random/getrandom" getrandom-0.1.6/Cargo.toml.orig0000644000000031640000000000000120200ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "getrandom" version = "0.1.6" authors = ["The Rand Project Developers"] exclude = ["utils/*", ".*", "appveyor.yml"] description = "A small cross-platform library for retrieving random data from system source" documentation = "https://docs.rs/getrandom" categories = ["os", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-random/getrandom" [dependencies.log] version = "0.4" optional = true [features] std = [] [target."cfg(any(unix, target_os = \"redox\"))".dependencies.lazy_static] version = "1.3.0" [target."cfg(any(unix, target_os = \"wasi\"))".dependencies.libc] version = "0.2.54" [target."cfg(target_os = \"uefi\")".dependencies.lazy_static] version = "1.3.0" features = ["spin_no_std"] [target.wasm32-unknown-unknown.dependencies.lazy_static] version = "1.3.0" [target.wasm32-unknown-unknown.dependencies.stdweb] version = "0.4.9" optional = true [target.wasm32-unknown-unknown.dependencies.wasm-bindgen] version = "0.2.29" optional = true [badges.appveyor] repository = "rust-random/getrandom" [badges.travis-ci] repository = "rust-random/getrandom" getrandom-0.1.6/LICENSE-APACHE010064400017500001750000000251411350536722200136530ustar0000000000000000 Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. getrandom-0.1.6/LICENSE-MIT010064400017500001750000000021351350536722200133610ustar0000000000000000Copyright 2018 Developers of the Rand project Copyright (c) 2014 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. getrandom-0.1.6/README.md010064400017500001750000000040571350536722200132110ustar0000000000000000# getrandom [![Build Status](https://travis-ci.org/rust-random/getrandom.svg?branch=master)](https://travis-ci.org/rust-random/getrandom) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-random/getrandom?svg=true)](https://ci.appveyor.com/project/rust-random/getrandom) [![Crate](https://img.shields.io/crates/v/getrandom.svg)](https://crates.io/crates/getrandom) [![Documentation](https://docs.rs/getrandom/badge.svg)](https://docs.rs/getrandom) [![Dependency status](https://deps.rs/repo/github/rust-random/getrandom/status.svg)](https://deps.rs/repo/github/rust-random/getrandom) A Rust library for retrieving random data from (operating) system source. It is assumed that system always provides high-quality cryptographically secure random data, ideally backed by hardware entropy sources. This crate derives its name from Linux's `getrandom` function, but is cross platform, roughly supporting the same set of platforms as Rust's `std` lib. This is a low-level API. Most users should prefer using high-level random-number library like [`rand`]. [`rand`]: https://crates.io/crates/rand ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] getrandom = "0.1" ``` Then invoke the `getrandom` function: ```rust fn get_random_buf() -> Result<[u8; 32], getrandom::Error> { let mut buf = [0u8; 32]; getrandom::getrandom(&mut buf)?; buf } ``` ## Features This library is `no_std` compatible, but uses `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`), WASI and Emscripten targets are supported directly; otherwise one of the following features must be enabled: - [`wasm-bindgen`](https://crates.io/crates/wasm_bindgen) - [`stdweb`](https://crates.io/crates/stdweb) ## Minimum Supported Rust Version This crate requires Rust 1.32.0 or later. # License The `getrandom` library is distributed under either of * [Apache License, Version 2.0](LICENSE-APACHE) * [MIT license](LICENSE-MIT) at your option. getrandom-0.1.6/benches/mod.rs010064400017500001750000000007671350536722200144720ustar0000000000000000#![feature(test)] extern crate getrandom; extern crate test; #[bench] fn bench_64(b: &mut test::Bencher) { let mut buf = [0u8; 64]; b.iter(|| { getrandom::getrandom(&mut buf[..]).unwrap(); test::black_box(&buf); }); b.bytes = buf.len() as u64; } #[bench] fn bench_65536(b: &mut test::Bencher) { let mut buf = [0u8; 65536]; b.iter(|| { getrandom::getrandom(&mut buf[..]).unwrap(); test::black_box(&buf); }); b.bytes = buf.len() as u64; } getrandom-0.1.6/src/cloudabi.rs010064400017500001750000000017321350536722200146460ustar0000000000000000// 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. //! Implementation for CloudABI use crate::Error; use core::num::NonZeroU32; extern "C" { fn cloudabi_sys_random_get(buf: *mut u8, buf_len: usize) -> u16; } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let errno = unsafe { cloudabi_sys_random_get(dest.as_mut_ptr(), dest.len()) }; if let Some(code) = NonZeroU32::new(errno as u32) { error!("cloudabi_sys_random_get failed with code {}", code); Err(Error::from(code)) } else { Ok(()) // Zero means success for CloudABI } } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/dummy.rs010064400017500001750000000013341350536722200142150ustar0000000000000000// 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. //! A dummy implementation for unsupported targets which always returns //! `Err(Error::UNAVAILABLE)` use crate::Error; use core::num::NonZeroU32; 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 } getrandom-0.1.6/src/error.rs010064400017500001750000000051151350553326400142150ustar0000000000000000// 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. use core::convert::From; use core::fmt; use core::num::NonZeroU32; // A randomly-chosen 24-bit prefix for our codes pub(crate) const CODE_PREFIX: u32 = 0x57f4c500; const CODE_UNKNOWN: u32 = CODE_PREFIX | 0x00; const CODE_UNAVAILABLE: u32 = CODE_PREFIX | 0x01; /// The error type. /// /// This type is small and no-std compatible. #[derive(Copy, Clone, Eq, PartialEq)] pub struct Error(pub(crate) NonZeroU32); impl Error { /// An unknown error. pub const UNKNOWN: Error = Error(unsafe { NonZeroU32::new_unchecked(CODE_UNKNOWN) }); /// No generator is available. pub const UNAVAILABLE: Error = Error(unsafe { NonZeroU32::new_unchecked(CODE_UNAVAILABLE) }); /// Extract the error code. /// /// This may equal one of the codes defined in this library or may be a /// system error code. /// /// One may attempt to format this error via the `Display` implementation. pub fn code(&self) -> NonZeroU32 { self.0 } pub(crate) 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.msg() { Some(msg) => write!(f, "{}", msg), None => write!(f, "getrandom: unknown code 0x{:08X}", self.0), } } } impl From for Error { fn from(code: NonZeroU32) -> Self { Error(code) } } impl From<&Error> for Error { fn from(error: &Error) -> Self { *error } } #[cfg(test)] mod tests { use super::Error; use core::mem::size_of; #[test] fn test_size() { assert_eq!(size_of::(), 4); assert_eq!(size_of::>(), 4); } } getrandom-0.1.6/src/error_impls.rs010064400017500001750000000020311350536722200154120ustar0000000000000000// 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. extern crate std; use crate::error::Error; use core::convert::From; use core::num::NonZeroU32; use std::{error, io}; impl From for Error { fn from(err: io::Error) -> Self { err.raw_os_error() .and_then(|code| NonZeroU32::new(code as u32)) .map(|code| Error(code)) // in practice this should never happen .unwrap_or(Error::UNKNOWN) } } impl From for io::Error { fn from(err: Error) -> Self { match err.msg() { Some(msg) => io::Error::new(io::ErrorKind::Other, msg), None => io::Error::from_raw_os_error(err.0.get() as i32), } } } impl error::Error for Error {} getrandom-0.1.6/src/freebsd.rs010064400017500001750000000024151350536722200144750ustar0000000000000000// 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. //! Implementation for FreeBSD extern crate std; use crate::Error; use core::num::NonZeroU32; use core::ptr; use std::io; fn kern_arnd(buf: &mut [u8]) -> Result { static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND]; let mut len = buf.len(); let ret = unsafe { libc::sysctl( MIB.as_ptr(), MIB.len() as libc::c_uint, buf.as_mut_ptr() as *mut _, &mut len, ptr::null(), 0, ) }; if ret == -1 { error!("freebsd: kern.arandom syscall failed"); return Err(io::Error::last_os_error().into()); } Ok(len) } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let mut start = 0; while start < dest.len() { start += kern_arnd(&mut dest[start..])?; } Ok(()) } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/fuchsia.rs010064400017500001750000000013751350536722200145110ustar0000000000000000// 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. //! Implementation for Fuchsia Zircon use crate::Error; use core::num::NonZeroU32; #[link(name = "zircon")] extern "C" { fn zx_cprng_draw(buffer: *mut u8, length: usize); } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { unsafe { zx_cprng_draw(dest.as_mut_ptr(), dest.len()) } Ok(()) } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/ios.rs010064400017500001750000000023061350553326400136550ustar0000000000000000// 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. //! Implementation for iOS extern crate std; use crate::Error; use core::num::NonZeroU32; use std::io; // TODO: Make extern once extern_types feature is stabilized. See: // https://github.com/rust-lang/rust/issues/43467 #[repr(C)] struct SecRandom([u8; 0]); #[link(name = "Security", kind = "framework")] extern "C" { static kSecRandomDefault: *const SecRandom; fn SecRandomCopyBytes(rnd: *const SecRandom, count: usize, bytes: *mut u8) -> i32; } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, dest.len(), dest.as_mut_ptr()) }; 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 } getrandom-0.1.6/src/lib.rs010064400017500001750000000244661350553326400136440ustar0000000000000000// Copyright 2019 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. //! Interface to the random number generator of the operating system. //! //! # Platform sources //! //! | OS | interface //! |------------------|--------------------------------------------------------- //! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after reading from `/dev/random` once //! | Windows | [`RtlGenRandom`][3] //! | macOS | [`getentropy()`][19] if available, otherise [`/dev/random`][20] (identical to `/dev/urandom`) //! | iOS | [`SecRandomCopyBytes`][4] //! | FreeBSD | [`kern.arandom`][5] //! | OpenBSD, Bitrig | [`getentropy`][6] //! | NetBSD | [`/dev/urandom`][7] after reading from `/dev/random` once //! | Dragonfly BSD | [`/dev/random`][8] //! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10] //! | Fuchsia OS | [`cprng_draw`][11] //! | Redox | [`rand:`][12] //! | CloudABI | [`cloudabi_sys_random_get`][13] //! | Haiku | `/dev/random` (identical to `/dev/urandom`) //! | SGX, UEFI | [RDRAND][18] //! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14]) //! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16]) //! | WASI | [`__wasi_random_get`][17] //! //! Getrandom doesn't have a blanket implementation for all Unix-like operating //! systems that reads from `/dev/urandom`. This ensures all supported operating //! systems are using the recommended interface and respect maximum buffer //! sizes. //! //! ## Support for WebAssembly and ams.js //! //! The three Emscripten targets `asmjs-unknown-emscripten`, //! `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use //! Emscripten's emulation of `/dev/random` on web browsers and Node.js. //! //! The bare WASM target `wasm32-unknown-unknown` tries to call the javascript //! methods directly, using either `stdweb` or `wasm-bindgen` depending on what //! features are activated for this crate. Note that if both features are //! enabled `wasm-bindgen` will be used. If neither feature is enabled, //! `getrandom` will always fail. //! //! The WASI target `wasm32-wasi` uses the `__wasi_random_get` function defined //! by the WASI standard. //! //! //! ## Early boot //! //! It is possible that early in the boot process the OS hasn't had enough time //! yet to collect entropy to securely seed its RNG, especially on virtual //! machines. //! //! Some operating systems always block the thread until the RNG is securely //! seeded. This can take anywhere from a few seconds to more than a minute. //! Others make a best effort to use a seed from before the shutdown and don't //! document much. //! //! A few, Linux, NetBSD and Solaris, offer a choice between blocking and //! getting an error; in these cases we always choose to block. //! //! On Linux (when the `genrandom` system call is not available) and on NetBSD //! reading from `/dev/urandom` never blocks, even when the OS hasn't collected //! enough entropy yet. To avoid returning low-entropy bytes, we first read from //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded. //! //! # Error handling //! //! We always choose failure over returning insecure "random" bytes. In general, //! on supported platforms, failure is highly unlikely, though not impossible. //! If an error does occur, then it is likely that it will occur on every call to //! `getrandom`, hence after the first successful call one can be reasonably //! confident that no errors will occur. //! //! On unsupported platforms, `getrandom` always fails with [`Error::UNAVAILABLE`]. //! //! ## Error codes //! The crate uses the following custom error codes: //! - `0x57f4c500` (dec: 1475659008) - an unknown error. Constant: //! [`Error::UNKNOWN`] //! - `0x57f4c501` (dec: 1475659009) - no generator is available. Constant: //! [`Error::UNAVAILABLE`] //! - `0x57f4c580` (dec: 1475659136) - `self.crypto` is undefined, //! `wasm-bindgen` specific error. //! - `0x57f4c581` (dec: 1475659137) - `crypto.getRandomValues` is undefined, //! `wasm-bindgen` specific error. //! //! These codes are provided for reference only and should not be matched upon //! (but you can match on `Error` constants). The codes may change in future and //! such change will not be considered a breaking one. //! //! Other error codes will originate from an underlying system. In case if such //! error is encountered, please consult with your system documentation. //! //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html //! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 //! [6]: https://man.openbsd.org/getentropy.2 //! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4 //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html //! [11]: https://fuchsia.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/cprng_draw.md //! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs //! [13]: https://github.com/nuxinl/cloudabi#random_get //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback //! [16]: #support-for-webassembly-and-amsjs //! [17]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#__wasi_random_get //! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide //! [19]: https://www.unix.com/man-page/mojave/2/getentropy/ //! [20]: https://www.unix.com/man-page/mojave/4/random/ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://rust-random.github.io/rand/" )] #![no_std] #![cfg_attr(feature = "stdweb", recursion_limit = "128")] #[cfg(feature = "log")] #[macro_use] extern crate log; #[cfg(not(feature = "log"))] #[allow(unused)] macro_rules! error { ($($x:tt)*) => {}; } // temp fix for stdweb #[cfg(target_arch = "wasm32")] extern crate std; mod error; pub use crate::error::Error; // System-specific implementations. // // These should all provide getrandom_inner with the same signature as getrandom. macro_rules! mod_use { ($cond:meta, $module:ident) => { #[$cond] mod $module; #[$cond] use crate::$module::{error_msg_inner, getrandom_inner}; }; } // These targets use std anyway, so we use the std declarations. #[cfg(any( feature = "std", windows, unix, target_os = "redox", target_arch = "wasm32", ))] mod error_impls; // These targets read from a file as a fallback method. #[cfg(any( target_os = "android", target_os = "linux", target_os = "macos", target_os = "solaris", target_os = "illumos", ))] mod use_file; mod_use!(cfg(target_os = "android"), linux_android); mod_use!(cfg(target_os = "bitrig"), openbsd_bitrig); mod_use!(cfg(target_os = "cloudabi"), cloudabi); mod_use!(cfg(target_os = "dragonfly"), use_file); mod_use!(cfg(target_os = "emscripten"), use_file); mod_use!(cfg(target_os = "freebsd"), freebsd); mod_use!(cfg(target_os = "fuchsia"), fuchsia); mod_use!(cfg(target_os = "haiku"), use_file); mod_use!(cfg(target_os = "illumos"), solaris_illumos); mod_use!(cfg(target_os = "ios"), ios); mod_use!(cfg(target_os = "linux"), linux_android); mod_use!(cfg(target_os = "macos"), macos); mod_use!(cfg(target_os = "netbsd"), use_file); mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig); mod_use!(cfg(target_os = "redox"), use_file); mod_use!(cfg(target_os = "solaris"), solaris_illumos); mod_use!(cfg(windows), windows); mod_use!(cfg(target_env = "sgx"), rdrand); mod_use!(cfg(all(target_arch = "x86_64", target_os = "uefi")), rdrand); mod_use!(cfg(target_os = "wasi"), wasi); mod_use!( cfg(all( target_arch = "wasm32", not(target_os = "emscripten"), not(target_os = "wasi"), feature = "wasm-bindgen" )), wasm32_bindgen ); mod_use!( cfg(all( target_arch = "wasm32", not(target_os = "emscripten"), not(target_os = "wasi"), not(feature = "wasm-bindgen"), feature = "stdweb", )), wasm32_stdweb ); mod_use!( cfg(not(any( target_os = "android", target_os = "bitrig", target_os = "cloudabi", target_os = "dragonfly", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", target_os = "haiku", target_os = "illumos", target_os = "ios", target_os = "linux", target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "redox", target_os = "solaris", all(target_arch = "x86_64", target_os = "uefi"), target_os = "wasi", target_env = "sgx", windows, all( target_arch = "wasm32", any(feature = "wasm-bindgen", feature = "stdweb"), ), ))), dummy ); /// Fill `dest` with random bytes from the system's preferred random number /// source. /// /// This function returns an error on any failure, including partial reads. We /// make no guarantees regarding the contents of `dest` on error. /// /// Blocking is possible, at least during early boot; see module documentation. /// /// 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::Error> { getrandom_inner(dest) } getrandom-0.1.6/src/linux_android.rs010064400017500001750000000036141350536722200157240ustar0000000000000000// 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. //! Implementation for Linux / Android extern crate std; use crate::{use_file, Error}; use core::num::NonZeroU32; use lazy_static::lazy_static; use std::io; fn syscall_getrandom(dest: &mut [u8], block: bool) -> Result { let flags = if block { 0 } else { libc::GRND_NONBLOCK }; let ret = unsafe { libc::syscall(libc::SYS_getrandom, dest.as_mut_ptr(), dest.len(), flags) }; if ret < 0 { let err = io::Error::last_os_error(); if err.raw_os_error() == Some(libc::EINTR) { return Ok(0); // Call was interrupted, try again } error!("Linux getrandom syscall failed with return value {}", ret); return Err(err); } Ok(ret as usize) } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { lazy_static! { static ref HAS_GETRANDOM: bool = is_getrandom_available(); } match *HAS_GETRANDOM { true => { let mut start = 0; while start < dest.len() { start += syscall_getrandom(&mut dest[start..], true)?; } Ok(()) } false => use_file::getrandom_inner(dest), } } fn is_getrandom_available() -> bool { match syscall_getrandom(&mut [], false) { Err(err) => match err.raw_os_error() { Some(libc::ENOSYS) => false, // No kernel support Some(libc::EPERM) => false, // Blocked by seccomp _ => true, }, Ok(_) => true, } } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/macos.rs010064400017500001750000000031501350553326400141630ustar0000000000000000// Copyright 2019 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. //! Implementation for macOS extern crate std; use crate::{use_file, Error}; use core::mem; use core::num::NonZeroU32; use lazy_static::lazy_static; use std::io; type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int; fn fetch_getentropy() -> Option { let name = "getentropy\0"; let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) }; unsafe { mem::transmute(addr) } } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { lazy_static! { static ref GETENTROPY_FUNC: Option = fetch_getentropy(); } if let Some(fptr) = *GETENTROPY_FUNC { for chunk in dest.chunks_mut(256) { let ret = unsafe { fptr(chunk.as_mut_ptr(), chunk.len()) }; if ret != 0 { error!("getentropy syscall failed with ret={}", ret); return Err(io::Error::last_os_error().into()); } } Ok(()) } else { // We fallback to reading from /dev/random instead of SecRandomCopyBytes // to avoid high startup costs and linking the Security framework. use_file::getrandom_inner(dest) } } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/openbsd_bitrig.rs010064400017500001750000000016461350536722200160620ustar0000000000000000// 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. //! Implementation for OpenBSD / Bitrig extern crate std; use crate::Error; use std::io; use std::num::NonZeroU32; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(256) { let ret = unsafe { libc::getentropy(chunk.as_mut_ptr() as *mut libc::c_void, chunk.len()) }; 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 } getrandom-0.1.6/src/rdrand.rs010064400017500001750000000066401350603602400143330ustar0000000000000000// 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. //! Implementation for SGX using RDRAND instruction use crate::Error; use core::arch::x86_64::_rdrand64_step; use core::mem; use core::num::NonZeroU32; // Recommendation from "Intel® Digital Random Number Generator (DRNG) Software // Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures // Software Developer’s Manual" - Volume 1 - Section 7.3.17.1. const RETRY_LIMIT: usize = 10; const WORD_SIZE: usize = mem::size_of::(); #[target_feature(enable = "rdrand")] unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { for _ in 0..RETRY_LIMIT { let mut el = mem::uninitialized(); if _rdrand64_step(&mut el) == 1 { // AMD CPUs from families 14h to 16h (pre Ryzen) sometimes fail to // set CF on bogus random data, so we check these values explictly. // See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505 // We perform this check regardless of target to guard against // any implementation that incorrectly fails to set CF. if el != 0 && el != !0 { return Ok(el.to_ne_bytes()); } error!("RDRAND returned {:X}, CPU RNG may be broken", el); // Keep looping in case this was a false positive. } } error!("RDRAND failed, CPU issue likely"); Err(Error::UNKNOWN) } // "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653. #[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))] compile_error!( "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd." ); #[cfg(target_feature = "rdrand")] fn is_rdrand_supported() -> bool { true } // TODO use is_x86_feature_detected!("rdrand") when that works in core. See: // https://github.com/rust-lang-nursery/stdsimd/issues/464 #[cfg(not(target_feature = "rdrand"))] fn is_rdrand_supported() -> bool { use core::arch::x86_64::__cpuid; use lazy_static::lazy_static; // SAFETY: All x86_64 CPUs support CPUID leaf 1 const FLAG: u32 = 1 << 30; lazy_static! { static ref HAS_RDRAND: bool = unsafe { __cpuid(1).ecx & FLAG != 0 }; } *HAS_RDRAND } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { if !is_rdrand_supported() { return Err(Error::UNAVAILABLE); } // SAFETY: After this point, rdrand is supported, so calling the rdrand // functions is not undefined behavior. unsafe { rdrand_exact(dest) } } #[target_feature(enable = "rdrand")] unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> { // We use chunks_exact_mut instead of chunks_mut as it allows almost all // calls to memcpy to be elided by the compiler. let mut chunks = dest.chunks_exact_mut(WORD_SIZE); for chunk in chunks.by_ref() { chunk.copy_from_slice(&rdrand()?); } let tail = chunks.into_remainder(); let n = tail.len(); if n > 0 { tail.copy_from_slice(&rdrand()?[..n]); } Ok(()) } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/solaris_illumos.rs010064400017500001750000000046751350536722200163150ustar0000000000000000// 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. //! Implementation for the Solaris family //! //! Read from `/dev/random`, with chunks of limited size (256 bytes). //! `/dev/random` uses the Hash_DRBG with SHA512 algorithm from NIST SP 800-90A. //! `/dev/urandom` uses the FIPS 186-2 algorithm, which is considered less //! secure. We choose to read from `/dev/random`. //! //! Since Solaris 11.3 and mid-2015 illumos, the `getrandom` syscall is available. //! To make sure we can compile on both Solaris and its derivatives, as well as //! function, we check for the existance of getrandom(2) in libc by calling //! libc::dlsym. extern crate std; use crate::{use_file, Error}; use core::mem; use core::num::NonZeroU32; use lazy_static::lazy_static; use std::io; #[cfg(target_os = "illumos")] type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; #[cfg(target_os = "solaris")] type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::c_int; 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(()) } } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { lazy_static! { static ref GETRANDOM_FUNC: Option = fetch_getrandom(); } // 256 bytes is the lowest common denominator across all the Solaris // derived platforms for atomically obtaining random data. for chunk in dest.chunks_mut(256) { match *GETRANDOM_FUNC { Some(fptr) => libc_getrandom(fptr, chunk)?, None => use_file::getrandom_inner(chunk)?, }; } Ok(()) } fn fetch_getrandom() -> Option { let name = "getrandom\0"; let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) }; unsafe { mem::transmute(addr) } } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/use_file.rs010064400017500001750000000033451350566660000146630ustar0000000000000000// 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. //! Implementations that just need to read from a file extern crate std; use crate::Error; use core::num::NonZeroU32; use lazy_static::lazy_static; use std::{fs::File, io::Read}; #[cfg(target_os = "redox")] const FILE_PATH: &str = "rand:"; #[cfg(any(target_os = "android", target_os = "linux", target_os = "netbsd"))] const FILE_PATH: &str = "/dev/urandom"; #[cfg(any( target_os = "dragonfly", target_os = "emscripten", target_os = "haiku", target_os = "macos", target_os = "solaris", target_os = "illumos" ))] const FILE_PATH: &str = "/dev/random"; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { lazy_static! { static ref FILE: Result = init_file(); } let mut f = FILE.as_ref()?; if cfg!(target_os = "emscripten") { // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes. for chunk in dest.chunks_mut(65536) { f.read_exact(chunk)?; } } else { f.read_exact(dest)?; } Ok(()) } fn init_file() -> Result { if FILE_PATH == "/dev/urandom" { // read one byte from "/dev/random" to ensure that OS RNG has initialized File::open("/dev/random")?.read_exact(&mut [0u8; 1])?; } Ok(File::open(FILE_PATH)?) } #[inline(always)] #[allow(dead_code)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/wasi.rs010064400017500001750000000016131350536722200140250ustar0000000000000000// 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. //! Implementation for WASI use crate::Error; use core::num::NonZeroU32; use std::io; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let ret = unsafe { libc::__wasi_random_get(dest.as_mut_ptr() as *mut libc::c_void, dest.len()) }; if ret == libc::__WASI_ESUCCESS { Ok(()) } else { error!("WASI: __wasi_random_get failed with return value {}", ret); Err(io::Error::last_os_error().into()) } } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/wasm32_bindgen.rs010064400017500001750000000113311350536722200156620ustar0000000000000000// 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. //! Implementation for WASM via wasm-bindgen use core::cell::RefCell; use core::mem; use core::num::NonZeroU32; use std::thread_local; use wasm_bindgen::prelude::*; use crate::error::CODE_PREFIX; use crate::Error; const CODE_CRYPTO_UNDEF: u32 = CODE_PREFIX | 0x80; const CODE_GRV_UNDEF: u32 = CODE_PREFIX | 0x81; #[derive(Clone, Debug)] enum RngSource { Node(NodeCrypto), Browser(BrowserCrypto), } // JsValues are always per-thread, so we initialize RngSource for each thread. // See: https://github.com/rustwasm/wasm-bindgen/pull/955 thread_local!( static RNG_SOURCE: RefCell> = RefCell::new(None); ); pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { assert_eq!(mem::size_of::(), 4); RNG_SOURCE.with(|f| { let mut source = f.borrow_mut(); if source.is_none() { *source = Some(getrandom_init()?); } match source.as_ref().unwrap() { RngSource::Node(n) => n.random_fill_sync(dest), RngSource::Browser(n) => { // see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues // // where it says: // // > A QuotaExceededError DOMException is thrown if the // > requested length is greater than 65536 bytes. for chunk in dest.chunks_mut(65536) { n.get_random_values(chunk) } } }; Ok(()) }) } fn getrandom_init() -> Result { // First up we need to detect if we're running in node.js or a // browser. To do this we get ahold of the `this` object (in a bit // of a roundabout fashion). // // Once we have `this` we look at its `self` property, which is // only defined on the web (either a main window or web worker). let this = Function::new("return this").call(&JsValue::undefined()); assert!(this != JsValue::undefined()); let this = This::from(this); let is_browser = this.self_() != JsValue::undefined(); if !is_browser { return Ok(RngSource::Node(node_require("crypto"))); } // If `self` is defined then we're in a browser somehow (main window // or web worker). Here we want to try to use // `crypto.getRandomValues`, but if `crypto` isn't defined we assume // we're in an older web browser and the OS RNG isn't available. let crypto = this.crypto(); if crypto.is_undefined() { 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() { 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, } } #[wasm_bindgen] extern "C" { type Function; #[wasm_bindgen(constructor)] fn new(s: &str) -> Function; #[wasm_bindgen(method)] fn call(this: &Function, self_: &JsValue) -> JsValue; type This; #[wasm_bindgen(method, getter, structural, js_name = self)] fn self_(me: &This) -> JsValue; #[wasm_bindgen(method, getter, structural)] fn crypto(me: &This) -> JsValue; #[derive(Clone, Debug)] type BrowserCrypto; // TODO: these `structural` annotations here ideally wouldn't be here to // avoid a JS shim, but for now with feature detection they're // unavoidable. #[wasm_bindgen(method, js_name = getRandomValues, structural, getter)] fn get_random_values_fn(me: &BrowserCrypto) -> JsValue; #[wasm_bindgen(method, js_name = getRandomValues, structural)] fn get_random_values(me: &BrowserCrypto, buf: &mut [u8]); #[wasm_bindgen(js_name = require)] fn node_require(s: &str) -> NodeCrypto; #[derive(Clone, Debug)] type NodeCrypto; #[wasm_bindgen(method, js_name = randomFillSync, structural)] fn random_fill_sync(me: &NodeCrypto, buf: &mut [u8]); } getrandom-0.1.6/src/wasm32_stdweb.rs010064400017500001750000000065141350536722200155530ustar0000000000000000// 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. //! Implementation for WASM via stdweb use core::mem; use core::num::NonZeroU32; use stdweb::unstable::TryInto; use stdweb::web::error::Error as WebError; use stdweb::{_js_impl, js}; use crate::Error; use lazy_static::lazy_static; #[derive(Clone, Copy, Debug)] enum RngSource { Browser, Node, } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { assert_eq!(mem::size_of::(), 4); lazy_static! { static ref RNG_SOURCE: Result = getrandom_init(); } getrandom_fill((*RNG_SOURCE)?, dest) } fn getrandom_init() -> Result { let result = js! { try { if ( typeof self === "object" && typeof self.crypto === "object" && typeof self.crypto.getRandomValues === "function" ) { return { success: true, ty: 1 }; } if (typeof require("crypto").randomBytes === "function") { return { success: true, ty: 2 }; } return { success: false, error: new Error("not supported") }; } catch(err) { return { success: false, error: err }; } }; if js! { return @{ result.as_ref() }.success } == true { let ty = js! { return @{ result }.ty }; if ty == 1 { Ok(RngSource::Browser) } else if ty == 2 { Ok(RngSource::Node) } else { unreachable!() } } else { let err: WebError = js! { return @{ result }.error }.try_into().unwrap(); error!("getrandom unavailable: {}", err); Err(Error::UNAVAILABLE) } } fn getrandom_fill(source: RngSource, dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(65536) { let len = chunk.len() as u32; let ptr = chunk.as_mut_ptr() as i32; let result = match source { RngSource::Browser => js! { try { let array = new Uint8Array(@{ len }); self.crypto.getRandomValues(array); HEAPU8.set(array, @{ ptr }); return { success: true }; } catch(err) { return { success: false, error: err }; } }, RngSource::Node => js! { try { let bytes = require("crypto").randomBytes(@{ len }); HEAPU8.set(new Uint8Array(bytes), @{ ptr }); return { success: true }; } catch(err) { return { success: false, error: err }; } }, }; if js! { return @{ result.as_ref() }.success } != true { let err: WebError = js! { return @{ result }.error }.try_into().unwrap(); error!("getrandom failed: {}", err); return Err(Error::UNKNOWN); } } Ok(()) } #[inline(always)] pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None } getrandom-0.1.6/src/windows.rs010064400017500001750000000021031350536722200145470ustar0000000000000000// 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. //! Implementation for Windows extern crate std; use crate::Error; use core::num::NonZeroU32; use std::io; extern "system" { #[link_name = "SystemFunction036"] fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: u32) -> u8; } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { // Prevent overflow of u32 for chunk in dest.chunks_mut(u32::max_value() as usize) { let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr(), chunk.len() as u32) }; 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 } getrandom-0.1.6/tests/mod.rs010064400017500001750000000024731350536722200142210ustar0000000000000000extern crate getrandom; use getrandom::getrandom; #[test] fn test_zero() { // Test that APIs are happy with zero-length requests getrandom(&mut [0u8; 0]).unwrap(); } #[test] fn test_diff() { let mut v1 = [0u8; 1000]; getrandom(&mut v1).unwrap(); let mut v2 = [0u8; 1000]; getrandom(&mut v2).unwrap(); let mut n_diff_bits = 0; for i in 0..v1.len() { n_diff_bits += (v1[i] ^ v2[i]).count_ones(); } // Check at least 1 bit per byte differs. p(failure) < 1e-1000 with random input. assert!(n_diff_bits >= v1.len() as u32); } #[test] fn test_huge() { let mut huge = [0u8; 100_000]; getrandom(&mut huge).unwrap(); } #[cfg(any(unix, windows, target_os = "redox", target_os = "fuchsia"))] #[test] fn test_multithreading() { use std::sync::mpsc::channel; use std::thread; let mut txs = vec![]; for _ in 0..20 { let (tx, rx) = channel(); txs.push(tx); thread::spawn(move || { // wait until all the tasks are ready to go. rx.recv().unwrap(); let mut v = [0u8; 1000]; for _ in 0..100 { getrandom(&mut v).unwrap(); thread::yield_now(); } }); } // start all the tasks for tx in txs.iter() { tx.send(()).unwrap(); } } getrandom-0.1.6/.cargo_vcs_info.json0000644000000001120000000000000130510ustar00{ "git": { "sha1": "e02e9466f9325a59f0df61cba19c36aa26a17d4d" } }