1mod mem_update_cfg;
2
3use crate::aes::{aes_cbc_enc, aes_ecb_enc, AesType};
4use crate::aes_mp::mp_compression;
5use crate::mem_update::mem_update_cfg::{KEY_UPDATE_ENC_C, KEY_UPDATE_MAC_C};
6use crate::cmac::cmac;
7
8#[derive(Debug, Clone, Copy)]
9pub enum KeyFlag {
10 WriteProtection = 0x10,
11 BootProtection = 0x08,
12 DebuggerProtection = 0x04,
13 KeyUsage = 0x02,
14 Wildcard = 0x01,
15 FlagUnset = 0x00,
16}
17
18#[derive(Debug)]
19#[allow(dead_code)]
20pub struct MemUpdate {
21 k1: [u8; 16],
22 k2: [u8; 16],
23 k3: [u8; 16],
24 k4: [u8; 16],
25 m1: [u8; 16],
26 m2: [u8; 32],
27 m3: [u8; 16],
28 m4: [u8; 32],
29 m5: [u8; 16],
30}
31
32impl MemUpdate {
33 pub fn new(
34 key_auth: &[u8; 16],
35 key_new: &[u8; 16],
36 counter: u32,
37 she_id: u8,
38 auth_id: u8,
39 uid: &[u8],
40 key_flags: &[KeyFlag],
41 ) -> Self {
42 let k1: [u8; 16] = kdf(key_auth, &KEY_UPDATE_ENC_C[0..6]);
43 let k2: [u8; 16] = kdf(key_auth, &KEY_UPDATE_MAC_C[0..6]);
44 let k3: [u8; 16] = kdf(key_new, &KEY_UPDATE_ENC_C[0..6]);
45 let k4: [u8; 16] = kdf(key_new, &KEY_UPDATE_MAC_C[0..6]);
46 let mut m1: [u8; 16] = [0; 16];
47 let iv: [u8; 16] = [0; 16];
48 let mut m2_raw: [u8; 32] = [0; 32];
49
50 for (i, byte) in uid.iter().enumerate() {
52 m1[i] = *byte;
53 }
54
55 m1[15] = (she_id << 4) | (auth_id & 0x0F);
56 let counter_bytes: [u8; 4] = (counter << 4).to_be_bytes();
60
61 for (i, byte) in counter_bytes.iter().enumerate() {
62 m2_raw[i] = *byte;
63 }
64 let mut flag_byte: u8 = 0x00;
65
66 for flag in key_flags {
67 flag_byte |= *flag as u8;
68 }
69
70 m2_raw[3] |= flag_byte >> 1;
71
72 m2_raw[4] = flag_byte << 7;
74
75 for (i, byte) in key_new.iter().enumerate() {
78 m2_raw[i + 16] = *byte;
79 }
80
81
82 let m2: [u8; 32] = aes_cbc_enc(&m2_raw, &k1, &iv, &AesType::AES128)
83 .try_into()
84 .unwrap();
85 let mut m3_raw: Vec<u8> = m1.to_vec();
89 m3_raw.append(&mut m2.to_vec());
90 let m3: [u8; 16] = cmac(&m3_raw, &k2, &AesType::AES128).try_into().unwrap();
91 let mut m4: Vec<u8> = m1.to_vec();
95 let mut m4_star_raw: [u8; 16] = [0; 16];
96 for (i, byte) in counter_bytes.iter().enumerate() {
97 m4_star_raw[i] = *byte;
98 }
99 m4_star_raw[3] |= 0x08;
100
101 let mut m4_star: Vec<u8> = aes_ecb_enc(&m4_star_raw, &k3, &AesType::AES128);
102 m4.append(&mut m4_star);
103 let m4: [u8; 32] = m4.try_into().unwrap();
104 let m5: [u8; 16] = cmac(&m4, &k4, &AesType::AES128).try_into().unwrap();
108 MemUpdate {
111 k1,
112 k2,
113 k3,
114 k4,
115 m1,
116 m2,
117 m3,
118 m4,
119 m5,
120 }
121 }
122}
123
124fn kdf(k: &[u8], c: &[u8]) -> [u8; 16] {
125 let mut msg: Vec<u8> = k.to_vec();
126 msg.append(&mut c.to_vec());
127 mp_compression(&msg)
128}
129
130#[cfg(test)]
131mod mem_update_tests {
132 use super::*;
133 #[test]
134 fn mem_update_test() {
135 let key_new: [u8; 16] = [
136 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
137 0x01, 0x00,
138 ];
139
140 let key_auth: [u8; 16] = [
141 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
142 0x0e, 0x0f,
143 ];
144
145 let uid: [u8; 15] = [
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x01,
148 ];
149 let she_id: u8 = 4;
150
151 let auth_id: u8 = 1;
152 let counter: u32 = 1;
153 let key_flags: Vec<KeyFlag> = vec![KeyFlag::FlagUnset];
154
155 let mem_update: MemUpdate = MemUpdate::new(
156 &key_auth, &key_new, counter, she_id, auth_id, &uid, &key_flags,
157 );
158 dbg!(&mem_update);
159 }
160}