oasis_core_runtime/common/crypto/mrae/
nonce.rs1use std::ops::Deref;
3
4use anyhow::{anyhow, Result};
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use rand::{rngs::OsRng, Rng};
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 rng = OsRng {};
39 let mut start_value = [0u8; NONCE_SIZE];
40 rng.fill(&mut start_value);
41
42 Self::new(start_value)
43 }
44
45 pub fn increment(&mut self) -> Result<()> {
50 let mut counter_array = &self.current_value[TAG_SIZE..];
52 let new_counter: u32 = {
54 let mut counter = counter_array.read_u32::<BigEndian>().unwrap();
55 #[allow(clippy::nonminimal_bool)]
57 if counter == !0u32 {
58 counter = 0;
59 } else {
60 counter += 1;
61 }
62 counter
63 };
64 let new_value: [u8; NONCE_SIZE] = {
66 let mut new_value_vec = self.current_value[..TAG_SIZE].to_vec();
67 new_value_vec.write_u32::<BigEndian>(new_counter).unwrap();
68
69 assert!(new_value_vec.len() == NONCE_SIZE);
70
71 let mut new_value = [0; NONCE_SIZE];
72 new_value.copy_from_slice(&new_value_vec);
73 new_value
74 };
75 if new_value == self.start_value {
77 return Err(anyhow!(
78 "This nonce has been exhausted, and a new one must be created",
79 ));
80 }
81 self.current_value = new_value;
83 Ok(())
85 }
86}
87
88impl Deref for Nonce {
89 type Target = [u8; NONCE_SIZE];
90
91 fn deref(&self) -> &Self::Target {
92 &self.current_value
93 }
94}
95
96#[cfg(test)]
97mod tests {
98
99 use super::*;
100
101 #[test]
102 fn test_increment_zero() {
103 let inner = [0; 15];
104 let mut nonce = Nonce::new(inner);
105 nonce.increment().unwrap();
106 let mut expected = [0; 15];
107 expected[14] = 1;
108 assert_eq!(nonce.to_vec(), expected.to_vec());
109 }
110
111 #[test]
112 fn test_increment_one() {
113 let mut start_value = [0; 15];
114 start_value[14] = 1;
115 let mut nonce = Nonce::new(start_value);
116 nonce.increment().unwrap();
117 let mut expected = [0; 15];
118 expected[14] = 2;
119
120 assert_eq!(nonce.to_vec(), expected.to_vec());
121 }
122
123 #[test]
124 fn test_increment_carry() {
125 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255];
126 let mut nonce = Nonce::new(start_value);
127 nonce.increment().unwrap();
128 let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0];
129 assert_eq!(nonce.to_vec(), expected.to_vec());
130 }
131
132 #[test]
133 fn test_increment_overflow() {
134 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
135 let mut nonce = Nonce::new(start_value);
136 nonce.increment().unwrap();
137 let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
138 assert_eq!(nonce.to_vec(), expected.to_vec());
139 }
140
141 #[test]
142 fn test_increment_exhaustion() {
143 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
144 let current_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254];
145 let mut nonce = Nonce {
146 start_value,
147 current_value,
148 };
149 assert_eq!(nonce.increment().is_err(), true);
150 assert_eq!(nonce.increment().is_err(), true);
152 }
153
154 #[test]
155 fn test_double_increment_exhaustion() {
156 let start_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255];
157 let current_value = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 253];
158 let mut nonce = Nonce {
159 start_value,
160 current_value,
161 };
162 let first_expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254];
163 nonce.increment().unwrap();
164 assert_eq!(nonce.to_vec(), first_expected.to_vec());
165 assert_eq!(nonce.increment().is_err(), true);
166 }
167}