1use crypto_bigint::Encoding;
2
3use crypto_bigint::U128;
4
5pub struct Nonce12 {
7 iv: U128,
8 seq_id: u64,
9}
10
11impl Nonce12 {
12 #[inline]
14 pub fn from_ks_iv(i: &[u8; 12]) -> Self {
15 let iv = U128::from_be_bytes([
16 0, 0, 0, 0, i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7], i[8], i[9], i[10], i[11],
17 ]);
18 let seq_id = 0u64;
19
20 Self { iv, seq_id }
21 }
22 #[inline]
24 pub fn use_and_incr(&mut self) -> Option<[u8; 12]> {
25 let seq_id = U128::from_u64(self.seq_id);
26 let nonce_u128 = self.iv.wrapping_xor(&seq_id);
27 let b: [u8; 16] = nonce_u128.to_be_bytes();
28
29 if self.seq_id == u64::MAX {
30 return None;
31 }
32
33 self.seq_id += 1;
34
35 Some([
36 b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15],
37 ])
38 }
39 #[inline]
41 #[cfg(test)]
42 pub fn hazmat_fast_forward_with_incr(&mut self, fast_forward: u64) -> Option<[u8; 12]> {
43 self.seq_id = fast_forward;
44 self.use_and_incr()
45 }
46}
47
48#[cfg(test)]
49mod test {
50
51 use super::*;
52 use hex_literal::hex;
53
54 #[test]
55 fn cur() {
56 let iv_bytes: [u8; 12] = hex!("6fac81d4f2c3bebe02b8b375");
57 let mut running_nonce = Nonce12::from_ks_iv(&iv_bytes);
58 let cur = running_nonce.use_and_incr();
59
60 assert_eq!(cur, Some(iv_bytes));
61 }
62
63 #[test]
64 fn packet_seq_1() {
65 let iv_bytes: [u8; 12] = hex!("6fac81d4f2c3bebe02b8b375");
66 let mut running_nonce = Nonce12::from_ks_iv(&iv_bytes);
67 let _cur = running_nonce.use_and_incr();
68 let seq_1 = running_nonce.use_and_incr();
69
70 assert_eq!(seq_1, Some(hex!("6fac81d4f2c3bebe02b8b374")));
71 }
72
73 #[test]
75 fn packet_seq_max() {
76 let iv_bytes: [u8; 12] = hex!("6fac81d4f2c3bebe02b8b375");
77 let mut running_nonce = Nonce12::from_ks_iv(&iv_bytes);
78 let cur = running_nonce.hazmat_fast_forward_with_incr(u64::MAX);
79
80 assert_eq!(cur, None);
81 }
82}