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