xref: /aosp_15_r20/system/security/prng_seeder/src/conditioner.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1*e1997b9aSAndroid Build Coastguard Worker // Copyright (C) 2022 The Android Open Source Project
2*e1997b9aSAndroid Build Coastguard Worker //
3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*e1997b9aSAndroid Build Coastguard Worker //
7*e1997b9aSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*e1997b9aSAndroid Build Coastguard Worker //
9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License.
14*e1997b9aSAndroid Build Coastguard Worker 
15*e1997b9aSAndroid Build Coastguard Worker use std::{fs::File, io::Read};
16*e1997b9aSAndroid Build Coastguard Worker 
17*e1997b9aSAndroid Build Coastguard Worker use anyhow::{ensure, Context, Result};
18*e1997b9aSAndroid Build Coastguard Worker use log::debug;
19*e1997b9aSAndroid Build Coastguard Worker use tokio::io::AsyncReadExt;
20*e1997b9aSAndroid Build Coastguard Worker 
21*e1997b9aSAndroid Build Coastguard Worker use crate::drbg;
22*e1997b9aSAndroid Build Coastguard Worker 
23*e1997b9aSAndroid Build Coastguard Worker const SEED_FOR_CLIENT_LEN: usize = 496;
24*e1997b9aSAndroid Build Coastguard Worker const NUM_REQUESTS_PER_RESEED: u32 = 256;
25*e1997b9aSAndroid Build Coastguard Worker 
26*e1997b9aSAndroid Build Coastguard Worker pub struct ConditionerBuilder {
27*e1997b9aSAndroid Build Coastguard Worker     hwrng: File,
28*e1997b9aSAndroid Build Coastguard Worker     rg: drbg::Drbg,
29*e1997b9aSAndroid Build Coastguard Worker }
30*e1997b9aSAndroid Build Coastguard Worker 
31*e1997b9aSAndroid Build Coastguard Worker impl ConditionerBuilder {
new(mut hwrng: File) -> Result<ConditionerBuilder>32*e1997b9aSAndroid Build Coastguard Worker     pub fn new(mut hwrng: File) -> Result<ConditionerBuilder> {
33*e1997b9aSAndroid Build Coastguard Worker         let mut et: drbg::Entropy = [0; drbg::ENTROPY_LEN];
34*e1997b9aSAndroid Build Coastguard Worker         hwrng.read_exact(&mut et).context("hwrng.read_exact in new")?;
35*e1997b9aSAndroid Build Coastguard Worker         let rg = drbg::Drbg::new(&et)?;
36*e1997b9aSAndroid Build Coastguard Worker         Ok(ConditionerBuilder { hwrng, rg })
37*e1997b9aSAndroid Build Coastguard Worker     }
38*e1997b9aSAndroid Build Coastguard Worker 
build(self) -> Conditioner39*e1997b9aSAndroid Build Coastguard Worker     pub fn build(self) -> Conditioner {
40*e1997b9aSAndroid Build Coastguard Worker         Conditioner {
41*e1997b9aSAndroid Build Coastguard Worker             hwrng: tokio::fs::File::from_std(self.hwrng),
42*e1997b9aSAndroid Build Coastguard Worker             rg: self.rg,
43*e1997b9aSAndroid Build Coastguard Worker             requests_since_reseed: 0,
44*e1997b9aSAndroid Build Coastguard Worker         }
45*e1997b9aSAndroid Build Coastguard Worker     }
46*e1997b9aSAndroid Build Coastguard Worker }
47*e1997b9aSAndroid Build Coastguard Worker 
48*e1997b9aSAndroid Build Coastguard Worker pub struct Conditioner {
49*e1997b9aSAndroid Build Coastguard Worker     hwrng: tokio::fs::File,
50*e1997b9aSAndroid Build Coastguard Worker     rg: drbg::Drbg,
51*e1997b9aSAndroid Build Coastguard Worker     requests_since_reseed: u32,
52*e1997b9aSAndroid Build Coastguard Worker }
53*e1997b9aSAndroid Build Coastguard Worker 
54*e1997b9aSAndroid Build Coastguard Worker impl Conditioner {
reseed_if_necessary(&mut self) -> Result<()>55*e1997b9aSAndroid Build Coastguard Worker     pub async fn reseed_if_necessary(&mut self) -> Result<()> {
56*e1997b9aSAndroid Build Coastguard Worker         if self.requests_since_reseed >= NUM_REQUESTS_PER_RESEED {
57*e1997b9aSAndroid Build Coastguard Worker             debug!("Reseeding DRBG");
58*e1997b9aSAndroid Build Coastguard Worker             let mut et: drbg::Entropy = [0; drbg::ENTROPY_LEN];
59*e1997b9aSAndroid Build Coastguard Worker             self.hwrng.read_exact(&mut et).await.context("hwrng.read_exact in reseed")?;
60*e1997b9aSAndroid Build Coastguard Worker             self.rg.reseed(&et)?;
61*e1997b9aSAndroid Build Coastguard Worker             self.requests_since_reseed = 0;
62*e1997b9aSAndroid Build Coastguard Worker         }
63*e1997b9aSAndroid Build Coastguard Worker         Ok(())
64*e1997b9aSAndroid Build Coastguard Worker     }
65*e1997b9aSAndroid Build Coastguard Worker 
request(&mut self) -> Result<[u8; SEED_FOR_CLIENT_LEN]>66*e1997b9aSAndroid Build Coastguard Worker     pub fn request(&mut self) -> Result<[u8; SEED_FOR_CLIENT_LEN]> {
67*e1997b9aSAndroid Build Coastguard Worker         ensure!(self.requests_since_reseed < NUM_REQUESTS_PER_RESEED, "Not enough reseeds");
68*e1997b9aSAndroid Build Coastguard Worker         let mut seed_for_client = [0u8; SEED_FOR_CLIENT_LEN];
69*e1997b9aSAndroid Build Coastguard Worker         self.rg.generate(&mut seed_for_client)?;
70*e1997b9aSAndroid Build Coastguard Worker         self.requests_since_reseed += 1;
71*e1997b9aSAndroid Build Coastguard Worker         Ok(seed_for_client)
72*e1997b9aSAndroid Build Coastguard Worker     }
73*e1997b9aSAndroid Build Coastguard Worker }
74