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