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(®[2].xor(®[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];