dup_crypto/
rand.rs

1//  Copyright (C) 2020 Éloïs SANCHEZ.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16//! Manage random generation.
17
18use byteorder::ByteOrder;
19use getrandom::getrandom;
20
21/// An error with absolutely no details.
22///
23/// *dup-crypto* uses this unit type as the error type in most of its results
24/// because (a) usually the specific reasons for a failure are obvious or are
25/// not useful to know, and/or (b) providing more details about a failure might
26/// provide a dangerous side channel, and/or (c) it greatly simplifies the
27/// error handling logic.
28///
29/// Experience with using and implementing other crypto libraries like has
30/// shown that sophisticated error reporting facilities often cause significant
31/// bugs themselves, both within the crypto library and within users of the
32/// crypto library. This approach attempts to minimize complexity in the hopes
33/// of avoiding such problems. In some cases, this approach may be too extreme,
34/// and it may be important for an operation to provide some details about the
35/// cause of a failure. Users of *dup-crypto* are encouraged to report such cases so
36/// that they can be addressed individually.
37#[derive(Copy, Clone, Debug, PartialEq)]
38pub struct UnspecifiedRandError;
39
40/// Secure random bytes generator
41pub fn gen_random_bytes(buffer: &mut [u8]) -> Result<(), UnspecifiedRandError> {
42    getrandom(buffer).map_err(|_| UnspecifiedRandError)
43}
44
45#[inline]
46/// Generate random u8
47pub fn gen_u8() -> Result<u8, UnspecifiedRandError> {
48    let mut random_byte = [0u8; 1];
49    getrandom(&mut random_byte[..]).map_err(|_| UnspecifiedRandError)?;
50    Ok(random_byte[0])
51}
52
53#[inline]
54/// Generate random u32
55pub fn gen_u32() -> Result<u32, UnspecifiedRandError> {
56    let mut random_bytes = [0u8; 4];
57    getrandom(&mut random_bytes[..]).map_err(|_| UnspecifiedRandError)?;
58    Ok(byteorder::BigEndian::read_u32(&random_bytes))
59}
60
61#[inline]
62/// Generate random 16 bytes
63pub fn gen_16_bytes() -> Result<[u8; 16], UnspecifiedRandError> {
64    let mut random_bytes = [0u8; 16];
65    getrandom(&mut random_bytes[..]).map_err(|_| UnspecifiedRandError)?;
66    Ok(random_bytes)
67}
68
69#[inline]
70/// Generate random 32 bytes
71pub fn gen_32_bytes() -> Result<[u8; 32], UnspecifiedRandError> {
72    let mut random_bytes = [0u8; 32];
73    getrandom(&mut random_bytes[..]).map_err(|_| UnspecifiedRandError)?;
74    Ok(random_bytes)
75}
76
77#[cfg(test)]
78mod tests {
79
80    use super::*;
81
82    #[test]
83    fn test_gen_u32() -> Result<(), UnspecifiedRandError> {
84        assert_ne!(gen_u32()?, gen_u32()?);
85        Ok(())
86    }
87
88    #[test]
89    fn test_gen_random_bytes() -> Result<(), UnspecifiedRandError> {
90        let mut buffer = [0u8; 51];
91        gen_random_bytes(buffer.as_mut())?;
92        let mut buffer = [0u8; 48];
93        gen_random_bytes(buffer.as_mut())?;
94        Ok(())
95    }
96}