oasis_core_runtime/common/crypto/mrae/
nonce.rs1use std::ops::Deref;
3
4use anyhow::{anyhow, Result};
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use rand::{rand_core::TryRng, rngs::SysRng};
7
8pub use super::deoxysii::NONCE_SIZE;
10pub const TAG_SIZE: usize = 11;
12
13#[derive(Debug, Clone)]
19pub struct Nonce {
20 current_value: [u8; NONCE_SIZE],
22 start_value: [u8; NONCE_SIZE],
25}
26
27impl Nonce {
28 pub fn new(start_value: [u8; NONCE_SIZE]) -> Self {
30 Nonce {
31 current_value: start_value,
32 start_value,
33 }
34 }
35
36 pub fn generate() -> Self {
38 let mut start_value = [0u8; NONCE_SIZE];
39 SysRng.try_fill_bytes(&mut start_value).unwrap();
40
41 Self::new(start_value)
42 }
43
44 pub fn increment(&mut self) -> Result<()> {
49 let mut counter_array = &self.current_value[TAG_SIZE..];
51 let new_counter: u32 = {
53 let mut counter = counter_array.read_u32::<BigEndian>().unwrap();
54 #[allow(clippy::nonminimal_bool)]
56 if counter == !0u32 {
57 counter = 0;
58 } else {
59 counter += 1;
60 }
61 counter
62 };
63 let new_value: [u8; NONCE_SIZE] = {
65 let mut new_value_vec = self.current_value[..TAG_SIZE].to_vec();
66 new_value_vec.write_u32::<BigEndian>(new_counter).unwrap();
67
68 assert!(new_value_vec.len() == NONCE_SIZE);
69
70 let mut new_value = [0; NONCE_SIZE];
71 new_value.copy_from_slice(&new_value_vec);
72 new_value
73 };
74 if new_value == self.start_value {
76 return Err(anyhow!(
77 "This nonce has been exhausted, and a new one must be created",
78 ));
79 }
80 self.current_value = new_value;
82 Ok(())
84 }
85}
86
87impl Deref for Nonce {
88 type Target = [u8; NONCE_SIZE];
89
90 fn deref(&self) -> &Self::Target {
91 &self.current_value
92 }
93}
94
95#[cfg(test)]
96mod tests {
97
98 use super::*;
99
100 #[test]
101 fn test_increment_zero() {
102 let inner = [0; 15];
103 let mut nonce = Nonce::new(inner);
104 nonce.increment().unwrap();
105 let mut expected = [0; 15];
106 expected[14] = 1;
107 assert_eq!(nonce.to_vec(), expected.to_vec());
108 }
109
110 #[test]
111 fn test_increment_one() {
112 let mut start_value = [0; 15];
113 start_value[14] = 1;
114 let mut nonce = Nonce::new(start_value);
115 nonce.increment().unwrap();
116 let mut expected = [0; 15];
117 expected[14] = 2;
118
119 assert_eq!(nonce.to_vec(), expected.to_vec());
120 }
121
122 #[test]
123 fn test_increment_carry() {
124 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255];
125 let mut nonce = Nonce::new(start_value);
126 nonce.increment().unwrap();
127 let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0];
128 assert_eq!(nonce.to_vec(), expected.to_vec());
129 }
130
131 #[test]
132 fn test_increment_overflow() {
133 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
134 let mut nonce = Nonce::new(start_value);
135 nonce.increment().unwrap();
136 let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
137 assert_eq!(nonce.to_vec(), expected.to_vec());
138 }
139
140 #[test]
141 fn test_increment_exhaustion() {
142 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
143 let current_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254];
144 let mut nonce = Nonce {
145 start_value,
146 current_value,
147 };
148 assert_eq!(nonce.increment().is_err(), true);
149 assert_eq!(nonce.increment().is_err(), true);
151 }
152
153 #[test]
154 fn test_double_increment_exhaustion() {
155 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
156 let current_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 253];
157 let mut nonce = Nonce {
158 start_value,
159 current_value,
160 };
161 let first_expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254];
162 nonce.increment().unwrap();
163 assert_eq!(nonce.to_vec(), first_expected.to_vec());
164 assert_eq!(nonce.increment().is_err(), true);
165 }
166}