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