1 // Copyright 2018 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use super::{
16     iv::{Iv, IV_LEN},
17     Nonce,
18 };
19 use crate::endian::*;
20 use core::convert::TryInto;
21 
22 /// A generator of a monotonically increasing series of `Iv`s.
23 ///
24 /// Intentionally not `Clone` to ensure counters aren't forked.
25 #[repr(C)]
26 pub struct Counter<U32> {
27     u32s: [U32; COUNTER_LEN],
28 }
29 
30 const COUNTER_LEN: usize = 4;
31 
32 impl<U32> Counter<U32>
33 where
34     U32: Copy,
35     U32: Encoding<u32>,
36     U32: From<[u8; 4]>,
37     U32: Layout,
38     [U32; 4]: ArrayEncoding<[u8; IV_LEN]>,
39 {
zero(nonce: Nonce) -> Self40     pub fn zero(nonce: Nonce) -> Self {
41         Self::new(nonce, 0)
42     }
one(nonce: Nonce) -> Self43     pub fn one(nonce: Nonce) -> Self {
44         Self::new(nonce, 1)
45     }
46 
47     #[cfg(test)]
from_test_vector(nonce: &[u8], initial_counter: u32) -> Self48     pub fn from_test_vector(nonce: &[u8], initial_counter: u32) -> Self {
49         Self::new(
50             Nonce::try_assume_unique_for_key(nonce).unwrap(),
51             initial_counter,
52         )
53     }
54 
new(nonce: Nonce, initial_counter: u32) -> Self55     fn new(nonce: Nonce, initial_counter: u32) -> Self {
56         let mut r = Self {
57             u32s: [U32::ZERO; COUNTER_LEN],
58         };
59         let nonce_index = (U32::COUNTER_INDEX + 1) % COUNTER_LEN;
60         (&mut r.u32s[nonce_index..][..3])
61             .iter_mut()
62             .zip(nonce.as_ref().chunks_exact(4))
63             .for_each(|(initial, nonce)| {
64                 let nonce: &[u8; 4] = nonce.try_into().unwrap();
65                 *initial = U32::from(*nonce);
66             });
67         r.u32s[U32::COUNTER_INDEX] = U32::from(initial_counter);
68         r
69     }
70 
71     #[inline]
increment(&mut self) -> Iv72     pub fn increment(&mut self) -> Iv {
73         let current = Self { u32s: self.u32s };
74         self.increment_by_less_safe(1);
75         current.into()
76     }
77 
78     #[inline]
increment_by_less_safe(&mut self, increment_by: u32)79     pub fn increment_by_less_safe(&mut self, increment_by: u32) {
80         let counter = &mut self.u32s[U32::COUNTER_INDEX];
81         let old_value: u32 = (*counter).into();
82         *counter = U32::from(old_value + increment_by);
83     }
84 }
85 
86 pub trait Layout {
87     const COUNTER_INDEX: usize;
88 }
89 
90 impl Layout for BigEndian<u32> {
91     const COUNTER_INDEX: usize = 3;
92 }
93 
94 impl Layout for LittleEndian<u32> {
95     const COUNTER_INDEX: usize = 0;
96 }
97 
98 impl<U32> Into<Iv> for Counter<U32>
99 where
100     [U32; 4]: ArrayEncoding<[u8; IV_LEN]>,
101 {
into(self) -> Iv102     fn into(self) -> Iv {
103         Iv::assume_unique_for_key(*self.u32s.as_byte_array())
104     }
105 }
106