1use aes::Aes128;
18use aes::cipher::generic_array::GenericArray;
19use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit};
20
21pub type Block = [u8; 16];
23
24#[inline]
26pub fn aes128_encrypt(key: &[u8; 16], block: &Block) -> Block {
27 let cipher = Aes128::new(GenericArray::from_slice(key));
28 let mut buf = *GenericArray::from_slice(block);
29 cipher.encrypt_block(&mut buf);
30 let mut out = [0u8; 16];
31 out.copy_from_slice(&buf);
32 out
33}
34
35#[inline]
37pub fn aes128_decrypt(key: &[u8; 16], block: &Block) -> Block {
38 let cipher = Aes128::new(GenericArray::from_slice(key));
39 let mut buf = *GenericArray::from_slice(block);
40 cipher.decrypt_block(&mut buf);
41 let mut out = [0u8; 16];
42 out.copy_from_slice(&buf);
43 out
44}
45
46fn key_template(tag1: u8, tag2: u8, rnd_a: &[u8; 8]) -> Block {
48 let mut t = [0u8; 16];
49 t[0] = tag1;
50 t[1] = tag2;
51 t[2..8].copy_from_slice(&rnd_a[0..6]);
52 t
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub struct SessionKeys {
58 pub s_enc: [u8; 16],
60 pub s_mac1: [u8; 16],
62 pub s_mac2: [u8; 16],
64}
65
66impl SessionKeys {
67 pub fn derive(scbk: &[u8; 16], rnd_a: &[u8; 8]) -> Self {
69 Self {
70 s_enc: aes128_encrypt(scbk, &key_template(0x01, 0x82, rnd_a)),
71 s_mac1: aes128_encrypt(scbk, &key_template(0x01, 0x01, rnd_a)),
72 s_mac2: aes128_encrypt(scbk, &key_template(0x01, 0x02, rnd_a)),
73 }
74 }
75}
76
77pub fn client_cryptogram(s_enc: &[u8; 16], rnd_a: &[u8; 8], rnd_b: &[u8; 8]) -> Block {
79 let mut block = [0u8; 16];
80 block[..8].copy_from_slice(rnd_a);
81 block[8..].copy_from_slice(rnd_b);
82 aes128_encrypt(s_enc, &block)
83}
84
85pub fn server_cryptogram(s_enc: &[u8; 16], rnd_a: &[u8; 8], rnd_b: &[u8; 8]) -> Block {
87 let mut block = [0u8; 16];
88 block[..8].copy_from_slice(rnd_b);
89 block[8..].copy_from_slice(rnd_a);
90 aes128_encrypt(s_enc, &block)
91}
92
93pub fn initial_rmac(s_mac1: &[u8; 16], s_mac2: &[u8; 16], server_cryptogram: &Block) -> Block {
97 let first = aes128_encrypt(s_mac1, server_cryptogram);
98 aes128_encrypt(s_mac2, &first)
99}
100
101pub fn diversify_scbk_legacy(mk: &[u8; 16], cuid: &[u8; 8]) -> [u8; 16] {
105 let mut block = [0u8; 16];
106 block[..8].copy_from_slice(cuid);
107 for (i, &b) in cuid.iter().enumerate() {
108 block[8 + i] = !b;
109 }
110 aes128_encrypt(mk, &block)
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
119 fn enc_then_dec_identity() {
120 let key = [0u8; 16];
121 let plain = [0xABu8; 16];
122 let ct = aes128_encrypt(&key, &plain);
123 let pt = aes128_decrypt(&key, &ct);
124 assert_eq!(pt, plain);
125 }
126
127 #[test]
129 fn fips_known_answer() {
130 let key = [0u8; 16];
131 let plain = [0u8; 16];
132 let ct = aes128_encrypt(&key, &plain);
133 let expected = [
134 0x66, 0xE9, 0x4B, 0xD4, 0xEF, 0x8A, 0x2C, 0x3B, 0x88, 0x4C, 0xFA, 0x59, 0xCA, 0x34,
135 0x2B, 0x2E,
136 ];
137 assert_eq!(ct, expected);
138 }
139
140 #[test]
141 fn keys_differ() {
142 let scbk = [0xAA; 16];
143 let rnd_a = [0x55u8; 8];
144 let k = SessionKeys::derive(&scbk, &rnd_a);
145 assert_ne!(k.s_enc, k.s_mac1);
146 assert_ne!(k.s_mac1, k.s_mac2);
147 assert_ne!(k.s_enc, k.s_mac2);
148 }
149
150 #[test]
151 fn cryptograms_distinct() {
152 let s_enc = [0; 16];
153 let rnd_a = [1u8; 8];
154 let rnd_b = [2u8; 8];
155 let c = client_cryptogram(&s_enc, &rnd_a, &rnd_b);
156 let s = server_cryptogram(&s_enc, &rnd_a, &rnd_b);
157 assert_ne!(c, s);
158 }
159}