eva_crypto/
sm4.rs

1use super::generic::{create_u8x4, create_u8x4x4, u8x4, u8x4_to_u32, u8x4x4, Ops, Permutation};
2
3pub struct SM4 {
4    pub round_keys: Vec<u8x4>,
5}
6
7type SM4state = u8x4x4;
8
9impl SM4 {
10    pub fn new(key: &[u8]) -> SM4 {
11        let mut round_keys = vec![[0; 4]; 32];
12        key_expansion(key, &mut round_keys);
13        SM4 { round_keys }
14    }
15
16    pub fn encrypt(self, data: &[u8]) -> Vec<u8> {
17        let mut state = create_u8x4x4(data);
18        for i in 0..32 {
19            let new = round_function(&state, &self.round_keys[i]);
20            state = [state[1], state[2], state[3], new];
21        }
22        reverse(&state).concat()
23    }
24    pub fn decrypt(self, data: &[u8]) -> Vec<u8> {
25        let mut state = reverse(&create_u8x4x4(data));
26        for i in (0..32).rev() {
27            println!("{:x?}", state);
28            let new = inv_round_function(&state, &self.round_keys[i]);
29            state = [new, state[0], state[1], state[2]];
30        }
31        state.concat()
32    }
33}
34
35fn key_expansion(key: &[u8], round_keys: &mut [u8x4]) {
36    let mut reg = create_u8x4x4(key).xor(&[
37        create_u8x4(FK[0]),
38        create_u8x4(FK[1]),
39        create_u8x4(FK[2]),
40        create_u8x4(FK[3]),
41    ]);
42    for i in 0..32 {
43        let rk = reg[0].xor(&lprime_substitution(tau_substitution(
44            reg[1].xor(&reg[2].xor(&reg[3].xor(&create_u8x4(CK[i])))),
45        )));
46        round_keys[i] = rk;
47        reg = [reg[1], reg[2], reg[3], rk];
48    }
49}
50
51fn reverse(input: &SM4state) -> SM4state {
52    [input[3], input[2], input[1], input[0]]
53}
54
55fn round_function(input: &[u8x4], round_key: &u8x4) -> u8x4 {
56    let (x0, x1, x2, x3) = (input[0], input[1], input[2], input[3]);
57    x0.xor(&l_substitution(tau_substitution(
58        x1.xor(&x2.xor(&x3.xor(&round_key))),
59    )))
60}
61
62fn inv_round_function(input: &[u8x4], round_key: &u8x4) -> u8x4 {
63    let (x3, x2, x1, x0) = (input[0], input[1], input[2], input[3]);
64    x0.xor(&l_substitution(tau_substitution(
65        x1.xor(&x2.xor(&x3.xor(&round_key))),
66    )))
67}
68
69fn tau_substitution(input: u8x4) -> u8x4 {
70    input.sub_sbox(&SBOX)
71}
72fn l_substitution(input: u8x4) -> u8x4 {
73    let word = u8x4_to_u32(input);
74    create_u8x4(
75        word ^ word.rotate_left(2)
76            ^ word.rotate_left(10)
77            ^ word.rotate_left(18)
78            ^ word.rotate_left(24),
79    )
80}
81
82fn lprime_substitution(input: u8x4) -> u8x4 {
83    let word = u8x4_to_u32(input);
84    create_u8x4(word ^ (word.rotate_left(13)) ^ (word.rotate_left(23)))
85}
86
87pub static SBOX: [u8; 256] = [
88    0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
89    0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
90    0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
91    0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
92    0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
93    0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
94    0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
95    0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
96    0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
97    0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
98    0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
99    0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
100    0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
101    0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
102    0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
103    0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
104];
105
106pub static FK: [u32; 4] = [0xa3b1_bac6, 0x56aa_3350, 0x677d_9197, 0xb270_22dc];
107
108pub static CK: [u32; 32] = [
109    0x0007_0E15,
110    0x1C23_2A31,
111    0x383F_464D,
112    0x545B_6269,
113    0x7077_7E85,
114    0x8C93_9AA1,
115    0xA8AF_B6BD,
116    0xC4CB_D2D9,
117    0xE0E7_EEF5,
118    0xFC03_0A11,
119    0x181F_262D,
120    0x343B_4249,
121    0x5057_5E65,
122    0x6C73_7A81,
123    0x888F_969D,
124    0xA4AB_B2B9,
125    0xC0C7_CED5,
126    0xDCE3_EAF1,
127    0xF8FF_060D,
128    0x141B_2229,
129    0x3037_3E45,
130    0x4C53_5A61,
131    0x686F_767D,
132    0x848B_9299,
133    0xA0A7_AEB5,
134    0xBCC3_CAD1,
135    0xD8DF_E6ED,
136    0xF4FB_0209,
137    0x1017_1E25,
138    0x2C33_3A41,
139    0x484F_565D,
140    0x646B_7279,
141];