1 /* $OpenBSD: sm4.c,v 1.6 2025/01/22 09:53:16 jsing Exp $ */
2 /*
3 * Copyright (c) 2017, 2019 Ribose Inc
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <openssl/opensslconf.h>
19
20 #ifndef OPENSSL_NO_SM4
21 #include <openssl/sm4.h>
22
23 #include "crypto_internal.h"
24
25 struct sm4_key {
26 uint32_t rk[SM4_KEY_SCHEDULE];
27 };
28
29 static const uint8_t SM4_S[256] = {
30 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2,
31 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
32 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4,
33 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
34 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA,
35 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
36 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2,
37 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
38 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B,
39 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
40 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2,
41 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
42 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30,
43 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
44 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45,
45 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
46 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41,
47 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
48 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A,
49 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
50 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E,
51 0xD7, 0xCB, 0x39, 0x48,
52 };
53
54 /*
55 * SM4_SBOX_T[j] == L(SM4_SBOX[j]).
56 */
57 static const uint32_t SM4_SBOX_T[256] = {
58 0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
59 0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
60 0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
61 0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
62 0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
63 0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
64 0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
65 0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
66 0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
67 0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
68 0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
69 0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
70 0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
71 0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
72 0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
73 0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
74 0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
75 0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
76 0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
77 0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
78 0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
79 0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
80 0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
81 0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
82 0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
83 0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
84 0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
85 0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
86 0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
87 0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
88 0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
89 0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
90 0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
91 0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
92 0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
93 0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
94 0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
95 0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
96 0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
97 0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
98 0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
99 0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
100 0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121,
101 };
102
103 static inline uint32_t
SM4_T_slow(uint32_t X)104 SM4_T_slow(uint32_t X)
105 {
106 uint32_t t = 0;
107
108 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
109 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
110 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
111 t |= SM4_S[(uint8_t)X];
112
113 /* L linear transform. */
114 return t ^ crypto_rol_u32(t, 2) ^ crypto_rol_u32(t, 10) ^
115 crypto_rol_u32(t, 18) ^ crypto_rol_u32(t, 24);
116 }
117
118 static inline uint32_t
SM4_T(uint32_t X)119 SM4_T(uint32_t X)
120 {
121 return SM4_SBOX_T[(uint8_t)(X >> 24)] ^
122 crypto_rol_u32(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^
123 crypto_rol_u32(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^
124 crypto_rol_u32(SM4_SBOX_T[(uint8_t)X], 8);
125 }
126
127 /*
128 * SM4 Family Key
129 */
130 static const uint32_t SM4_FK[4] = {
131 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
132 };
133
134 /*
135 * SM4 Constant Key
136 */
137 static const uint32_t SM4_CK[32] = {
138 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
139 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
140 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
141 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
142 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
143 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
144 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
145 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279,
146 };
147
148 int
SM4_set_key(const uint8_t * key,SM4_KEY * k)149 SM4_set_key(const uint8_t *key, SM4_KEY *k)
150 {
151 struct sm4_key *ks = (struct sm4_key *)k;
152 uint32_t K[4];
153 int i;
154
155 K[0] = crypto_load_be32toh(&key[0 * 4]) ^ SM4_FK[0];
156 K[1] = crypto_load_be32toh(&key[1 * 4]) ^ SM4_FK[1];
157 K[2] = crypto_load_be32toh(&key[2 * 4]) ^ SM4_FK[2];
158 K[3] = crypto_load_be32toh(&key[3 * 4]) ^ SM4_FK[3];
159
160 for (i = 0; i < SM4_KEY_SCHEDULE; i++) {
161 uint32_t X;
162 uint32_t t = 0;
163
164 X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ SM4_CK[i];
165
166 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
167 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
168 t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
169 t |= SM4_S[(uint8_t)X];
170
171 t = t ^ crypto_rol_u32(t, 13) ^ crypto_rol_u32(t, 23);
172 K[i % 4] ^= t;
173 ks->rk[i] = K[i % 4];
174 }
175
176 return 1;
177 }
178 LCRYPTO_ALIAS(SM4_set_key);
179
180 void
SM4_encrypt(const uint8_t * in,uint8_t * out,const SM4_KEY * k)181 SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k)
182 {
183 struct sm4_key *ks = (struct sm4_key *)k;
184 uint32_t B0, B1, B2, B3;
185
186 B0 = crypto_load_be32toh(&in[0 * 4]);
187 B1 = crypto_load_be32toh(&in[1 * 4]);
188 B2 = crypto_load_be32toh(&in[2 * 4]);
189 B3 = crypto_load_be32toh(&in[3 * 4]);
190
191 /*
192 * Uses byte-wise sbox in the first and last rounds to provide some
193 * protection from cache based side channels.
194 */
195 B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[0]);
196 B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[1]);
197 B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[2]);
198 B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[3]);
199
200 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[4]);
201 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[5]);
202 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[6]);
203 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[7]);
204
205 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[8]);
206 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[9]);
207 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[10]);
208 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[11]);
209
210 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[12]);
211 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[13]);
212 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[14]);
213 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[15]);
214
215 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[16]);
216 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[17]);
217 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[18]);
218 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[19]);
219
220 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[20]);
221 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[21]);
222 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[22]);
223 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[23]);
224
225 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[24]);
226 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[25]);
227 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[26]);
228 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[27]);
229
230 B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[28]);
231 B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[29]);
232 B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[30]);
233 B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[31]);
234
235 crypto_store_htobe32(&out[0 * 4], B3);
236 crypto_store_htobe32(&out[1 * 4], B2);
237 crypto_store_htobe32(&out[2 * 4], B1);
238 crypto_store_htobe32(&out[3 * 4], B0);
239 }
240 LCRYPTO_ALIAS(SM4_encrypt);
241
242 void
SM4_decrypt(const uint8_t * in,uint8_t * out,const SM4_KEY * k)243 SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k)
244 {
245 struct sm4_key *ks = (struct sm4_key *)k;
246 uint32_t B0, B1, B2, B3;
247
248 B0 = crypto_load_be32toh(&in[0 * 4]);
249 B1 = crypto_load_be32toh(&in[1 * 4]);
250 B2 = crypto_load_be32toh(&in[2 * 4]);
251 B3 = crypto_load_be32toh(&in[3 * 4]);
252
253 /*
254 * Uses byte-wise sbox in the first and last rounds to provide some
255 * protection from cache based side channels.
256 */
257 B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[31]);
258 B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[30]);
259 B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[29]);
260 B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[28]);
261
262 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[27]);
263 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[26]);
264 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[25]);
265 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[24]);
266
267 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[23]);
268 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[22]);
269 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[21]);
270 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[20]);
271
272 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[19]);
273 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[18]);
274 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[17]);
275 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[16]);
276
277 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[15]);
278 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[14]);
279 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[13]);
280 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[12]);
281
282 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[11]);
283 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[10]);
284 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[9]);
285 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[8]);
286
287 B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[7]);
288 B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[6]);
289 B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[5]);
290 B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[4]);
291
292 B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[3]);
293 B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[2]);
294 B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[1]);
295 B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[0]);
296
297 crypto_store_htobe32(&out[0 * 4], B3);
298 crypto_store_htobe32(&out[1 * 4], B2);
299 crypto_store_htobe32(&out[2 * 4], B1);
300 crypto_store_htobe32(&out[3 * 4], B0);
301 }
302 LCRYPTO_ALIAS(SM4_decrypt);
303
304 #endif /* OPENSSL_NO_SM4 */
305