Coverage Report

Created: 2026-07-12 07:21

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
27.8M
{
91
27.8M
    return (a << n) | (a >> (32 - n));
92
27.8M
}
93
94
static ossl_inline uint32_t load_u32_be(const uint8_t *b, uint32_t n)
95
3.47M
{
96
3.47M
    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
3.47M
}
98
99
static ossl_inline void store_u32_be(uint32_t v, uint8_t *b)
100
3.47M
{
101
3.47M
    b[0] = (uint8_t)(v >> 24);
102
3.47M
    b[1] = (uint8_t)(v >> 16);
103
3.47M
    b[2] = (uint8_t)(v >> 8);
104
3.47M
    b[3] = (uint8_t)(v);
105
3.47M
}
106
107
static ossl_inline uint32_t SM4_T_slow(uint32_t X)
108
6.95M
{
109
6.95M
    uint32_t t = 0;
110
111
6.95M
    t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
112
6.95M
    t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
113
6.95M
    t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
114
6.95M
    t |= SM4_S[(uint8_t)X];
115
116
    /*
117
     * L linear transform
118
     */
119
6.95M
    return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24);
120
6.95M
}
121
122
static ossl_inline uint32_t SM4_T(uint32_t X)
123
20.8M
{
124
20.8M
    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
20.8M
}
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
6.95M
    do {                                    \
175
6.95M
        B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \
176
6.95M
        B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \
177
6.95M
        B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \
178
6.95M
        B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \
179
6.95M
    } while (0)
180
181
void ossl_sm4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
182
869k
{
183
869k
    uint32_t B0 = load_u32_be(in, 0);
184
869k
    uint32_t B1 = load_u32_be(in, 1);
185
869k
    uint32_t B2 = load_u32_be(in, 2);
186
869k
    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
869k
    SM4_RNDS(0, 1, 2, 3, SM4_T_slow);
193
869k
    SM4_RNDS(4, 5, 6, 7, SM4_T);
194
869k
    SM4_RNDS(8, 9, 10, 11, SM4_T);
195
869k
    SM4_RNDS(12, 13, 14, 15, SM4_T);
196
869k
    SM4_RNDS(16, 17, 18, 19, SM4_T);
197
869k
    SM4_RNDS(20, 21, 22, 23, SM4_T);
198
869k
    SM4_RNDS(24, 25, 26, 27, SM4_T);
199
869k
    SM4_RNDS(28, 29, 30, 31, SM4_T_slow);
200
201
869k
    store_u32_be(B3, out);
202
869k
    store_u32_be(B2, out + 4);
203
869k
    store_u32_be(B1, out + 8);
204
869k
    store_u32_be(B0, out + 12);
205
869k
}
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
}