neo_crypto/
mem_update.rs

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        // generate M1 begin
51        for (i, byte) in uid.iter().enumerate() {
52            m1[i] = *byte;
53        }
54
55        m1[15] = (she_id << 4) | (auth_id & 0x0F);
56        // generate M1 end
57
58        // generate M2 begin
59        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        // last bit in key_flag and seven bits "0"
73        m2_raw[4] = flag_byte << 7;
74
75        // rest of 88 bits (95-7) "0" already been filled
76
77        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        // generate M2 end
86
87        // generate M3 begin
88        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        // generate M3 end
92
93        // generate M4 begin
94        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        // generate M4 end 
105
106        // generate M5 begin
107        let m5: [u8; 16] = cmac(&m4, &k4, &AesType::AES128).try_into().unwrap();
108        // generate M5 end
109
110        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}