1 /* $OpenBSD: sm4.c,v 1.2 2023/07/07 12:01:32 beck 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 102 rotl(uint32_t a, uint8_t n) 103 { 104 return (a << n) | (a >> (32 - n)); 105 } 106 107 static inline uint32_t 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 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 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 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 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 LCRYPTO_ALIAS(SM4_set_key); 203 204 #define SM4_ROUNDS(k0, k1, k2, k3, F) \ 205 do { \ 206 B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \ 207 B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \ 208 B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \ 209 B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \ 210 } while(0) 211 212 void 213 SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k) 214 { 215 struct sm4_key *ks = (struct sm4_key *)k; 216 uint32_t B0 = load_u32_be(in, 0); 217 uint32_t B1 = load_u32_be(in, 1); 218 uint32_t B2 = load_u32_be(in, 2); 219 uint32_t B3 = load_u32_be(in, 3); 220 221 /* 222 * Uses byte-wise sbox in the first and last rounds to provide some 223 * protection from cache based side channels. 224 */ 225 SM4_ROUNDS( 0, 1, 2, 3, SM4_T_slow); 226 SM4_ROUNDS( 4, 5, 6, 7, SM4_T); 227 SM4_ROUNDS( 8, 9, 10, 11, SM4_T); 228 SM4_ROUNDS(12, 13, 14, 15, SM4_T); 229 SM4_ROUNDS(16, 17, 18, 19, SM4_T); 230 SM4_ROUNDS(20, 21, 22, 23, SM4_T); 231 SM4_ROUNDS(24, 25, 26, 27, SM4_T); 232 SM4_ROUNDS(28, 29, 30, 31, SM4_T_slow); 233 234 store_u32_be(B3, out); 235 store_u32_be(B2, out + 4); 236 store_u32_be(B1, out + 8); 237 store_u32_be(B0, out + 12); 238 } 239 LCRYPTO_ALIAS(SM4_encrypt); 240 241 void 242 SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k) 243 { 244 struct sm4_key *ks = (struct sm4_key *)k; 245 uint32_t B0 = load_u32_be(in, 0); 246 uint32_t B1 = load_u32_be(in, 1); 247 uint32_t B2 = load_u32_be(in, 2); 248 uint32_t B3 = load_u32_be(in, 3); 249 250 SM4_ROUNDS(31, 30, 29, 28, SM4_T_slow); 251 SM4_ROUNDS(27, 26, 25, 24, SM4_T); 252 SM4_ROUNDS(23, 22, 21, 20, SM4_T); 253 SM4_ROUNDS(19, 18, 17, 16, SM4_T); 254 SM4_ROUNDS(15, 14, 13, 12, SM4_T); 255 SM4_ROUNDS(11, 10, 9, 8, SM4_T); 256 SM4_ROUNDS( 7, 6, 5, 4, SM4_T); 257 SM4_ROUNDS( 3, 2, 1, 0, SM4_T_slow); 258 259 store_u32_be(B3, out); 260 store_u32_be(B2, out + 4); 261 store_u32_be(B1, out + 8); 262 store_u32_be(B0, out + 12); 263 } 264 LCRYPTO_ALIAS(SM4_decrypt); 265 266 #endif /* OPENSSL_NO_SM4 */ 267