ring/aead/
counter.rs
1use super::{
16 iv::{Iv, IV_LEN},
17 Nonce,
18};
19use crate::endian::*;
20use core::convert::TryInto;
21
22#[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}