ring/aead/
counter.rs

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
15use super::{
16    iv::{Iv, IV_LEN},
17    Nonce,
18};
19use crate::endian::*;
20use 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)]
26pub struct Counter<U32> {
27    u32s: [U32; COUNTER_LEN],
28}
29
30const COUNTER_LEN: usize = 4;
31
32impl<U32> Counter<U32>
33where
34    U32: Copy,
35    U32: Encoding<u32>,
36    U32: From<[u8; 4]>,
37    U32: Layout,
38    [U32; 4]: ArrayEncoding<[u8; IV_LEN]>,
39{
40    pub fn zero(nonce: Nonce) -> Self {
41        Self::new(nonce, 0)
42    }
43    pub fn one(nonce: Nonce) -> Self {
44        Self::new(nonce, 1)
45    }
46
47    #[cfg(test)]
48    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
55    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]
72    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]
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
86pub trait Layout {
87    const COUNTER_INDEX: usize;
88}
89
90impl Layout for BigEndian<u32> {
91    const COUNTER_INDEX: usize = 3;
92}
93
94impl Layout for LittleEndian<u32> {
95    const COUNTER_INDEX: usize = 0;
96}
97
98impl<U32> Into<Iv> for Counter<U32>
99where
100    [U32; 4]: ArrayEncoding<[u8; IV_LEN]>,
101{
102    fn into(self) -> Iv {
103        Iv::assume_unique_for_key(*self.u32s.as_byte_array())
104    }
105}