1use crate::prf;
6use bytes::{BufMut, BytesMut};
7use fuchsia_sync::Mutex;
8
9use ieee80211::MacAddr;
10use num::bigint::BigUint;
11use rand::rngs::OsRng;
12use rand::Rng as _;
13use std::sync::Arc;
14
15pub type Nonce = [u8; 32];
16
17#[derive(Debug)]
21pub struct NonceReader {
22 key_counter: Mutex<BigUint>,
23}
24
25impl NonceReader {
26 pub fn new(sta_addr: &MacAddr) -> Result<Arc<NonceReader>, anyhow::Error> {
27 let mut buf = BytesMut::with_capacity(14);
34 let epoch_nanos = zx::MonotonicInstant::get().into_nanos();
35 buf.put_i64_le(epoch_nanos);
36 buf.put_slice(sta_addr.as_slice());
37 let k = OsRng.gen::<[u8; 32]>();
38 let init = prf::prf(&k[..], "Init Counter", &buf[..], 8 * std::mem::size_of_val(&k))?;
39 Ok(Arc::new(NonceReader { key_counter: Mutex::new(BigUint::from_bytes_le(&init[..])) }))
40 }
41
42 pub fn next(&self) -> Nonce {
43 let mut counter = self.key_counter.lock();
44 *counter += 1u8;
45
46 let mut result = (*counter).to_bytes_le();
48 result.resize(32, 0);
49 let mut nonce = Nonce::default();
50 nonce.copy_from_slice(&result[..]);
51 nonce
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_next_nonce() {
61 let addr = MacAddr::from([1, 2, 3, 4, 5, 6]);
62 let rdr = NonceReader::new(&addr).expect("error creating NonceReader");
63 let mut previous_nonce = rdr.next();
64 for _ in 0..300 {
65 let nonce = rdr.next();
66 let nonce_int = BigUint::from_bytes_le(&nonce[..]);
67 let previous_nonce_int = BigUint::from_bytes_le(&previous_nonce[..]);
68 assert_eq!(nonce_int.gt(&previous_nonce_int), true);
69
70 previous_nonce = nonce;
71 }
72 }
73}