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