blob: e4b8c63a06fdc251ba796b85c1902f8cbc30ee0b [file] [log] [blame]
Pierre-Clément Tosi90cd4f12023-02-17 11:19:56 +00001// Copyright 2023, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Pierre-Clément Tosicb38e6d2023-06-22 10:51:00 +000015//! Functions and drivers for obtaining true entropy.
16
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000017use crate::arch::rand::{platform_entropy, PlatformError, MAX_BYTES_PER_CALL};
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000018use core::fmt;
Pierre-Clément Tosi9320e0e2023-07-11 15:51:55 +000019
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000020pub(crate) type Entropy = [u8; MAX_BYTES_PER_CALL];
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000021
Pierre-Clément Tosicb38e6d2023-06-22 10:51:00 +000022/// Error type for rand operations.
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000023pub enum Error {
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000024 /// No source of entropy found.
25 NoEntropySource,
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000026
27 /// Platform specific error
28 Platform(PlatformError),
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000029}
30
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000031impl From<PlatformError> for Error {
32 fn from(e: PlatformError) -> Self {
33 Error::Platform(e)
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000034 }
35}
36
Pierre-Clément Tosicb38e6d2023-06-22 10:51:00 +000037/// Result type for rand operations.
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000038pub type Result<T> = core::result::Result<T, Error>;
39
40impl fmt::Display for Error {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 match self {
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000043 Self::NoEntropySource => write!(f, "No source of entropy available"),
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000044 Self::Platform(e) => write!(f, "Platform error: {e}"),
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000045 }
46 }
47}
48
Pierre-Clément Tosi78b68512023-06-22 09:40:16 +000049impl fmt::Debug for Error {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 write!(f, "{self}")
52 }
53}
54
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000055/// Fills a slice of bytes with true entropy.
56pub fn fill_with_entropy(s: &mut [u8]) -> Result<()> {
Pierre-Clément Tosi9320e0e2023-07-11 15:51:55 +000057 for chunk in s.chunks_mut(MAX_BYTES_PER_CALL) {
Bartłomiej Grzesikee0a5c62025-02-04 09:06:17 +000058 let entropy = platform_entropy(chunk.len())?;
Pierre-Clément Tosi9320e0e2023-07-11 15:51:55 +000059 chunk.clone_from_slice(&entropy[..chunk.len()]);
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000060 }
61
62 Ok(())
63}
64
Pierre-Clément Tosicb38e6d2023-06-22 10:51:00 +000065/// Generate an array of fixed-size initialized with true-random bytes.
Pierre-Clément Tosia59103d2023-02-02 14:46:55 +000066pub fn random_array<const N: usize>() -> Result<[u8; N]> {
67 let mut arr = [0; N];
68 fill_with_entropy(&mut arr)?;
69 Ok(arr)
70}