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