1#![allow(deprecated)]
2#[allow(deprecated)]
5use aes::cipher::{Array, BlockCipherEncrypt};
6use polyval::{Polyval, universal_hash::UniversalHash};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Error {
11 InputTooShort,
13 TweakTooLong,
15 TweakTooShort,
17 InvalidTweak,
19 InvalidDigit,
21 OutputLengthMismatch,
23}
24
25impl core::fmt::Display for Error {
26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27 match self {
28 Error::InputTooShort => write!(f, "input too short"),
29 Error::TweakTooLong => write!(f, "tweak too long"),
30 Error::TweakTooShort => write!(f, "tweak too short"),
31 Error::InvalidTweak => write!(f, "invalid tweak format"),
32 Error::InvalidDigit => write!(f, "digit out of range for radix"),
33 Error::OutputLengthMismatch => write!(f, "output length does not match input length"),
34 }
35 }
36}
37
38#[cfg(feature = "std")]
39impl std::error::Error for Error {}
40
41pub const BLOCK_LENGTH: usize = 16;
43
44#[derive(Clone, Copy)]
46pub enum Direction {
47 Encrypt,
48 Decrypt,
49}
50
51pub fn absorb(poly: &mut Polyval, msg: &[u8]) -> [u8; BLOCK_LENGTH] {
55 let full_blocks = msg.len() / BLOCK_LENGTH;
56 for i in 0..full_blocks {
57 let block = Array::clone_from_slice(&msg[i * BLOCK_LENGTH..(i + 1) * BLOCK_LENGTH]);
58 poly.update(&[block]);
59 }
60
61 let remainder = msg.len() % BLOCK_LENGTH;
62 if remainder > 0 {
63 let start = full_blocks * BLOCK_LENGTH;
64 let remaining = &msg[start..];
65
66 let mut padded_block = [0u8; BLOCK_LENGTH];
67 padded_block[..remaining.len()].copy_from_slice(remaining);
68 padded_block[remaining.len()] = 1;
69 poly.update(&[Array::clone_from_slice(&padded_block)]);
70 }
71
72 let mut hh = [0u8; BLOCK_LENGTH];
73 hh.copy_from_slice(poly.clone().finalize().as_slice());
74 hh
75}
76
77pub fn xctr<Aes: BlockCipherEncrypt>(
81 ks_enc: &Aes,
82 dst: &mut [u8],
83 src: &[u8],
84 z: &[u8; BLOCK_LENGTH],
85) {
86 let mut counter: u64 = 1;
87 let mut i = 0;
88
89 while i + BLOCK_LENGTH <= src.len() {
90 let mut counter_bytes = [0u8; BLOCK_LENGTH];
91 counter_bytes[..8].copy_from_slice(&counter.to_le_bytes());
92
93 for j in 0..BLOCK_LENGTH {
94 counter_bytes[j] ^= z[j];
95 }
96
97 let mut block = Array::clone_from_slice(&counter_bytes);
98 ks_enc.encrypt_block(&mut block);
99
100 for j in 0..BLOCK_LENGTH {
101 dst[i + j] = src[i + j] ^ block[j];
102 }
103
104 counter += 1;
105 i += BLOCK_LENGTH;
106 }
107
108 let left = src.len() - i;
109 if left > 0 {
110 let mut counter_bytes = [0u8; BLOCK_LENGTH];
111 counter_bytes[..8].copy_from_slice(&counter.to_le_bytes());
112
113 for j in 0..BLOCK_LENGTH {
114 counter_bytes[j] ^= z[j];
115 }
116
117 let mut block = Array::clone_from_slice(&counter_bytes);
118 ks_enc.encrypt_block(&mut block);
119
120 for j in 0..left {
121 dst[i + j] = src[i + j] ^ block[j];
122 }
123 }
124}
125
126#[inline]
131pub fn lfsr_next_128(state: &[u8; 16]) -> [u8; 16] {
132 let mut result = *state;
133
134 let msb = result[15] >> 7;
135 let mask = 0u8.wrapping_sub(msb);
136
137 let mut carry: u8 = 0;
138 for byte in result.iter_mut() {
139 let new_carry = (*byte & 0x80) >> 7;
140 *byte = (*byte << 1) | carry;
141 carry = new_carry;
142 }
143
144 result[0] ^= 0x87 & mask;
145
146 result
147}
148
149#[inline]
154#[allow(dead_code)]
155pub fn lfsr_next_256(state: &[u8; 32]) -> [u8; 32] {
156 let mut result = *state;
157
158 let msb = result[31] >> 7;
159 let mask = 0u8.wrapping_sub(msb);
160
161 let mut carry: u8 = 0;
162 for byte in result.iter_mut() {
163 let new_carry = (*byte & 0x80) >> 7;
164 *byte = (*byte << 1) | carry;
165 carry = new_carry;
166 }
167
168 result[0] ^= 0x01 & mask;
169 result[30] ^= 0x40 & mask;
170 result[31] ^= 0x08 & mask;
171 result[31] ^= 0x40 & mask;
172
173 result
174}
175
176#[inline]
178pub fn xor_block(dst: &mut [u8; BLOCK_LENGTH], src: &[u8; BLOCK_LENGTH]) {
179 for i in 0..BLOCK_LENGTH {
180 dst[i] ^= src[i];
181 }
182}
183
184#[inline]
186pub fn xor_blocks(a: &[u8; BLOCK_LENGTH], b: &[u8; BLOCK_LENGTH]) -> [u8; BLOCK_LENGTH] {
187 let mut result = *a;
188 xor_block(&mut result, b);
189 result
190}
191
192#[inline]
194pub fn xor_blocks_3(
195 a: &[u8; BLOCK_LENGTH],
196 b: &[u8; BLOCK_LENGTH],
197 c: &[u8; BLOCK_LENGTH],
198) -> [u8; BLOCK_LENGTH] {
199 let mut result = [0u8; BLOCK_LENGTH];
200 for i in 0..BLOCK_LENGTH {
201 result[i] = a[i] ^ b[i] ^ c[i];
202 }
203 result
204}
205
206pub fn elk<Aes: BlockCipherEncrypt>(
211 ks: &Aes,
212 dst: &mut [u8],
213 src: &[u8],
214 seed: &[u8; BLOCK_LENGTH],
215) {
216 let mut lfsr_state = *seed;
217 let mut i = 0;
218
219 while i + BLOCK_LENGTH <= src.len() {
220 let mut block = Array::clone_from_slice(&lfsr_state);
221 ks.encrypt_block(&mut block);
222
223 for j in 0..BLOCK_LENGTH {
224 dst[i + j] = src[i + j] ^ block[j];
225 }
226
227 lfsr_state = lfsr_next_128(&lfsr_state);
228 i += BLOCK_LENGTH;
229 }
230
231 let left = src.len() - i;
232 if left > 0 {
233 let mut block = Array::clone_from_slice(&lfsr_state);
234 ks.encrypt_block(&mut block);
235
236 for j in 0..left {
237 dst[i + j] = src[i + j] ^ block[j];
238 }
239 }
240}