gm_zuc/
eia.rs

1use crate::ZUC;
2
3#[derive(Debug)]
4pub struct EIA {
5    zuc: ZUC,
6}
7
8impl EIA {
9    pub fn new(ik: &[u8], count: u32, bearer: u32, direction: u32) -> EIA {
10        let mut iv = [0u8; 16];
11        iv[0] = (count >> 24) as u8;
12        iv[1] = (count >> 16) as u8;
13        iv[2] = (count >> 8) as u8;
14        iv[3] = count as u8;
15        iv[4] = (bearer << 3) as u8;
16
17        iv[8] = iv[0] ^ ((direction << 7) as u8);
18        iv[9] = iv[1];
19        iv[10] = iv[2];
20        iv[11] = iv[3];
21        iv[12] = iv[4];
22        iv[14] = iv[6] ^ ((direction << 7) as u8);
23        EIA {
24            zuc: ZUC::new(ik, &iv),
25        }
26    }
27
28    /// Return MAC
29    pub fn gen_mac(&mut self, m: &[u32], ilen: u32) -> u32 {
30        let keylength = (ilen + 31) / 32 + 2;
31        let keys = self.zuc.generate_keystream(keylength as usize);
32        let keys = keys.as_slice();
33        let mut t = 0_u32;
34        for i in 0..ilen as usize {
35            if m[i >> 5] & (0x1 << (31 - (i & 0x1f))) > 0 {
36                t ^= find_word(keys, i);
37            }
38        }
39
40        t ^= find_word(keys, ilen as usize);
41        t ^ find_word(keys, 32 * (keylength - 1) as usize)
42    }
43}
44
45/// Return
46/// ```txt
47/// K_i = K[i] || K[i+1] || ... || K[i+31]
48/// ```
49fn find_word(keys: &[u32], i: usize) -> u32 {
50    let j = i >> 5;
51    let m = i & 0x1f;
52    if m == 0 {
53        keys[j]
54    } else {
55        (keys[j] << m) | (keys[j + 1] >> (32 - m))
56    }
57}
58
59#[cfg(test)]
60mod eia_test {
61    use crate::eia::EIA;
62
63    #[test]
64    pub fn test_eia() {
65        let ik: [u8; 16] = [
66            0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb, 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85,
67            0xab, 0x0a,
68        ];
69
70        let count = 0xa94059da_u32;
71        let bearer = 0x0a_u32;
72        let direction = 0x01_u32;
73        let length = 0x0241_u32;
74
75        let m: [u32; 19] = [
76            0x983b41d4, 0x7d780c9e, 0x1ad11d7e, 0xb70391b1, 0xde0b35da, 0x2dc62f83, 0xe7b78d63,
77            0x06ca0ea0, 0x7e941b7b, 0xe91348f9, 0xfcb170e2, 0x217fecd9, 0x7f9f68ad, 0xb16e5d7d,
78            0x21e569d2, 0x80ed775c, 0xebde3f40, 0x93c53881, 0x00000000,
79        ];
80
81        let mac = 0xfae8ff0b_u32;
82
83        let mut eia = EIA::new(&ik, count, bearer, direction);
84        let rs = eia.gen_mac(&m, length);
85        assert_eq!(mac, rs)
86    }
87}