Coverage Report

Created: 2025-12-31 06:58

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