aws_lc_rs/aead/nonce_sequence/
counter32.rs1use crate::aead::{Nonce, NonceSequence, NONCE_LEN};
5use crate::error::Unspecified;
6use crate::iv::FixedLength;
7
8#[allow(clippy::module_name_repetitions)]
18pub struct Counter32 {
19 limit: u32,
20 generated: u32,
21 identifier: [u8; 8],
22 counter: u32,
23}
24
25#[allow(clippy::module_name_repetitions)]
27pub struct Counter32Builder {
28 limit: u32,
29 identifier: [u8; 8],
30 counter: u32,
31}
32
33impl Default for Counter32Builder {
34 fn default() -> Self {
35 Counter32Builder::new()
36 }
37}
38
39impl Counter32Builder {
40 #[must_use]
42 pub fn new() -> Counter32Builder {
43 Counter32Builder {
44 limit: u32::MAX,
45 identifier: [0u8; 8],
46 counter: 0,
47 }
48 }
49
50 #[must_use]
53 pub fn identifier<T: Into<[u8; 8]>>(mut self, identifier: T) -> Counter32Builder {
54 self.identifier = identifier.into();
55 self
56 }
57
58 #[must_use]
60 pub fn counter(mut self, counter: u32) -> Counter32Builder {
61 self.counter = counter;
62 self
63 }
64
65 #[must_use]
67 pub fn limit(mut self, limit: u32) -> Counter32Builder {
68 self.limit = limit;
69 self
70 }
71
72 #[must_use]
75 pub fn build(self) -> Counter32 {
76 Counter32 {
77 limit: self.limit,
78 generated: 0,
79 identifier: self.identifier,
80 counter: self.counter,
81 }
82 }
83}
84
85impl Counter32 {
86 #[must_use]
88 pub fn identifier(&self) -> [u8; 8] {
89 self.identifier
90 }
91
92 #[must_use]
94 pub fn counter(&self) -> u32 {
95 self.counter
96 }
97
98 #[must_use]
100 pub fn generated(&self) -> u32 {
101 self.generated
102 }
103
104 #[must_use]
106 pub fn limit(&self) -> u32 {
107 self.limit
108 }
109}
110
111impl NonceSequence for Counter32 {
112 fn advance(&mut self) -> Result<Nonce, Unspecified> {
113 self.generated = self.generated.checked_add(1).ok_or(Unspecified)?;
114 if self.generated > self.limit {
115 return Err(Unspecified);
116 }
117 let counter_bytes: [u8; 4] = self.counter.to_be_bytes();
118 let mut nonce_bytes = [0u8; NONCE_LEN];
119 nonce_bytes[..8].copy_from_slice(&self.identifier);
120 nonce_bytes[8..].copy_from_slice(&counter_bytes);
121 self.counter = self.counter.wrapping_add(1);
122 Ok(Nonce(FixedLength::from(nonce_bytes)))
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use crate::aead::nonce_sequence::Counter32Builder;
129 use crate::aead::NonceSequence;
130
131 #[test]
132 fn test_counter32_identifier() {
133 let mut cns = Counter32Builder::default()
134 .identifier([0xA1, 0xB2, 0xC3, 0xD4, 0xA2, 0xB3, 0xC4, 0xD5])
135 .counter(7)
136 .build();
137 assert_eq!(0, cns.generated());
138 let nonce = cns.advance().unwrap();
139 let nonce = nonce.as_ref();
140 assert_eq!(8, cns.counter());
141 assert_eq!(
142 [0xA1, 0xB2, 0xC3, 0xD4, 0xA2, 0xB3, 0xC4, 0xD5],
143 cns.identifier()
144 );
145 assert_eq!(u32::MAX, cns.limit());
146 assert_eq!(1, cns.generated());
147 assert_eq!(
148 nonce,
149 &[0xA1, 0xB2, 0xC3, 0xD4, 0xA2, 0xB3, 0xC4, 0xD5, 0, 0, 0, 7]
150 );
151 let nonce = cns.advance().unwrap();
152 let nonce = nonce.as_ref();
153 assert_eq!(2, cns.generated());
154 assert_eq!(9, cns.counter());
155 assert_eq!(
156 [0xA1, 0xB2, 0xC3, 0xD4, 0xA2, 0xB3, 0xC4, 0xD5],
157 cns.identifier()
158 );
159 assert_eq!(
160 nonce,
161 &[0xA1, 0xB2, 0xC3, 0xD4, 0xA2, 0xB3, 0xC4, 0xD5, 0, 0, 0, 8]
162 );
163 }
164
165 #[test]
166 fn test_counter32() {
167 let mut cns = Counter32Builder::new().counter(0x_4CB0_16EA_u32).build();
168 let nonce = cns.advance().unwrap();
169 let nonce = nonce.as_ref();
170 assert_eq!(nonce, &[0, 0, 0, 0, 0, 0, 0, 0, 0x4C, 0xB0, 0x16, 0xEA]);
171 let nonce = cns.advance().unwrap();
172 let nonce = nonce.as_ref();
173 assert_eq!(nonce, &[0, 0, 0, 0, 0, 0, 0, 0, 0x4C, 0xB0, 0x16, 0xEB]);
174 }
175
176 #[test]
177 fn test_counter32_int_id() {
178 let mut cns = Counter32Builder::new()
179 .counter(0x_6A_u32)
180 .identifier(0x_7B_u64.to_be_bytes())
181 .build();
182 let nonce = cns.advance().unwrap();
183 let nonce = nonce.as_ref();
184 assert_eq!(nonce, &[0, 0, 0, 0, 0, 0, 0, 0x7B, 0, 0, 0, 0x6A]);
185 let nonce = cns.advance().unwrap();
186 let nonce = nonce.as_ref();
187 assert_eq!(nonce, &[0, 0, 0, 0, 0, 0, 0, 0x7B, 0, 0, 0, 0x6B]);
188 }
189
190 #[test]
191 fn test_counter32_limit() {
192 let mut cns = Counter32Builder::new().limit(1).build();
193 assert_eq!(1, cns.limit());
194 assert_eq!(0, cns.generated());
195 let _nonce = cns.advance().unwrap();
196 assert_eq!(1, cns.generated());
197 assert!(cns.advance().is_err());
198 }
199}