1use crate::error::SecureSessionError;
11use crate::secure::pad::{pad_data, unpad_data};
12use aes::cipher::generic_array::GenericArray;
13use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
14use alloc::vec::Vec;
15
16type Encryptor = cbc::Encryptor<aes::Aes128>;
17type Decryptor = cbc::Decryptor<aes::Aes128>;
18
19#[inline]
21pub fn complement_icv(other_mac: &[u8; 16]) -> [u8; 16] {
22 let mut iv = [0u8; 16];
23 for (d, s) in iv.iter_mut().zip(other_mac.iter()) {
24 *d = !*s;
25 }
26 iv
27}
28
29pub fn encrypt_data(s_enc: &[u8; 16], iv: &[u8; 16], data: &[u8]) -> Vec<u8> {
35 let mut buf = Vec::with_capacity(data.len() + 16);
36 buf.extend_from_slice(data);
37 pad_data(&mut buf);
38 debug_assert_eq!(buf.len() % 16, 0);
39
40 let mut enc = Encryptor::new(
41 GenericArray::from_slice(s_enc),
42 GenericArray::from_slice(iv),
43 );
44 for chunk in buf.chunks_exact_mut(16) {
45 let mut block = *GenericArray::from_slice(chunk);
46 enc.encrypt_block_mut(&mut block);
47 chunk.copy_from_slice(&block);
48 }
49 buf
50}
51
52pub fn decrypt_data(
57 s_enc: &[u8; 16],
58 iv: &[u8; 16],
59 ct: &[u8],
60) -> Result<Vec<u8>, SecureSessionError> {
61 if ct.is_empty() || ct.len() % 16 != 0 {
62 return Err(SecureSessionError::BadPadding);
63 }
64 let mut buf = ct.to_vec();
65 let mut dec = Decryptor::new(
66 GenericArray::from_slice(s_enc),
67 GenericArray::from_slice(iv),
68 );
69 for chunk in buf.chunks_exact_mut(16) {
70 let mut block = *GenericArray::from_slice(chunk);
71 dec.decrypt_block_mut(&mut block);
72 chunk.copy_from_slice(&block);
73 }
74 let stripped = unpad_data(&buf)?;
75 Ok(stripped.to_vec())
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn roundtrip_short() {
84 let s_enc = [0x42u8; 16];
85 let iv = [0xAAu8; 16];
86 for n in 0..40usize {
87 let plain: Vec<u8> = (0u8..(n as u8)).collect();
88 let ct = encrypt_data(&s_enc, &iv, &plain);
89 assert_eq!(ct.len() % 16, 0);
90 assert!(ct.len() > plain.len());
91 let pt = decrypt_data(&s_enc, &iv, &ct).unwrap();
92 assert_eq!(pt, plain);
93 }
94 }
95
96 #[test]
97 fn complement_icv_is_xor_ff() {
98 let mac = [0xA5u8; 16];
99 let iv = complement_icv(&mac);
100 assert!(iv.iter().all(|&b| b == 0x5A));
101 }
102
103 #[test]
104 fn decrypt_rejects_unaligned() {
105 let key = [0u8; 16];
106 let iv = [0u8; 16];
107 assert!(decrypt_data(&key, &iv, &[0u8; 15]).is_err());
108 assert!(decrypt_data(&key, &iv, &[]).is_err());
109 }
110
111 #[test]
113 fn wrong_iv_fails_padding() {
114 let s_enc = [0x42u8; 16];
115 let iv = [0xAAu8; 16];
116 let ct = encrypt_data(&s_enc, &iv, &[1, 2, 3, 4]);
117 let bad_iv = [0xFFu8; 16];
118 assert!(decrypt_data(&s_enc, &bad_iv, &ct).is_err());
119 }
120}