Skip to content

Commit 6cec07a

Browse files
author
Sangho Lee
committed
reseeding
1 parent 2f51aa6 commit 6cec07a

1 file changed

Lines changed: 83 additions & 4 deletions

File tree

litebox_platform_lvbs/src/host/lvbs_impl.rs

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
Errno, HostInterface, arch::ioport::serial_print_string,
88
host::per_cpu_variables::with_per_cpu_variables,
99
};
10+
use digest::Digest;
1011
use rand_core::{RngCore, SeedableRng};
1112
use zeroize::Zeroizing;
1213

@@ -104,13 +105,67 @@ unsafe impl litebox::platform::ThreadLocalStorageProvider for LvbsLinuxKernel {
104105

105106
impl litebox::platform::CrngProvider for LvbsLinuxKernel {
106107
fn fill_bytes_crng(&self, buf: &mut [u8]) {
107-
static RANDOM: spin::mutex::SpinMutex<Option<rand_chacha::ChaCha20Rng>> =
108-
spin::mutex::SpinMutex::new(None);
108+
static RANDOM: spin::mutex::SpinMutex<Option<LvbsCrng>> = spin::mutex::SpinMutex::new(None);
109109

110110
let mut random = RANDOM.lock();
111111
random
112-
.get_or_insert_with(|| rand_chacha::ChaCha20Rng::from_seed(rdrand_seed()))
113-
.fill_bytes(buf);
112+
.get_or_insert_with(|| LvbsCrng::new(PRK_ONCE.wait(), rdrand_seed()))
113+
.fill_bytes(buf, rdrand_seed);
114+
}
115+
}
116+
117+
const CRNG_RESEED_INTERVAL_BYTES: usize = 1024 * 1024;
118+
const CRNG_RESEED_STATE_BYTES: usize = 32;
119+
120+
struct LvbsCrng {
121+
random: rand_chacha::ChaCha20Rng,
122+
bytes_until_reseed: usize,
123+
reseed_counter: usize,
124+
}
125+
126+
impl LvbsCrng {
127+
fn new(
128+
prk: &[u8; PRK_LEN],
129+
rdrand_seed: <rand_chacha::ChaCha20Rng as SeedableRng>::Seed,
130+
) -> Self {
131+
Self {
132+
random: rand_chacha::ChaCha20Rng::from_seed(crng_seed_from_prk_and_rdrand(
133+
prk,
134+
rdrand_seed,
135+
)),
136+
bytes_until_reseed: CRNG_RESEED_INTERVAL_BYTES,
137+
reseed_counter: 0,
138+
}
139+
}
140+
141+
fn fill_bytes(
142+
&mut self,
143+
mut buf: &mut [u8],
144+
rdrand_seed: impl Fn() -> <rand_chacha::ChaCha20Rng as SeedableRng>::Seed,
145+
) {
146+
while !buf.is_empty() {
147+
let len = buf.len().min(self.bytes_until_reseed);
148+
let (chunk, rest) = buf.split_at_mut(len);
149+
self.random.fill_bytes(chunk);
150+
buf = rest;
151+
self.bytes_until_reseed -= len;
152+
153+
if self.bytes_until_reseed == 0 {
154+
self.reseed(rdrand_seed());
155+
}
156+
}
157+
}
158+
159+
fn reseed(&mut self, rdrand_seed: <rand_chacha::ChaCha20Rng as SeedableRng>::Seed) {
160+
self.reseed_counter += 1;
161+
let mut current_state = Zeroizing::new([0u8; CRNG_RESEED_STATE_BYTES]);
162+
self.random.fill_bytes(&mut *current_state);
163+
self.random = rand_chacha::ChaCha20Rng::from_seed(crng_reseed_from_rdrand_and_state(
164+
rdrand_seed,
165+
self.reseed_counter,
166+
&current_state,
167+
));
168+
self.bytes_until_reseed = CRNG_RESEED_INTERVAL_BYTES;
114169
}
115170
}
116171

@@ -152,6 +207,30 @@ fn rdrand_seed() -> <rand_chacha::ChaCha20Rng as SeedableRng>::Seed {
152207
seed
153208
}
154209

210+
fn crng_seed_from_prk_and_rdrand(
211+
prk: &[u8; PRK_LEN],
212+
rdrand_seed: <rand_chacha::ChaCha20Rng as SeedableRng>::Seed,
213+
) -> <rand_chacha::ChaCha20Rng as SeedableRng>::Seed {
214+
let mut hasher = sha2::Sha256::new();
215+
hasher.update(b"litebox-lvbs-crng-seed-v1");
216+
hasher.update(prk);
217+
hasher.update(rdrand_seed);
218+
hasher.finalize().into()
219+
}
220+
221+
fn crng_reseed_from_rdrand_and_state(
222+
rdrand_seed: <rand_chacha::ChaCha20Rng as SeedableRng>::Seed,
223+
reseed_counter: usize,
224+
current_state: &[u8; CRNG_RESEED_STATE_BYTES],
225+
) -> <rand_chacha::ChaCha20Rng as SeedableRng>::Seed {
226+
let mut hasher = sha2::Sha256::new();
227+
hasher.update(b"litebox-lvbs-crng-reseed-v1");
228+
hasher.update(rdrand_seed);
229+
hasher.update(reseed_counter.to_le_bytes());
230+
hasher.update(current_state);
231+
hasher.finalize().into()
232+
}
233+
155234
pub struct HostLvbsInterface;
156235

157236
impl HostLvbsInterface {}

0 commit comments

Comments
 (0)