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 core::array::from_fn(|i| !other_mac[i])
23}
24
25pub fn encrypt_data(s_enc: &[u8; 16], iv: &[u8; 16], data: &[u8]) -> Vec<u8> {
31 let mut buf = Vec::with_capacity(data.len() + 16);
32 buf.extend_from_slice(data);
33 pad_data(&mut buf);
34 debug_assert_eq!(buf.len() % 16, 0);
35
36 let mut enc = Encryptor::new(
37 GenericArray::from_slice(s_enc),
38 GenericArray::from_slice(iv),
39 );
40 for chunk in buf.chunks_exact_mut(16) {
41 let mut block = *GenericArray::from_slice(chunk);
42 enc.encrypt_block_mut(&mut block);
43 chunk.copy_from_slice(&block);
44 }
45 buf
46}
47
48pub fn decrypt_data(
53 s_enc: &[u8; 16],
54 iv: &[u8; 16],
55 ct: &[u8],
56) -> Result<Vec<u8>, SecureSessionError> {
57 if ct.is_empty() || ct.len() % 16 != 0 {
58 return Err(SecureSessionError::BadPadding);
59 }
60 let mut buf = ct.to_vec();
61 let mut dec = Decryptor::new(
62 GenericArray::from_slice(s_enc),
63 GenericArray::from_slice(iv),
64 );
65 for chunk in buf.chunks_exact_mut(16) {
66 let mut block = *GenericArray::from_slice(chunk);
67 dec.decrypt_block_mut(&mut block);
68 chunk.copy_from_slice(&block);
69 }
70 let stripped = unpad_data(&buf)?;
71 Ok(stripped.to_vec())
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 fn fixture(tag: u8) -> [u8; 16] {
80 core::array::from_fn(|i| tag.wrapping_add(i as u8))
81 }
82
83 #[test]
84 fn roundtrip_short() {
85 let s_enc = fixture(0x42);
86 let iv = fixture(0xAA);
87 for n in 0..40usize {
88 let plain: Vec<u8> = (0u8..(n as u8)).collect();
89 let ct = encrypt_data(&s_enc, &iv, &plain);
90 assert_eq!(ct.len() % 16, 0);
91 assert!(ct.len() > plain.len());
92 let pt = decrypt_data(&s_enc, &iv, &ct).unwrap();
93 assert_eq!(pt, plain);
94 }
95 }
96
97 #[test]
98 fn complement_icv_is_xor_ff() {
99 let mac = [0xA5u8; 16];
100 let iv = complement_icv(&mac);
101 assert!(iv.iter().all(|&b| b == 0x5A));
102 }
103
104 #[test]
105 fn decrypt_rejects_unaligned() {
106 let key = fixture(0);
107 let iv = fixture(0);
108 assert!(decrypt_data(&key, &iv, &[0u8; 15]).is_err());
109 assert!(decrypt_data(&key, &iv, &[]).is_err());
110 }
111
112 #[test]
114 fn wrong_iv_fails_padding() {
115 let s_enc = fixture(0x42);
116 let iv = fixture(0xAA);
117 let ct = encrypt_data(&s_enc, &iv, &[1, 2, 3, 4]);
118 let bad_iv = fixture(0xFF);
119 assert!(decrypt_data(&s_enc, &bad_iv, &ct).is_err());
120 }
121}