Botan  2.6.0
Crypto and TLS for C++11
sm4.cpp
Go to the documentation of this file.
1 /*
2 * SM4
3 * (C) 2017 Ribose Inc
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/sm4.h>
9 #include <botan/loadstor.h>
10 
11 namespace Botan {
12 
13 namespace {
14 
15 const uint8_t SM4_SBOX[256] = {
16 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
17 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
18 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
19 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,
20 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,
21 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
22 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,
23 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,
24 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
25 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,
26 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,
27 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
28 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8,
29 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0,
30 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
31 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48
32 };
33 
34 /*
35 * SM4_SBOX_T[j] == L(SM4_SBOX[j]).
36 */
37 const uint32_t SM4_SBOX_T[256] = {
38  0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
39  0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
40  0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
41  0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
42  0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
43  0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
44  0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
45  0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
46  0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
47  0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
48  0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
49  0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
50  0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
51  0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
52  0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
53  0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
54  0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
55  0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
56  0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
57  0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
58  0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
59  0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
60  0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
61  0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
62  0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
63  0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
64  0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
65  0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
66  0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
67  0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
68  0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
69  0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
70  0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
71  0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
72  0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
73  0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
74  0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
75  0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
76  0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
77  0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
78  0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
79  0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
80  0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 };
81 
82 inline uint32_t SM4_T_slow(uint32_t b)
83  {
84  const uint32_t t = make_uint32(SM4_SBOX[get_byte(0,b)],
85  SM4_SBOX[get_byte(1,b)],
86  SM4_SBOX[get_byte(2,b)],
87  SM4_SBOX[get_byte(3,b)]);
88 
89  // L linear transform
90  return t ^ rotl<2>(t) ^ rotl<10>(t) ^ rotl<18>(t) ^ rotl<24>(t);
91  }
92 
93 inline uint32_t SM4_T(uint32_t b)
94  {
95  return SM4_SBOX_T[get_byte(0,b)] ^
96  rotr< 8>(SM4_SBOX_T[get_byte(1,b)]) ^
97  rotr<16>(SM4_SBOX_T[get_byte(2,b)]) ^
98  rotr<24>(SM4_SBOX_T[get_byte(3,b)]);
99  }
100 
101 // Variant of T for key schedule
102 inline uint32_t SM4_Tp(uint32_t b)
103  {
104  const uint32_t t = make_uint32(SM4_SBOX[get_byte(0,b)],
105  SM4_SBOX[get_byte(1,b)],
106  SM4_SBOX[get_byte(2,b)],
107  SM4_SBOX[get_byte(3,b)]);
108 
109  // L' linear transform
110  return t ^ rotl<13>(t) ^ rotl<23>(t);
111  }
112 
113 #define SM4_RNDS(k0,k1,k2,k3,F) do { \
114  B0 ^= F(B1 ^ B2 ^ B3 ^ m_RK[k0]); \
115  B1 ^= F(B0 ^ B2 ^ B3 ^ m_RK[k1]); \
116  B2 ^= F(B0 ^ B1 ^ B3 ^ m_RK[k2]); \
117  B3 ^= F(B0 ^ B1 ^ B2 ^ m_RK[k3]); \
118  } while(0)
119 
120 }
121 
122 /*
123 * SM4 Encryption
124 */
125 void SM4::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
126  {
127  verify_key_set(m_RK.empty() == false);
128 
129  for(size_t i = 0; i != blocks; ++i)
130  {
131  uint32_t B0 = load_be<uint32_t>(in, 0);
132  uint32_t B1 = load_be<uint32_t>(in, 1);
133  uint32_t B2 = load_be<uint32_t>(in, 2);
134  uint32_t B3 = load_be<uint32_t>(in, 3);
135 
136  SM4_RNDS( 0, 1, 2, 3, SM4_T_slow);
137  SM4_RNDS( 4, 5, 6, 7, SM4_T);
138  SM4_RNDS( 8, 9, 10, 11, SM4_T);
139  SM4_RNDS(12, 13, 14, 15, SM4_T);
140  SM4_RNDS(16, 17, 18, 19, SM4_T);
141  SM4_RNDS(20, 21, 22, 23, SM4_T);
142  SM4_RNDS(24, 25, 26, 27, SM4_T);
143  SM4_RNDS(28, 29, 30, 31, SM4_T_slow);
144 
145  store_be(out, B3, B2, B1, B0);
146 
147  in += BLOCK_SIZE;
148  out += BLOCK_SIZE;
149  }
150  }
151 
152 /*
153 * SM4 Decryption
154 */
155 void SM4::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
156  {
157  verify_key_set(m_RK.empty() == false);
158 
159  for(size_t i = 0; i != blocks; ++i)
160  {
161  uint32_t B0 = load_be<uint32_t>(in, 0);
162  uint32_t B1 = load_be<uint32_t>(in, 1);
163  uint32_t B2 = load_be<uint32_t>(in, 2);
164  uint32_t B3 = load_be<uint32_t>(in, 3);
165 
166  SM4_RNDS(31, 30, 29, 28, SM4_T_slow);
167  SM4_RNDS(27, 26, 25, 24, SM4_T);
168  SM4_RNDS(23, 22, 21, 20, SM4_T);
169  SM4_RNDS(19, 18, 17, 16, SM4_T);
170  SM4_RNDS(15, 14, 13, 12, SM4_T);
171  SM4_RNDS(11, 10, 9, 8, SM4_T);
172  SM4_RNDS( 7, 6, 5, 4, SM4_T);
173  SM4_RNDS( 3, 2, 1, 0, SM4_T_slow);
174 
175  store_be(out, B3, B2, B1, B0);
176 
177  in += BLOCK_SIZE;
178  out += BLOCK_SIZE;
179  }
180  }
181 
182 #undef SM4_RNDS
183 
184 /*
185 * SM4 Key Schedule
186 */
187 void SM4::key_schedule(const uint8_t key[], size_t)
188  {
189  // System parameter or family key
190  const uint32_t FK[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
191 
192  const uint32_t CK[32] = {
193  0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
194  0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
195  0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
196  0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
197  0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
198  0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
199  0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
200  0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
201  };
202 
203  secure_vector<uint32_t> K(4);
204  K[0] = load_be<uint32_t>(key, 0) ^ FK[0];
205  K[1] = load_be<uint32_t>(key, 1) ^ FK[1];
206  K[2] = load_be<uint32_t>(key, 2) ^ FK[2];
207  K[3] = load_be<uint32_t>(key, 3) ^ FK[3];
208 
209  m_RK.resize(32);
210  for(size_t i = 0; i != 32; ++i)
211  {
212  K[i % 4] ^= SM4_Tp(K[(i+1)%4] ^ K[(i+2)%4] ^ K[(i+3)%4] ^ CK[i]);
213  m_RK[i] = K[i % 4];
214  }
215  }
216 
218  {
219  zap(m_RK);
220  }
221 
222 }
#define SM4_RNDS(k0, k1, k2, k3, F)
Definition: sm4.cpp:113
void verify_key_set(bool cond) const
Definition: sym_algo.h:95
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:193
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:434
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:177
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: sm4.cpp:125
Definition: alg_id.cpp:13
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: sm4.cpp:155
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
void clear() override
Definition: sm4.cpp:217
uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition: loadstor.h:65