Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-math-all/wolfcrypt/src/sm4.c
Line
Count
Source
1
/* sm4.c
2
 *
3
 * Copyright (C) 2006-2024 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
/* For more info on the algorithm, see:
23
 *  https://datatracker.ietf.org/doc/html/draft-ribose-cfrg-sm4
24
 */
25
26
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
27
28
#ifdef WOLFSSL_SM4
29
30
#include <wolfssl/wolfcrypt/sm4.h>
31
#ifdef WOLF_CRYPTO_CB_SM
32
    #include <wolfssl/wolfcrypt/cryptocb.h>
33
#endif
34
35
#ifdef NO_INLINE
36
    #include <wolfssl/wolfcrypt/misc.h>
37
#else
38
    #define WOLFSSL_MISC_INCLUDED
39
    #include <wolfcrypt/src/misc.c>
40
#endif
41
42
43
#ifdef LITTLE_ENDIAN_ORDER
44
45
/* Load unsigned 32-bit word from big-endian byte array.
46
 *
47
 * @param [in] b  Byte array with big-endian data.
48
 * @return  Unsigned 32-bit word.
49
 */
50
#define LOAD_U32_BE(b, v0, v1, v2, v3)  \
51
0
    XMEMCPY(&v0, b +  0, sizeof(v0));   \
52
0
    XMEMCPY(&v1, b +  4, sizeof(v1));   \
53
0
    XMEMCPY(&v2, b +  8, sizeof(v2));   \
54
0
    XMEMCPY(&v3, b + 12, sizeof(v3));   \
55
0
    v0 = ByteReverseWord32(v0);         \
56
0
    v1 = ByteReverseWord32(v1);         \
57
0
    v2 = ByteReverseWord32(v2);         \
58
0
    v3 = ByteReverseWord32(v3)
59
60
/* Store unsigned 32-bit word as big-endian byte array.
61
 *
62
 * @param [in]  v  Unsigned 32-bit value.
63
 * @param [out] b  Byte array to hold big-endian data.
64
 */
65
#define STORE_U32_BE(v0, v1, v2, v3, b) \
66
0
    v0 = ByteReverseWord32(v0);         \
67
0
    v1 = ByteReverseWord32(v1);         \
68
0
    v2 = ByteReverseWord32(v2);         \
69
0
    v3 = ByteReverseWord32(v3);         \
70
0
    XMEMCPY(b +  0, &v3, sizeof(v3));   \
71
0
    XMEMCPY(b +  4, &v2, sizeof(v2));   \
72
0
    XMEMCPY(b +  8, &v1, sizeof(v1));   \
73
0
    XMEMCPY(b + 12, &v0, sizeof(v0))
74
75
#else
76
77
/* Load unsigned 32-bit word from big-endian byte array.
78
 *
79
 * @param [in] b  Byte array with big-endian data.
80
 * @return  Unsigned 32-bit word.
81
 */
82
#define LOAD_U32_BE(b, v0, v1, v2, v3)  \
83
    XMEMCPY(&v0, b +  0, sizeof(v0));   \
84
    XMEMCPY(&v1, b +  4, sizeof(v1));   \
85
    XMEMCPY(&v2, b +  8, sizeof(v2));   \
86
    XMEMCPY(&v3, b + 12, sizeof(v3))
87
88
/* Store unsigned 32-bit word as big-endian byte array.
89
 *
90
 * @param [in]  v  Unsigned 32-bit value.
91
 * @param [out] b  Byte array to hold big-endian data.
92
 */
93
#define STORE_U32_BE(v0, v1, v2, v3, b) \
94
    XMEMCPY(b +  0, &v3, sizeof(v3));   \
95
    XMEMCPY(b +  4, &v2, sizeof(v2));   \
96
    XMEMCPY(b +  8, &v1, sizeof(v1));   \
97
    XMEMCPY(b + 12, &v0, sizeof(v0))
98
99
#endif
100
101
102
/* Constant key values used in creating key schedule. */
103
static word32 sm4_ck[32] = {
104
    0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
105
    0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
106
    0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
107
    0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
108
    0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
109
    0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
110
    0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
111
    0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
112
};
113
114
/* Family key values used in creating key schedule. */
115
static word32 sm4_fk[4] = {
116
    0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC
117
};
118
119
120
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM4)
121
122
/* S-box used in nonlinear transformation tau. */
123
static byte sm4_sbox[256] = {
124
    0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,
125
    0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
126
    0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
127
    0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
128
    0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A,
129
    0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
130
    0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95,
131
    0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,
132
    0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
133
    0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,
134
    0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B,
135
    0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
136
    0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2,
137
    0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,
138
    0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
139
    0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,
140
    0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5,
141
    0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
142
    0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,
143
    0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,
144
    0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
145
    0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,
146
    0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F,
147
    0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
148
    0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F,
149
    0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8,
150
    0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
151
    0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0,
152
    0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,
153
    0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
154
    0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,
155
    0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48
156
};
157
158
#ifndef WOLFSSL_SM4_SMALL
159
160
/* S-boxes used in nonlinear transformation tau.
161
 * Linear transformation applied to each byte.
162
 *
163
 * Generated using script: ruby scripts/sm4/tables.rb
164
 */
165
static const word32 sm4_sbox_0[256] = {
166
    0xd55b5b8e, 0x924242d0, 0xeaa7a74d, 0xfdfbfb06, 0xcf3333fc, 0xe2878765,
167
    0x3df4f4c9, 0xb5dede6b, 0x1658584e, 0xb4dada6e, 0x14505044, 0xc10b0bca,
168
    0x28a0a088, 0xf8efef17, 0x2cb0b09c, 0x05141411, 0x2bacac87, 0x669d9dfb,
169
    0x986a6af2, 0x77d9d9ae, 0x2aa8a882, 0xbcfafa46, 0x04101014, 0xc00f0fcf,
170
    0xa8aaaa02, 0x45111154, 0x134c4c5f, 0x269898be, 0x4825256d, 0x841a1a9e,
171
    0x0618181e, 0x9b6666fd, 0x9e7272ec, 0x4309094a, 0x51414110, 0xf7d3d324,
172
    0x934646d5, 0xecbfbf53, 0x9a6262f8, 0x7be9e992, 0x33ccccff, 0x55515104,
173
    0x0b2c2c27, 0x420d0d4f, 0xeeb7b759, 0xcc3f3ff3, 0xaeb2b21c, 0x638989ea,
174
    0xe7939374, 0xb1cece7f, 0x1c70706c, 0xaba6a60d, 0xca2727ed, 0x08202028,
175
    0xeba3a348, 0x975656c1, 0x82020280, 0xdc7f7fa3, 0x965252c4, 0xf9ebeb12,
176
    0x74d5d5a1, 0x8d3e3eb3, 0x3ffcfcc3, 0xa49a9a3e, 0x461d1d5b, 0x071c1c1b,
177
    0xa59e9e3b, 0xfff3f30c, 0xf0cfcf3f, 0x72cdcdbf, 0x175c5c4b, 0xb8eaea52,
178
    0x810e0e8f, 0x5865653d, 0x3cf0f0cc, 0x1964647d, 0xe59b9b7e, 0x87161691,
179
    0x4e3d3d73, 0xaaa2a208, 0x69a1a1c8, 0x6aadadc7, 0x83060685, 0xb0caca7a,
180
    0x70c5c5b5, 0x659191f4, 0xd96b6bb2, 0x892e2ea7, 0xfbe3e318, 0xe8afaf47,
181
    0x0f3c3c33, 0x4a2d2d67, 0x71c1c1b0, 0x5759590e, 0x9f7676e9, 0x35d4d4e1,
182
    0x1e787866, 0x249090b4, 0x0e383836, 0x5f797926, 0x628d8def, 0x59616138,
183
    0xd2474795, 0xa08a8a2a, 0x259494b1, 0x228888aa, 0x7df1f18c, 0x3bececd7,
184
    0x01040405, 0x218484a5, 0x79e1e198, 0x851e1e9b, 0xd7535384, 0x00000000,
185
    0x4719195e, 0x565d5d0b, 0x9d7e7ee3, 0xd04f4f9f, 0x279c9cbb, 0x5349491a,
186
    0x4d31317c, 0x36d8d8ee, 0x0208080a, 0xe49f9f7b, 0xa2828220, 0xc71313d4,
187
    0xcb2323e8, 0x9c7a7ae6, 0xe9abab42, 0xbdfefe43, 0x882a2aa2, 0xd14b4b9a,
188
    0x41010140, 0xc41f1fdb, 0x38e0e0d8, 0xb7d6d661, 0xa18e8e2f, 0xf4dfdf2b,
189
    0xf1cbcb3a, 0xcd3b3bf6, 0xfae7e71d, 0x608585e5, 0x15545441, 0xa3868625,
190
    0xe3838360, 0xacbaba16, 0x5c757529, 0xa6929234, 0x996e6ef7, 0x34d0d0e4,
191
    0x1a686872, 0x54555501, 0xafb6b619, 0x914e4edf, 0x32c8c8fa, 0x30c0c0f0,
192
    0xf6d7d721, 0x8e3232bc, 0xb3c6c675, 0xe08f8f6f, 0x1d747469, 0xf5dbdb2e,
193
    0xe18b8b6a, 0x2eb8b896, 0x800a0a8a, 0x679999fe, 0xc92b2be2, 0x618181e0,
194
    0xc30303c0, 0x29a4a48d, 0x238c8caf, 0xa9aeae07, 0x0d343439, 0x524d4d1f,
195
    0x4f393976, 0x6ebdbdd3, 0xd6575781, 0xd86f6fb7, 0x37dcdceb, 0x44151551,
196
    0xdd7b7ba6, 0xfef7f709, 0x8c3a3ab6, 0x2fbcbc93, 0x030c0c0f, 0xfcffff03,
197
    0x6ba9a9c2, 0x73c9c9ba, 0x6cb5b5d9, 0x6db1b1dc, 0x5a6d6d37, 0x50454515,
198
    0x8f3636b9, 0x1b6c6c77, 0xadbebe13, 0x904a4ada, 0xb9eeee57, 0xde7777a9,
199
    0xbef2f24c, 0x7efdfd83, 0x11444455, 0xda6767bd, 0x5d71712c, 0x40050545,
200
    0x1f7c7c63, 0x10404050, 0x5b696932, 0xdb6363b8, 0x0a282822, 0xc20707c5,
201
    0x31c4c4f5, 0x8a2222a8, 0xa7969631, 0xce3737f9, 0x7aeded97, 0xbff6f649,
202
    0x2db4b499, 0x75d1d1a4, 0xd3434390, 0x1248485a, 0xbae2e258, 0xe6979771,
203
    0xb6d2d264, 0xb2c2c270, 0x8b2626ad, 0x68a5a5cd, 0x955e5ecb, 0x4b292962,
204
    0x0c30303c, 0x945a5ace, 0x76ddddab, 0x7ff9f986, 0x649595f1, 0xbbe6e65d,
205
    0xf2c7c735, 0x0924242d, 0xc61717d1, 0x6fb9b9d6, 0xc51b1bde, 0x86121294,
206
    0x18606078, 0xf3c3c330, 0x7cf5f589, 0xefb3b35c, 0x3ae8e8d2, 0xdf7373ac,
207
    0x4c353579, 0x208080a0, 0x78e5e59d, 0xedbbbb56, 0x5e7d7d23, 0x3ef8f8c6,
208
    0xd45f5f8b, 0xc82f2fe7, 0x39e4e4dd, 0x49212168,
209
};
210
static const word32 sm4_sbox_1[256] = {
211
    0x5b5b8ed5, 0x4242d092, 0xa7a74dea, 0xfbfb06fd, 0x3333fccf, 0x878765e2,
212
    0xf4f4c93d, 0xdede6bb5, 0x58584e16, 0xdada6eb4, 0x50504414, 0x0b0bcac1,
213
    0xa0a08828, 0xefef17f8, 0xb0b09c2c, 0x14141105, 0xacac872b, 0x9d9dfb66,
214
    0x6a6af298, 0xd9d9ae77, 0xa8a8822a, 0xfafa46bc, 0x10101404, 0x0f0fcfc0,
215
    0xaaaa02a8, 0x11115445, 0x4c4c5f13, 0x9898be26, 0x25256d48, 0x1a1a9e84,
216
    0x18181e06, 0x6666fd9b, 0x7272ec9e, 0x09094a43, 0x41411051, 0xd3d324f7,
217
    0x4646d593, 0xbfbf53ec, 0x6262f89a, 0xe9e9927b, 0xccccff33, 0x51510455,
218
    0x2c2c270b, 0x0d0d4f42, 0xb7b759ee, 0x3f3ff3cc, 0xb2b21cae, 0x8989ea63,
219
    0x939374e7, 0xcece7fb1, 0x70706c1c, 0xa6a60dab, 0x2727edca, 0x20202808,
220
    0xa3a348eb, 0x5656c197, 0x02028082, 0x7f7fa3dc, 0x5252c496, 0xebeb12f9,
221
    0xd5d5a174, 0x3e3eb38d, 0xfcfcc33f, 0x9a9a3ea4, 0x1d1d5b46, 0x1c1c1b07,
222
    0x9e9e3ba5, 0xf3f30cff, 0xcfcf3ff0, 0xcdcdbf72, 0x5c5c4b17, 0xeaea52b8,
223
    0x0e0e8f81, 0x65653d58, 0xf0f0cc3c, 0x64647d19, 0x9b9b7ee5, 0x16169187,
224
    0x3d3d734e, 0xa2a208aa, 0xa1a1c869, 0xadadc76a, 0x06068583, 0xcaca7ab0,
225
    0xc5c5b570, 0x9191f465, 0x6b6bb2d9, 0x2e2ea789, 0xe3e318fb, 0xafaf47e8,
226
    0x3c3c330f, 0x2d2d674a, 0xc1c1b071, 0x59590e57, 0x7676e99f, 0xd4d4e135,
227
    0x7878661e, 0x9090b424, 0x3838360e, 0x7979265f, 0x8d8def62, 0x61613859,
228
    0x474795d2, 0x8a8a2aa0, 0x9494b125, 0x8888aa22, 0xf1f18c7d, 0xececd73b,
229
    0x04040501, 0x8484a521, 0xe1e19879, 0x1e1e9b85, 0x535384d7, 0x00000000,
230
    0x19195e47, 0x5d5d0b56, 0x7e7ee39d, 0x4f4f9fd0, 0x9c9cbb27, 0x49491a53,
231
    0x31317c4d, 0xd8d8ee36, 0x08080a02, 0x9f9f7be4, 0x828220a2, 0x1313d4c7,
232
    0x2323e8cb, 0x7a7ae69c, 0xabab42e9, 0xfefe43bd, 0x2a2aa288, 0x4b4b9ad1,
233
    0x01014041, 0x1f1fdbc4, 0xe0e0d838, 0xd6d661b7, 0x8e8e2fa1, 0xdfdf2bf4,
234
    0xcbcb3af1, 0x3b3bf6cd, 0xe7e71dfa, 0x8585e560, 0x54544115, 0x868625a3,
235
    0x838360e3, 0xbaba16ac, 0x7575295c, 0x929234a6, 0x6e6ef799, 0xd0d0e434,
236
    0x6868721a, 0x55550154, 0xb6b619af, 0x4e4edf91, 0xc8c8fa32, 0xc0c0f030,
237
    0xd7d721f6, 0x3232bc8e, 0xc6c675b3, 0x8f8f6fe0, 0x7474691d, 0xdbdb2ef5,
238
    0x8b8b6ae1, 0xb8b8962e, 0x0a0a8a80, 0x9999fe67, 0x2b2be2c9, 0x8181e061,
239
    0x0303c0c3, 0xa4a48d29, 0x8c8caf23, 0xaeae07a9, 0x3434390d, 0x4d4d1f52,
240
    0x3939764f, 0xbdbdd36e, 0x575781d6, 0x6f6fb7d8, 0xdcdceb37, 0x15155144,
241
    0x7b7ba6dd, 0xf7f709fe, 0x3a3ab68c, 0xbcbc932f, 0x0c0c0f03, 0xffff03fc,
242
    0xa9a9c26b, 0xc9c9ba73, 0xb5b5d96c, 0xb1b1dc6d, 0x6d6d375a, 0x45451550,
243
    0x3636b98f, 0x6c6c771b, 0xbebe13ad, 0x4a4ada90, 0xeeee57b9, 0x7777a9de,
244
    0xf2f24cbe, 0xfdfd837e, 0x44445511, 0x6767bdda, 0x71712c5d, 0x05054540,
245
    0x7c7c631f, 0x40405010, 0x6969325b, 0x6363b8db, 0x2828220a, 0x0707c5c2,
246
    0xc4c4f531, 0x2222a88a, 0x969631a7, 0x3737f9ce, 0xeded977a, 0xf6f649bf,
247
    0xb4b4992d, 0xd1d1a475, 0x434390d3, 0x48485a12, 0xe2e258ba, 0x979771e6,
248
    0xd2d264b6, 0xc2c270b2, 0x2626ad8b, 0xa5a5cd68, 0x5e5ecb95, 0x2929624b,
249
    0x30303c0c, 0x5a5ace94, 0xddddab76, 0xf9f9867f, 0x9595f164, 0xe6e65dbb,
250
    0xc7c735f2, 0x24242d09, 0x1717d1c6, 0xb9b9d66f, 0x1b1bdec5, 0x12129486,
251
    0x60607818, 0xc3c330f3, 0xf5f5897c, 0xb3b35cef, 0xe8e8d23a, 0x7373acdf,
252
    0x3535794c, 0x8080a020, 0xe5e59d78, 0xbbbb56ed, 0x7d7d235e, 0xf8f8c63e,
253
    0x5f5f8bd4, 0x2f2fe7c8, 0xe4e4dd39, 0x21216849,
254
};
255
static const word32 sm4_sbox_2[256] = {
256
    0x5b8ed55b, 0x42d09242, 0xa74deaa7, 0xfb06fdfb, 0x33fccf33, 0x8765e287,
257
    0xf4c93df4, 0xde6bb5de, 0x584e1658, 0xda6eb4da, 0x50441450, 0x0bcac10b,
258
    0xa08828a0, 0xef17f8ef, 0xb09c2cb0, 0x14110514, 0xac872bac, 0x9dfb669d,
259
    0x6af2986a, 0xd9ae77d9, 0xa8822aa8, 0xfa46bcfa, 0x10140410, 0x0fcfc00f,
260
    0xaa02a8aa, 0x11544511, 0x4c5f134c, 0x98be2698, 0x256d4825, 0x1a9e841a,
261
    0x181e0618, 0x66fd9b66, 0x72ec9e72, 0x094a4309, 0x41105141, 0xd324f7d3,
262
    0x46d59346, 0xbf53ecbf, 0x62f89a62, 0xe9927be9, 0xccff33cc, 0x51045551,
263
    0x2c270b2c, 0x0d4f420d, 0xb759eeb7, 0x3ff3cc3f, 0xb21caeb2, 0x89ea6389,
264
    0x9374e793, 0xce7fb1ce, 0x706c1c70, 0xa60daba6, 0x27edca27, 0x20280820,
265
    0xa348eba3, 0x56c19756, 0x02808202, 0x7fa3dc7f, 0x52c49652, 0xeb12f9eb,
266
    0xd5a174d5, 0x3eb38d3e, 0xfcc33ffc, 0x9a3ea49a, 0x1d5b461d, 0x1c1b071c,
267
    0x9e3ba59e, 0xf30cfff3, 0xcf3ff0cf, 0xcdbf72cd, 0x5c4b175c, 0xea52b8ea,
268
    0x0e8f810e, 0x653d5865, 0xf0cc3cf0, 0x647d1964, 0x9b7ee59b, 0x16918716,
269
    0x3d734e3d, 0xa208aaa2, 0xa1c869a1, 0xadc76aad, 0x06858306, 0xca7ab0ca,
270
    0xc5b570c5, 0x91f46591, 0x6bb2d96b, 0x2ea7892e, 0xe318fbe3, 0xaf47e8af,
271
    0x3c330f3c, 0x2d674a2d, 0xc1b071c1, 0x590e5759, 0x76e99f76, 0xd4e135d4,
272
    0x78661e78, 0x90b42490, 0x38360e38, 0x79265f79, 0x8def628d, 0x61385961,
273
    0x4795d247, 0x8a2aa08a, 0x94b12594, 0x88aa2288, 0xf18c7df1, 0xecd73bec,
274
    0x04050104, 0x84a52184, 0xe19879e1, 0x1e9b851e, 0x5384d753, 0x00000000,
275
    0x195e4719, 0x5d0b565d, 0x7ee39d7e, 0x4f9fd04f, 0x9cbb279c, 0x491a5349,
276
    0x317c4d31, 0xd8ee36d8, 0x080a0208, 0x9f7be49f, 0x8220a282, 0x13d4c713,
277
    0x23e8cb23, 0x7ae69c7a, 0xab42e9ab, 0xfe43bdfe, 0x2aa2882a, 0x4b9ad14b,
278
    0x01404101, 0x1fdbc41f, 0xe0d838e0, 0xd661b7d6, 0x8e2fa18e, 0xdf2bf4df,
279
    0xcb3af1cb, 0x3bf6cd3b, 0xe71dfae7, 0x85e56085, 0x54411554, 0x8625a386,
280
    0x8360e383, 0xba16acba, 0x75295c75, 0x9234a692, 0x6ef7996e, 0xd0e434d0,
281
    0x68721a68, 0x55015455, 0xb619afb6, 0x4edf914e, 0xc8fa32c8, 0xc0f030c0,
282
    0xd721f6d7, 0x32bc8e32, 0xc675b3c6, 0x8f6fe08f, 0x74691d74, 0xdb2ef5db,
283
    0x8b6ae18b, 0xb8962eb8, 0x0a8a800a, 0x99fe6799, 0x2be2c92b, 0x81e06181,
284
    0x03c0c303, 0xa48d29a4, 0x8caf238c, 0xae07a9ae, 0x34390d34, 0x4d1f524d,
285
    0x39764f39, 0xbdd36ebd, 0x5781d657, 0x6fb7d86f, 0xdceb37dc, 0x15514415,
286
    0x7ba6dd7b, 0xf709fef7, 0x3ab68c3a, 0xbc932fbc, 0x0c0f030c, 0xff03fcff,
287
    0xa9c26ba9, 0xc9ba73c9, 0xb5d96cb5, 0xb1dc6db1, 0x6d375a6d, 0x45155045,
288
    0x36b98f36, 0x6c771b6c, 0xbe13adbe, 0x4ada904a, 0xee57b9ee, 0x77a9de77,
289
    0xf24cbef2, 0xfd837efd, 0x44551144, 0x67bdda67, 0x712c5d71, 0x05454005,
290
    0x7c631f7c, 0x40501040, 0x69325b69, 0x63b8db63, 0x28220a28, 0x07c5c207,
291
    0xc4f531c4, 0x22a88a22, 0x9631a796, 0x37f9ce37, 0xed977aed, 0xf649bff6,
292
    0xb4992db4, 0xd1a475d1, 0x4390d343, 0x485a1248, 0xe258bae2, 0x9771e697,
293
    0xd264b6d2, 0xc270b2c2, 0x26ad8b26, 0xa5cd68a5, 0x5ecb955e, 0x29624b29,
294
    0x303c0c30, 0x5ace945a, 0xddab76dd, 0xf9867ff9, 0x95f16495, 0xe65dbbe6,
295
    0xc735f2c7, 0x242d0924, 0x17d1c617, 0xb9d66fb9, 0x1bdec51b, 0x12948612,
296
    0x60781860, 0xc330f3c3, 0xf5897cf5, 0xb35cefb3, 0xe8d23ae8, 0x73acdf73,
297
    0x35794c35, 0x80a02080, 0xe59d78e5, 0xbb56edbb, 0x7d235e7d, 0xf8c63ef8,
298
    0x5f8bd45f, 0x2fe7c82f, 0xe4dd39e4, 0x21684921,
299
};
300
static const word32 sm4_sbox_3[256] = {
301
    0x8ed55b5b, 0xd0924242, 0x4deaa7a7, 0x06fdfbfb, 0xfccf3333, 0x65e28787,
302
    0xc93df4f4, 0x6bb5dede, 0x4e165858, 0x6eb4dada, 0x44145050, 0xcac10b0b,
303
    0x8828a0a0, 0x17f8efef, 0x9c2cb0b0, 0x11051414, 0x872bacac, 0xfb669d9d,
304
    0xf2986a6a, 0xae77d9d9, 0x822aa8a8, 0x46bcfafa, 0x14041010, 0xcfc00f0f,
305
    0x02a8aaaa, 0x54451111, 0x5f134c4c, 0xbe269898, 0x6d482525, 0x9e841a1a,
306
    0x1e061818, 0xfd9b6666, 0xec9e7272, 0x4a430909, 0x10514141, 0x24f7d3d3,
307
    0xd5934646, 0x53ecbfbf, 0xf89a6262, 0x927be9e9, 0xff33cccc, 0x04555151,
308
    0x270b2c2c, 0x4f420d0d, 0x59eeb7b7, 0xf3cc3f3f, 0x1caeb2b2, 0xea638989,
309
    0x74e79393, 0x7fb1cece, 0x6c1c7070, 0x0daba6a6, 0xedca2727, 0x28082020,
310
    0x48eba3a3, 0xc1975656, 0x80820202, 0xa3dc7f7f, 0xc4965252, 0x12f9ebeb,
311
    0xa174d5d5, 0xb38d3e3e, 0xc33ffcfc, 0x3ea49a9a, 0x5b461d1d, 0x1b071c1c,
312
    0x3ba59e9e, 0x0cfff3f3, 0x3ff0cfcf, 0xbf72cdcd, 0x4b175c5c, 0x52b8eaea,
313
    0x8f810e0e, 0x3d586565, 0xcc3cf0f0, 0x7d196464, 0x7ee59b9b, 0x91871616,
314
    0x734e3d3d, 0x08aaa2a2, 0xc869a1a1, 0xc76aadad, 0x85830606, 0x7ab0caca,
315
    0xb570c5c5, 0xf4659191, 0xb2d96b6b, 0xa7892e2e, 0x18fbe3e3, 0x47e8afaf,
316
    0x330f3c3c, 0x674a2d2d, 0xb071c1c1, 0x0e575959, 0xe99f7676, 0xe135d4d4,
317
    0x661e7878, 0xb4249090, 0x360e3838, 0x265f7979, 0xef628d8d, 0x38596161,
318
    0x95d24747, 0x2aa08a8a, 0xb1259494, 0xaa228888, 0x8c7df1f1, 0xd73becec,
319
    0x05010404, 0xa5218484, 0x9879e1e1, 0x9b851e1e, 0x84d75353, 0x00000000,
320
    0x5e471919, 0x0b565d5d, 0xe39d7e7e, 0x9fd04f4f, 0xbb279c9c, 0x1a534949,
321
    0x7c4d3131, 0xee36d8d8, 0x0a020808, 0x7be49f9f, 0x20a28282, 0xd4c71313,
322
    0xe8cb2323, 0xe69c7a7a, 0x42e9abab, 0x43bdfefe, 0xa2882a2a, 0x9ad14b4b,
323
    0x40410101, 0xdbc41f1f, 0xd838e0e0, 0x61b7d6d6, 0x2fa18e8e, 0x2bf4dfdf,
324
    0x3af1cbcb, 0xf6cd3b3b, 0x1dfae7e7, 0xe5608585, 0x41155454, 0x25a38686,
325
    0x60e38383, 0x16acbaba, 0x295c7575, 0x34a69292, 0xf7996e6e, 0xe434d0d0,
326
    0x721a6868, 0x01545555, 0x19afb6b6, 0xdf914e4e, 0xfa32c8c8, 0xf030c0c0,
327
    0x21f6d7d7, 0xbc8e3232, 0x75b3c6c6, 0x6fe08f8f, 0x691d7474, 0x2ef5dbdb,
328
    0x6ae18b8b, 0x962eb8b8, 0x8a800a0a, 0xfe679999, 0xe2c92b2b, 0xe0618181,
329
    0xc0c30303, 0x8d29a4a4, 0xaf238c8c, 0x07a9aeae, 0x390d3434, 0x1f524d4d,
330
    0x764f3939, 0xd36ebdbd, 0x81d65757, 0xb7d86f6f, 0xeb37dcdc, 0x51441515,
331
    0xa6dd7b7b, 0x09fef7f7, 0xb68c3a3a, 0x932fbcbc, 0x0f030c0c, 0x03fcffff,
332
    0xc26ba9a9, 0xba73c9c9, 0xd96cb5b5, 0xdc6db1b1, 0x375a6d6d, 0x15504545,
333
    0xb98f3636, 0x771b6c6c, 0x13adbebe, 0xda904a4a, 0x57b9eeee, 0xa9de7777,
334
    0x4cbef2f2, 0x837efdfd, 0x55114444, 0xbdda6767, 0x2c5d7171, 0x45400505,
335
    0x631f7c7c, 0x50104040, 0x325b6969, 0xb8db6363, 0x220a2828, 0xc5c20707,
336
    0xf531c4c4, 0xa88a2222, 0x31a79696, 0xf9ce3737, 0x977aeded, 0x49bff6f6,
337
    0x992db4b4, 0xa475d1d1, 0x90d34343, 0x5a124848, 0x58bae2e2, 0x71e69797,
338
    0x64b6d2d2, 0x70b2c2c2, 0xad8b2626, 0xcd68a5a5, 0xcb955e5e, 0x624b2929,
339
    0x3c0c3030, 0xce945a5a, 0xab76dddd, 0x867ff9f9, 0xf1649595, 0x5dbbe6e6,
340
    0x35f2c7c7, 0x2d092424, 0xd1c61717, 0xd66fb9b9, 0xdec51b1b, 0x94861212,
341
    0x78186060, 0x30f3c3c3, 0x897cf5f5, 0x5cefb3b3, 0xd23ae8e8, 0xacdf7373,
342
    0x794c3535, 0xa0208080, 0x9d78e5e5, 0x56edbbbb, 0x235e7d7d, 0xc63ef8f8,
343
    0x8bd45f5f, 0xe7c82f2f, 0xdd39e4e4, 0x68492121,
344
};
345
346
/* Linear transformation of nonlinear transformation tau.
347
 *
348
 * Each S-box value has had the linear transformation applied.
349
 *
350
 * @param [in] x  Unsigned 32-bit value to transform.
351
 * @return  Unsigned 32-bit bit value.
352
 */
353
static WC_INLINE word32 sm4_t(word32 x)
354
0
{
355
0
    return sm4_sbox_3[(byte)(x >> 24)] ^
356
0
           sm4_sbox_2[(byte)(x >> 16)] ^
357
0
           sm4_sbox_1[(byte)(x >>  8)] ^
358
0
           sm4_sbox_0[(byte)(x >>  0)];
359
0
}
360
361
#else
362
363
/* Linear transformation of nonlinear transformation tau.
364
 *
365
 * @param [in] x  Unsigned 32-bit value to transform.
366
 * @return  Unsigned 32-bit bit value.
367
 */
368
static word32 sm4_t(word32 x)
369
{
370
    word32 t;
371
372
    /* Nonlinear transformation. */
373
    t  = ((word32)sm4_sbox[(byte)(x >> 24)]) << 24;
374
    t |= ((word32)sm4_sbox[(byte)(x >> 16)]) << 16;
375
    t |= ((word32)sm4_sbox[(byte)(x >>  8)]) <<  8;
376
    t |=          sm4_sbox[(byte) x       ]       ;
377
378
    /* Linear transformation. */
379
    return t ^ rotlFixed(t, 2) ^ rotlFixed(t, 10) ^ rotlFixed(t, 18) ^
380
        rotlFixed(t, 24);
381
}
382
383
#endif
384
385
#endif /* !__aarch64__ || !WOLFSSL_ARMASM_CRYPTO_SM4 */
386
387
/* Key schedule calculation.
388
 *
389
 * @param [in]  key  Array of bytes representing key.
390
 * @param [out] ks   Array of unsigned 32-bit values that are the key schedule.
391
 */
392
static void sm4_key_schedule(const byte* key, word32* ks)
393
0
{
394
0
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM4)
395
#ifndef WOLFSSL_SMALL_STACK
396
    word32 k[36];
397
    word32 t;
398
    word32 x;
399
    int i;
400
401
    /* Load key into words. */
402
    LOAD_U32_BE(key, k[0], k[1], k[2], k[3]);
403
    k[0] ^= sm4_fk[0];
404
    k[1] ^= sm4_fk[1];
405
    k[2] ^= sm4_fk[2];
406
    k[3] ^= sm4_fk[3];
407
408
    /* Calculate each word of key schedule. */
409
    for (i = 0; i < SM4_KEY_SCHEDULE; ++i) {
410
        x = k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ sm4_ck[i];
411
412
        /* Nonlinear operation tau */
413
        t = ((word32)sm4_sbox[(byte)(x >> 24)]) << 24 |
414
            ((word32)sm4_sbox[(byte)(x >> 16)]) << 16 |
415
            ((word32)sm4_sbox[(byte)(x >>  8)]) <<  8 |
416
            ((word32)sm4_sbox[(byte)(x      )])       ;
417
418
        /* Linear operation L' */
419
        k[i+4] = k[i] ^ (t ^ rotlFixed(t, 13) ^ rotlFixed(t, 23));
420
        ks[i] = k[i + 4];
421
    }
422
#else
423
0
    word32 k[8];
424
0
    word32 t;
425
0
    word32 x;
426
0
    int i;
427
428
    /* Load key into words. */
429
0
    LOAD_U32_BE(key, k[0], k[1], k[2], k[3]);
430
0
    k[0] ^= sm4_fk[0];
431
0
    k[1] ^= sm4_fk[1];
432
0
    k[2] ^= sm4_fk[2];
433
0
    k[3] ^= sm4_fk[3];
434
435
    /* Calculate first 4 words of key schedule using k. */
436
0
    for (i = 0; i < 4; ++i) {
437
0
        x = k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ sm4_ck[i];
438
439
        /* Nonlinear operation tau */
440
0
        t = ((word32)sm4_sbox[(byte)(x >> 24)]) << 24 |
441
0
            ((word32)sm4_sbox[(byte)(x >> 16)]) << 16 |
442
0
            ((word32)sm4_sbox[(byte)(x >>  8)]) <<  8 |
443
0
            ((word32)sm4_sbox[(byte)(x      )])       ;
444
445
        /* Linear operation L' */
446
0
        k[i + 4] = k[i] ^ (t ^ rotlFixed(t, 13) ^ rotlFixed(t, 23));
447
0
        ks[i] = k[i + 4];
448
0
    }
449
    /* Calculate remaining words of key schedule without k. */
450
0
    for (; i < SM4_KEY_SCHEDULE; ++i) {
451
0
        x = ks[i - 3] ^ ks[i - 2] ^ ks[i - 1] ^ sm4_ck[i];
452
453
        /* Nonlinear operation tau */
454
0
        t = ((word32)sm4_sbox[(byte)(x >> 24)]) << 24 |
455
0
            ((word32)sm4_sbox[(byte)(x >> 16)]) << 16 |
456
0
            ((word32)sm4_sbox[(byte)(x >>  8)]) <<  8 |
457
0
            ((word32)sm4_sbox[(byte)(x      )])       ;
458
459
        /* Linear operation L' */
460
0
        ks[i] = ks[i - 4] ^ (t ^ rotlFixed(t, 13) ^ rotlFixed(t, 23));
461
0
    }
462
0
#endif
463
    /* Round-key material must not be left on the stack. */
464
0
    ForceZero(k, sizeof(k));
465
0
    ForceZero(&t, sizeof(t));
466
0
    ForceZero(&x, sizeof(x));
467
#else
468
    word32* ck = sm4_ck;
469
470
    __asm__ volatile (
471
        "LD1  {v0.16b}, [%[key]]\n\t"
472
        "LD1  {v9.16b}, [%[fk]]\n\t"
473
        "REV32  v0.16B, v0.16B\n\t"
474
        "LD1  {v1.4S-v4.4S}, [%[ck]], #64\n\t"
475
        "EOR  v0.16B, v0.16B, v9.16B\n\t"
476
        "LD1  {v5.4S-v8.4S}, [%[ck]]\n\t"
477
478
        "SM4EKEY  v1.4S, v0.4S, v1.4S\n\t"
479
        "SM4EKEY  v2.4S, v1.4S, v2.4S\n\t"
480
        "SM4EKEY  v3.4S, v2.4S, v3.4S\n\t"
481
        "SM4EKEY  v4.4S, v3.4S, v4.4S\n\t"
482
        "SM4EKEY  v5.4S, v4.4S, v5.4S\n\t"
483
        "SM4EKEY  v6.4S, v5.4S, v6.4S\n\t"
484
        "SM4EKEY  v7.4S, v6.4S, v7.4S\n\t"
485
        "SM4EKEY  v8.4S, v7.4S, v8.4S\n\t"
486
487
        "ST4  {v1.S-v4.S}[0], [%[ks]], #16\n\t"
488
        "ST4  {v5.S-v8.S}[0], [%[ks]], #16\n\t"
489
        "ST4  {v1.S-v4.S}[1], [%[ks]], #16\n\t"
490
        "ST4  {v5.S-v8.S}[1], [%[ks]], #16\n\t"
491
        "ST4  {v1.S-v4.S}[2], [%[ks]], #16\n\t"
492
        "ST4  {v5.S-v8.S}[2], [%[ks]], #16\n\t"
493
        "ST4  {v1.S-v4.S}[3], [%[ks]], #16\n\t"
494
        "ST4  {v5.S-v8.S}[3], [%[ks]], #16\n\t"
495
        : [ks] "+r" (ks), [ck] "+r" (ck)
496
        : [key] "r" (key), [fk] "r" (sm4_fk)
497
        : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
498
          "v9"
499
    );
500
#endif
501
0
}
502
503
/* Round operation.
504
 *
505
 * Assumes x0, x1, x2, x3 are the current state.
506
 * Assumes ks is the key schedule.
507
 *
508
 * @param [in] k0  Index into key schedule for first word.
509
 * @param [in] k1  Index into key schedule for second word.
510
 * @param [in] k2  Index into key schedule for third word.
511
 * @param [in] k3  Index into key schedule for fourth word.
512
 */
513
#define SM4_ROUNDS(k0, k1, k2, k3)          \
514
0
        x0 ^= sm4_t(x1 ^ x2 ^ x3 ^ ks[k0]); \
515
0
        x1 ^= sm4_t(x0 ^ x2 ^ x3 ^ ks[k1]); \
516
0
        x2 ^= sm4_t(x0 ^ x1 ^ x3 ^ ks[k2]); \
517
0
        x3 ^= sm4_t(x0 ^ x1 ^ x2 ^ ks[k3])
518
519
/* Encrypt a block of data using SM4 algorithm.
520
 *
521
 * @param [in]  ks   Key schedule.
522
 * @param [in]  in   Block to encrypt.
523
 * @param [out] out  Encrypted block.
524
 */
525
static void sm4_encrypt(const word32* ks, const byte* in, byte* out)
526
0
{
527
0
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM4)
528
0
    word32 x0, x1, x2, x3;
529
    /* Load block. */
530
0
    LOAD_U32_BE(in, x0, x1, x2, x3);
531
532
    /* Encrypt block. */
533
0
    SM4_ROUNDS( 0,  1,  2,  3);
534
0
    SM4_ROUNDS( 4,  5,  6,  7);
535
0
    SM4_ROUNDS( 8,  9, 10, 11);
536
0
    SM4_ROUNDS(12, 13, 14, 15);
537
0
    SM4_ROUNDS(16, 17, 18, 19);
538
0
    SM4_ROUNDS(20, 21, 22, 23);
539
0
    SM4_ROUNDS(24, 25, 26, 27);
540
0
    SM4_ROUNDS(28, 29, 30, 31);
541
542
    /* Store encrypted block. */
543
0
    STORE_U32_BE(x0, x1, x2, x3, out);
544
#else
545
    __asm__ volatile (
546
        "LD1  {v0.16b}, [%[in]]\n\t"
547
        "LD4  {v1.S-v4.S}[0], [%[ks]], #16\n\t"
548
        "LD4  {v5.S-v8.S}[0], [%[ks]], #16\n\t"
549
        "LD4  {v1.S-v4.S}[1], [%[ks]], #16\n\t"
550
        "LD4  {v5.S-v8.S}[1], [%[ks]], #16\n\t"
551
        "REV32  v0.16B, v0.16B\n\t"
552
        "LD4  {v1.S-v4.S}[2], [%[ks]], #16\n\t"
553
        "LD4  {v5.S-v8.S}[2], [%[ks]], #16\n\t"
554
        "LD4  {v1.S-v4.S}[3], [%[ks]], #16\n\t"
555
        "LD4  {v5.S-v8.S}[3], [%[ks]], #16\n\t"
556
557
        "SM4E v0.4S, v1.4S\n\t"
558
        "SM4E v0.4S, v2.4S\n\t"
559
        "SM4E v0.4S, v3.4S\n\t"
560
        "SM4E v0.4S, v4.4S\n\t"
561
        "SM4E v0.4S, v5.4S\n\t"
562
        "SM4E v0.4S, v6.4S\n\t"
563
        "SM4E v0.4S, v7.4S\n\t"
564
        "SM4E v0.4S, v8.4S\n\t"
565
566
        "REV64  v0.16B, v0.16B\n\t"
567
        "EXT  v0.16B, v0.16B, v0.16B, #8\n\t"
568
        "ST1  {v0.16b}, [%[out]]\n\t"
569
570
        : [ks] "+r" (ks), [out] "+r" (out)
571
        : [in] "r" (in)
572
        : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"
573
    );
574
#endif
575
0
}
576
577
#if defined(WOLFSSL_SM4_ECB) || defined(WOLFSSL_SM4_CBC)
578
/* Decrypt a block of data using SM4 algorithm.
579
 *
580
 * @param [in]  ks   Key schedule.
581
 * @param [in]  in   Block to decrypt.
582
 * @param [out] out  Decrypted block.
583
 */
584
static void sm4_decrypt(const word32* ks, const byte* in, byte* out)
585
0
{
586
0
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM4)
587
0
    word32 x0, x1, x2, x3;
588
589
    /* Load block. */
590
0
    LOAD_U32_BE(in, x0, x1, x2, x3);
591
592
    /* Decrypt block. */
593
0
    SM4_ROUNDS(31, 30, 29, 28);
594
0
    SM4_ROUNDS(27, 26, 25, 24);
595
0
    SM4_ROUNDS(23, 22, 21, 20);
596
0
    SM4_ROUNDS(19, 18, 17, 16);
597
0
    SM4_ROUNDS(15, 14, 13, 12);
598
0
    SM4_ROUNDS(11, 10,  9,  8);
599
0
    SM4_ROUNDS( 7,  6,  5,  4);
600
0
    SM4_ROUNDS( 3,  2,  1,  0);
601
602
    /* Store decrypted block. */
603
0
    STORE_U32_BE(x0, x1, x2, x3, out);
604
#else
605
    __asm__ volatile (
606
        "LD1  {v0.16b}, [%[in]]\n\t"
607
        "LD4  {v1.S-v4.S}[3], [%[ks]], #16\n\t"
608
        "LD4  {v5.S-v8.S}[3], [%[ks]], #16\n\t"
609
        "LD4  {v1.S-v4.S}[2], [%[ks]], #16\n\t"
610
        "LD4  {v5.S-v8.S}[2], [%[ks]], #16\n\t"
611
        "REV32  v0.16B, v0.16B\n\t"
612
        "LD4  {v1.S-v4.S}[1], [%[ks]], #16\n\t"
613
        "LD4  {v5.S-v8.S}[1], [%[ks]], #16\n\t"
614
        "LD4  {v1.S-v4.S}[0], [%[ks]], #16\n\t"
615
        "LD4  {v5.S-v8.S}[0], [%[ks]], #16\n\t"
616
617
        "SM4E v0.4S, v8.4S\n\t"
618
        "SM4E v0.4S, v7.4S\n\t"
619
        "SM4E v0.4S, v6.4S\n\t"
620
        "SM4E v0.4S, v5.4S\n\t"
621
        "SM4E v0.4S, v4.4S\n\t"
622
        "SM4E v0.4S, v3.4S\n\t"
623
        "SM4E v0.4S, v2.4S\n\t"
624
        "SM4E v0.4S, v1.4S\n\t"
625
626
        "REV64  v0.16B, v0.16B\n\t"
627
        "EXT  v0.16B, v0.16B, v0.16B, #8\n\t"
628
        "ST1  {v0.16b}, [%[out]]\n\t"
629
630
        : [ks] "+r" (ks)
631
        : [in] "r" (in), [out] "r" (out)
632
        : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"
633
    );
634
#endif
635
0
}
636
#endif
637
638
639
/* Initialize the SM4 algorithm object.
640
 *
641
 * @param [in, out] sm4    SM4 algorithm object.
642
 * @param [in]      heap   Heap hint for dynamic memory allocation.
643
 * @param [in]      devId  Device identifier.
644
 * @return  0 on success.
645
 * @return  BAD_FUNC_ARG when sm4 is NULL.
646
 */
647
int wc_Sm4Init(wc_Sm4* sm4, void* heap, int devId)
648
0
{
649
0
    int ret = 0;
650
651
#ifndef WOLF_CRYPTO_CB_SM
652
    (void)devId;
653
#endif
654
655
    /* Validate parameters. */
656
0
    if (sm4 == NULL) {
657
0
        ret = BAD_FUNC_ARG;
658
0
    }
659
660
0
    if (ret == 0) {
661
        /* Set all fields to zero including bit fields. */
662
0
        XMEMSET(sm4, 0, sizeof(*sm4));
663
664
        /* Cache heap hint to use with any dynamic allocations. */
665
0
        sm4->heap = heap;
666
0
#ifdef WOLF_CRYPTO_CB_SM
667
        /* Cache the device to offer operations to. */
668
0
        sm4->devId = devId;
669
0
        sm4->devCtx = NULL;
670
0
#endif
671
0
    }
672
673
0
    return ret;
674
0
}
675
676
/* Dispose of SM4 algorithm object.
677
 *
678
 * Zeroize sensitive data in object.
679
 *
680
 * @param [in, out] sm4  SM4 algorithm object.
681
 */
682
void wc_Sm4Free(wc_Sm4* sm4)
683
0
{
684
    /* Check we have something to work with. */
685
0
    if (sm4 != NULL) {
686
    #if defined(WOLF_CRYPTO_CB_SM) && \
687
        defined(WOLF_CRYPTO_CB_FREE)
688
        #ifndef WOLF_CRYPTO_CB_FIND
689
        if (sm4->devId != INVALID_DEVID)
690
        #endif
691
        {
692
            /* Let the device release any state it holds for this context. */
693
            (void)wc_CryptoCb_Free(sm4->devId, WC_ALGO_TYPE_CIPHER,
694
                WC_CIPHER_SM4, 0, sm4);
695
            /* Clear the handle so a second free cannot resubmit it. */
696
            sm4->devCtx = NULL;
697
        }
698
    #endif
699
        /* Must zeroize key schedule. */
700
0
        ForceZero(sm4->ks, sizeof(sm4->ks));
701
0
    #ifdef WOLF_CRYPTO_CB_SM
702
        /* The raw key kept for a device is key material too. */
703
0
        ForceZero(sm4->devKey, sizeof(sm4->devKey));
704
0
    #endif
705
0
    #if defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_CTR)
706
        /* CTR keystream and CBC decrypt plaintext both land in tmp. */
707
0
        ForceZero(sm4->tmp, sizeof(sm4->tmp));
708
0
    #endif
709
0
    #ifdef WOLFSSL_SM4_GCM
710
        /* gcm.H is the GHASH subkey derived from the key. */
711
0
        ForceZero(&sm4->gcm, sizeof(sm4->gcm));
712
0
    #endif
713
0
    }
714
0
}
715
716
/* Set the key.
717
 *
718
 * @param [in, out] sm4  SM4 algorithm object.
719
 * @param [in]      key  Array of bytes representing key.
720
 */
721
static void sm4_set_key(wc_Sm4* sm4, const byte* key)
722
0
{
723
    /* Create key schedule. */
724
0
    sm4_key_schedule(key, sm4->ks);
725
0
#ifdef WOLF_CRYPTO_CB_SM
726
0
    #ifndef WOLF_CRYPTO_CB_FIND
727
0
    if (sm4->devId != INVALID_DEVID)
728
0
    #endif
729
0
    {
730
0
        XMEMCPY(sm4->devKey, key, SM4_KEY_SIZE);
731
0
    }
732
0
#endif
733
    /* Mark key as having been set. */
734
0
    sm4->keySet = 1;
735
0
}
736
737
#if defined(WOLFSSL_SM4_ECB) || defined(WOLFSSL_SM4_CBC) || \
738
    defined(WOLFSSL_SM4_CTR) || defined(WOLFSSL_SM4_CCM)
739
/* Set the key.
740
 *
741
 * @param [in, out] sm4  SM4 algorithm object.
742
 * @param [in]      key  Array of bytes representing key.
743
 * @param [in]      len  Length of key. Must be SM4_KEY_SIZE.
744
 * @return  0 on success.
745
 * @return  BAD_FUNC_ARG when sm4 or key is NULL.
746
 * @return  BAD_FUNC_ARG when len is not SM4_KEY_SIZE.
747
 */
748
int wc_Sm4SetKey(wc_Sm4* sm4, const byte* key, word32 len)
749
0
{
750
0
    int ret = 0;
751
752
    /* Validate parameters. */
753
0
    if ((sm4 == NULL) || (key == NULL) || (len != SM4_KEY_SIZE)) {
754
0
        ret = BAD_FUNC_ARG;
755
0
    }
756
757
0
    if (ret == 0) {
758
0
        sm4_set_key(sm4, key);
759
0
    }
760
761
0
    return ret;
762
0
}
763
#endif
764
765
#if defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_CTR) || \
766
    defined(WOLFSSL_SM4_GCM)
767
/* Set the IV.
768
 *
769
 * @param [in, out] sm4  SM4 algorithm object.
770
 * @param [in]      iv   Array of bytes representing IV. May be NULL.
771
 */
772
static void sm4_set_iv(wc_Sm4* sm4, const byte* iv)
773
0
{
774
    /* Set IV. */
775
0
    XMEMCPY(sm4->iv, iv, SM4_IV_SIZE);
776
0
#ifdef WOLFSSL_SM4_CTR
777
    /* Unused count of encrypted counter for CTR mode. */
778
0
    sm4->unused = 0;
779
0
#endif
780
0
    sm4->ivSet = 1;
781
0
}
782
#endif
783
784
#if defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_CTR)
785
/* Set the IV.
786
 *
787
 * @param [in, out] sm4  SM4 algorithm object.
788
 * @param [in]      iv   Array of bytes representing IV. May be NULL.
789
 * @return  0 on success.
790
 * @return  BAD_FUNC_ARG when sm4 or iv is NULL.
791
 */
792
int wc_Sm4SetIV(wc_Sm4* sm4, const byte* iv)
793
0
{
794
0
    int ret = 0;
795
796
    /* Validate parameters. */
797
0
    if ((sm4 == NULL) || (iv == NULL)) {
798
0
        ret = BAD_FUNC_ARG;
799
0
    }
800
801
0
    if (ret == 0) {
802
0
        sm4_set_iv(sm4, iv);
803
0
    }
804
805
0
    return ret;
806
0
}
807
#endif
808
809
#ifdef WOLFSSL_SM4_ECB
810
811
/* Encrypt whole blocks with SM4-ECB in software.
812
 *
813
 * The public wc_Sm4EcbEncrypt() offers the work to a crypto callback device
814
 * first. Internal callers use this worker instead, so blocks of a larger
815
 * operation - the GCM counters - do not go back through the callback.
816
 *
817
 * @param [in]  sm4  SM4 algorithm object with a key set.
818
 * @param [out] out  Byte array in which to place encrypted data.
819
 * @param [in]  in   Array of bytes to encrypt.
820
 * @param [in]  sz   Number of bytes to encrypt. Multiple of block size.
821
 */
822
static void sm4_ecb_encrypt_blocks(const wc_Sm4* sm4, byte* out,
823
    const byte* in, word32 sz)
824
0
{
825
    /* Encrypt all bytes. */
826
0
    while (sz > 0) {
827
        /* Encrypt a block. */
828
0
        sm4_encrypt(sm4->ks, in, out);
829
        /* Move on to next block. */
830
0
        in += SM4_BLOCK_SIZE;
831
0
        out += SM4_BLOCK_SIZE;
832
0
        sz -= SM4_BLOCK_SIZE;
833
0
    }
834
0
}
835
836
/* Encrypt bytes using SM4-ECB.
837
 *
838
 * Length of input must be a multiple of the block size.
839
 * Assumes out is at least sz bytes long.
840
 *
841
 * @param [in]  sm4  SM4 algorithm object.
842
 * @param [out] out  Byte array in which to place encrypted data.
843
 * @param [in]  in   Array of bytes to encrypt.
844
 * @param [in]  sz   Number of bytes to encrypt.
845
 * @return  0 on success.
846
 * @return  BAD_FUNC_ARG when sm4, out or in is NULL.
847
 * @return  BAD_FUNC_ARG when sz is not a multiple of SM4_BLOCK_SIZE.
848
 * @return  MISSING_KEY when a key has not been set.
849
 */
850
int wc_Sm4EcbEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
851
0
{
852
0
    int ret = 0;
853
854
    /* Validate parameters. */
855
0
    if ((sm4 == NULL) || (in == NULL) || (out == NULL)) {
856
0
        ret = BAD_FUNC_ARG;
857
0
    }
858
    /* Can only work on multiples of block size of bytes. */
859
0
    if ((ret == 0) && ((sz & (SM4_BLOCK_SIZE - 1)) != 0)) {
860
0
        ret = BAD_FUNC_ARG;
861
0
    }
862
863
0
#ifdef WOLF_CRYPTO_CB_SM
864
    /* Offer to the device before the key check: the key may live there. */
865
0
    if (ret == 0) {
866
0
    #ifndef WOLF_CRYPTO_CB_FIND
867
0
        if (sm4->devId != INVALID_DEVID)
868
0
    #endif
869
0
        {
870
0
            ret = wc_CryptoCb_Sm4EcbEncrypt(sm4, out, in, sz);
871
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
872
0
                return ret;
873
0
            }
874
0
            ret = 0;
875
0
        }
876
0
    }
877
0
#endif
878
879
    /* Ensure a key has been set. */
880
0
    if ((ret == 0) && (!sm4->keySet)) {
881
0
        ret = MISSING_KEY;
882
0
    }
883
884
0
    if (ret == 0) {
885
0
        sm4_ecb_encrypt_blocks(sm4, out, in, sz);
886
0
    }
887
888
0
    return ret;
889
0
}
890
891
/* Decrypt bytes using SM4-ECB.
892
 *
893
 * Length of input must be a multiple of the block size.
894
 * Assumes out is at least sz bytes long.
895
 *
896
 * @param [in]  sm4  SM4 algorithm object.
897
 * @param [out] out  Byte array in which to place decrypted data.
898
 * @param [in]  in   Array of bytes to decrypt.
899
 * @param [in]  sz   Number of bytes to decrypt.
900
 * @return  0 on success.
901
 * @return  BAD_FUNC_ARG when sm4, out or in is NULL.
902
 * @return  BAD_FUNC_ARG when sz is not a multiple of SM4_BLOCK_SIZE.
903
 * @return  MISSING_KEY when a key has not been set.
904
 */
905
int wc_Sm4EcbDecrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
906
0
{
907
908
0
    int ret = 0;
909
910
    /* Validate parameters. */
911
0
    if ((sm4 == NULL) || (in == NULL) || (out == NULL)) {
912
0
        ret = BAD_FUNC_ARG;
913
0
    }
914
    /* Can only work on multiples of block size of bytes. */
915
0
    if ((ret == 0) && ((sz & (SM4_BLOCK_SIZE - 1)) != 0)) {
916
0
        ret = BAD_FUNC_ARG;
917
0
    }
918
919
0
#ifdef WOLF_CRYPTO_CB_SM
920
    /* Offer to the device before the key check: the key may live there. */
921
0
    if (ret == 0) {
922
0
    #ifndef WOLF_CRYPTO_CB_FIND
923
0
        if (sm4->devId != INVALID_DEVID)
924
0
    #endif
925
0
        {
926
0
            ret = wc_CryptoCb_Sm4EcbDecrypt(sm4, out, in, sz);
927
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
928
0
                return ret;
929
0
            }
930
0
            ret = 0;
931
0
        }
932
0
    }
933
0
#endif
934
935
    /* Ensure a key has been set. */
936
0
    if ((ret == 0) && (!sm4->keySet)) {
937
0
        ret = MISSING_KEY;
938
0
    }
939
940
0
    if (ret == 0) {
941
       /* Decrypt all bytes. */
942
0
        while (sz > 0) {
943
            /* Decrypt a block. */
944
0
            sm4_decrypt(sm4->ks, in, out);
945
            /* Move on to next block. */
946
0
            in += SM4_BLOCK_SIZE;
947
0
            out += SM4_BLOCK_SIZE;
948
0
            sz -= SM4_BLOCK_SIZE;
949
0
        }
950
0
    }
951
952
0
    return ret;
953
0
}
954
955
#endif /* WOLFSSL_SM4_ECB */
956
957
#ifdef WOLFSSL_SM4_CBC
958
959
/* Encrypt bytes using SM4-CBC.
960
 *
961
 * Length of input must be a multiple of the block size.
962
 * Assumes out is at least sz bytes long.
963
 *
964
 * @param [in]  sm4  SM4 algorithm object.
965
 * @param [out] out  Byte array in which to place encrypted data.
966
 * @param [in]  in   Array of bytes to encrypt.
967
 * @param [in]  sz   Number of bytes to encrypt.
968
 * @return  0 on success.
969
 * @return  BAD_FUNC_ARG when sm4, out or in is NULL.
970
 * @return  BAD_FUNC_ARG when sz is not a multiple of SM4_BLOCK_SIZE.
971
 * @return  MISSING_KEY when a key has not been set.
972
 * @return  MISSING_IV when an IV has not been set.
973
 */
974
int wc_Sm4CbcEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
975
0
{
976
0
    int ret = 0;
977
978
    /* Validate parameters. */
979
0
    if ((sm4 == NULL) || (in == NULL) || (out == NULL)) {
980
0
        ret = BAD_FUNC_ARG;
981
0
    }
982
    /* Can only work on multiples of block size of bytes. */
983
0
    if ((ret == 0) && ((sz & (SM4_BLOCK_SIZE - 1)) != 0)) {
984
0
        ret = BAD_FUNC_ARG;
985
0
    }
986
987
0
#ifdef WOLF_CRYPTO_CB_SM
988
    /* Offer to the device before the key check: the key may live there. */
989
0
    if (ret == 0) {
990
0
    #ifndef WOLF_CRYPTO_CB_FIND
991
0
        if (sm4->devId != INVALID_DEVID)
992
0
    #endif
993
0
        {
994
0
            ret = wc_CryptoCb_Sm4CbcEncrypt(sm4, out, in, sz);
995
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
996
0
                return ret;
997
0
            }
998
0
            ret = 0;
999
0
        }
1000
0
    }
1001
0
#endif
1002
1003
    /* Ensure a key and IV have been set. */
1004
0
    if ((ret == 0) && (!sm4->keySet)) {
1005
0
        ret = MISSING_KEY;
1006
0
    }
1007
0
    if ((ret == 0) && (!sm4->ivSet)) {
1008
0
        ret = MISSING_IV;
1009
0
    }
1010
1011
0
    if (ret == 0) {
1012
        /* Encrypt all bytes. */
1013
0
        while (sz > 0) {
1014
            /* XOR next block into IV. */
1015
0
            xorbuf(sm4->iv, in, SM4_BLOCK_SIZE);
1016
            /* Encrypt IV XORed with block. */
1017
0
            sm4_encrypt(sm4->ks, sm4->iv, sm4->iv);
1018
            /* Use output block as next IV. */
1019
0
            XMEMCPY(out, sm4->iv, SM4_BLOCK_SIZE);
1020
1021
            /* Move on to next block. */
1022
0
            in += SM4_BLOCK_SIZE;
1023
0
            out += SM4_BLOCK_SIZE;
1024
0
            sz -= SM4_BLOCK_SIZE;
1025
0
        }
1026
0
    }
1027
1028
0
    return ret;
1029
0
}
1030
1031
/* Decrypt bytes using SM4-CBC.
1032
 *
1033
 * Length of input must be a multiple of the block size.
1034
 * Assumes out is at least sz bytes long.
1035
 *
1036
 * @param [in]  sm4  SM4 algorithm object.
1037
 * @param [out] out  Byte array in which to place decrypted data.
1038
 * @param [in]  in   Array of bytes to decrypt.
1039
 * @param [in]  sz   Number of bytes to decrypt.
1040
 * @return  0 on success.
1041
 * @return  BAD_FUNC_ARG when sm4, out or in is NULL.
1042
 * @return  MISSING_KEY when a key has not been set.
1043
 * @return  MISSING_IV when an IV has not been set.
1044
 */
1045
int wc_Sm4CbcDecrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
1046
0
{
1047
0
    int ret = 0;
1048
1049
    /* Validate parameters. */
1050
0
    if ((sm4 == NULL) || (in == NULL) || (out == NULL)) {
1051
0
        ret = BAD_FUNC_ARG;
1052
0
    }
1053
    /* Can only work on multiples of block size of bytes. */
1054
0
    if ((ret == 0) && ((sz & (SM4_BLOCK_SIZE - 1)) != 0)) {
1055
0
        ret = BAD_FUNC_ARG;
1056
0
    }
1057
1058
0
#ifdef WOLF_CRYPTO_CB_SM
1059
    /* Offer to the device before the key check: the key may live there. */
1060
0
    if (ret == 0) {
1061
0
    #ifndef WOLF_CRYPTO_CB_FIND
1062
0
        if (sm4->devId != INVALID_DEVID)
1063
0
    #endif
1064
0
        {
1065
0
            ret = wc_CryptoCb_Sm4CbcDecrypt(sm4, out, in, sz);
1066
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1067
0
                return ret;
1068
0
            }
1069
0
            ret = 0;
1070
0
        }
1071
0
    }
1072
0
#endif
1073
1074
    /* Ensure a key and IV have been set. */
1075
0
    if ((ret == 0) && (!sm4->keySet)) {
1076
0
        ret = MISSING_KEY;
1077
0
    }
1078
0
    if ((ret == 0) && (!sm4->ivSet)) {
1079
0
        ret = MISSING_IV;
1080
0
    }
1081
1082
0
    if (ret == 0) {
1083
0
    #ifndef WOLFSSL_SM4_SMALL
1084
0
        if (in != out) {
1085
0
            while (sz > 0) {
1086
                /* Decrypt next block. */
1087
0
                sm4_decrypt(sm4->ks, in, sm4->tmp);
1088
                /* XOR decrypted block with IV to create output. */
1089
0
                xorbufout(out, sm4->tmp, sm4->iv, SM4_BLOCK_SIZE);
1090
                /* This encrypted block is the IV for next decryption. */
1091
0
                XMEMCPY(sm4->iv, in, SM4_BLOCK_SIZE);
1092
1093
                /* Move on to next block. */
1094
0
                in += SM4_BLOCK_SIZE;
1095
0
                out += SM4_BLOCK_SIZE;
1096
0
                sz -= SM4_BLOCK_SIZE;
1097
0
            }
1098
0
        }
1099
0
        else
1100
0
    #endif
1101
0
        {
1102
0
            while (sz > 0) {
1103
                /* Cache encrypted block as it is next IV. */
1104
0
                XMEMCPY(sm4->tmp, in, SM4_BLOCK_SIZE);
1105
                /* Decrypt next block. */
1106
0
                sm4_decrypt(sm4->ks, sm4->tmp, out);
1107
                /* XOR decrypted block with IV to create output. */
1108
0
                xorbuf(out, sm4->iv, SM4_BLOCK_SIZE);
1109
                /* Cached encrypted block is next IV. */
1110
0
                XMEMCPY(sm4->iv, sm4->tmp, SM4_BLOCK_SIZE);
1111
1112
                /* Move on to next block. */
1113
0
                in += SM4_BLOCK_SIZE;
1114
0
                out += SM4_BLOCK_SIZE;
1115
0
                sz -= SM4_BLOCK_SIZE;
1116
0
            }
1117
0
        }
1118
0
    }
1119
1120
0
    return ret;
1121
0
}
1122
1123
#endif /* WOLFSSL_SM4_CBC */
1124
1125
#ifdef WOLFSSL_SM4_CTR
1126
1127
/* Increment IV in big-endian representation.
1128
 *
1129
 * @param [in, out] counter  Counter value to increment.
1130
 */
1131
static WC_INLINE void sm4_increment_counter(byte* counter)
1132
0
{
1133
0
    int i;
1134
1135
    /* Big-endian number. */
1136
0
    for (i = SM4_BLOCK_SIZE - 1; i >= 0; i--) {
1137
        /* Increment byte and check for carry. */
1138
0
        if ((++counter[i]) != 0) {
1139
            /* No carry - done. */
1140
0
            break;
1141
0
        }
1142
0
    }
1143
0
}
1144
1145
/* Encrypt bytes using SM4-CTR.
1146
 *
1147
 * Assumes out is at least sz bytes long.
1148
 *
1149
 * @param [in]  sm4  SM4 algorithm object.
1150
 * @param [out] out  Byte array in which to place encrypted data.
1151
 * @param [in]  in   Array of bytes to encrypt.
1152
 * @param [in]  sz   Number of bytes to encrypt.
1153
 * @return  0 on success.
1154
 * @return  BAD_FUNC_ARG when sm4, out or in is NULL.
1155
 * @return  MISSING_KEY when a key has not been set.
1156
 * @return  MISSING_IV when an IV has not been set.
1157
 */
1158
int wc_Sm4CtrEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz)
1159
0
{
1160
0
    int ret = 0;
1161
1162
    /* Validate parameters. */
1163
0
    if ((sm4 == NULL) || (in == NULL) || (out == NULL)) {
1164
0
        ret = BAD_FUNC_ARG;
1165
0
    }
1166
1167
0
#ifdef WOLF_CRYPTO_CB_SM
1168
    /* Offer to the device before the key check: the key may live there. */
1169
0
    if (ret == 0) {
1170
0
    #ifndef WOLF_CRYPTO_CB_FIND
1171
0
        if (sm4->devId != INVALID_DEVID)
1172
0
    #endif
1173
0
        {
1174
0
            ret = wc_CryptoCb_Sm4CtrEncrypt(sm4, out, in, sz);
1175
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1176
0
                return ret;
1177
0
            }
1178
0
            ret = 0;
1179
0
        }
1180
0
    }
1181
0
#endif
1182
1183
    /* Ensure a key and IV have been set. */
1184
0
    if ((ret == 0) && (!sm4->keySet)) {
1185
0
        ret = MISSING_KEY;
1186
0
    }
1187
0
    if ((ret == 0) && (!sm4->ivSet)) {
1188
0
        ret = MISSING_IV;
1189
0
    }
1190
1191
    /* Continue if no error and bytes to encrypt. */
1192
0
    if ((ret == 0) && (sz > 0)) {
1193
        /* Check for unused bytes from previous encrypted counter. */
1194
0
        if (sm4->unused != 0) {
1195
            /* Calculate maximum length that can be encrypted. */
1196
0
            word32 len = min(sm4->unused, sz);
1197
1198
            /* XOR the encrypted counter with input into output. */
1199
0
            xorbufout(out, in, sm4->tmp + SM4_BLOCK_SIZE - sm4->unused, len);
1200
1201
            /* Move over processed data. */
1202
0
            in += len;
1203
0
            out += len;
1204
0
            sz -= len;
1205
            /* Some or all unused bytes used up. */
1206
0
            sm4->unused -= (byte)len;
1207
0
        }
1208
1209
        /* Do blocks at a time - only get here when there are no unused bytes.
1210
         */
1211
0
        while (sz >= SM4_BLOCK_SIZE) {
1212
            /* Encrypt the current IV into temporary buffer in object. */
1213
0
            sm4_encrypt(sm4->ks, sm4->iv, sm4->tmp);
1214
            /* XOR the encrypted IV with next block into output. */
1215
0
            xorbufout(out, in, sm4->tmp, SM4_BLOCK_SIZE);
1216
            /* Increment counter for next block. */
1217
0
            sm4_increment_counter(sm4->iv);
1218
1219
            /* Move on to next block. */
1220
0
            in += SM4_BLOCK_SIZE;
1221
0
            out += SM4_BLOCK_SIZE;
1222
0
            sz -= SM4_BLOCK_SIZE;
1223
0
        }
1224
1225
        /* Check for less than a block of data that needing to be encrypted. */
1226
0
        if (sz > 0) {
1227
            /* Encrypt the current IV into temporary buffer in object. */
1228
0
            sm4_encrypt(sm4->ks, sm4->iv, sm4->tmp);
1229
            /* Increment counter for next block. */
1230
0
            sm4_increment_counter(sm4->iv);
1231
            /* XOR the encrypted IV with remaining data into output. */
1232
0
            xorbufout(out, in, sm4->tmp, sz);
1233
            /* Record number of unused encrypted IV bytes. */
1234
0
            sm4->unused = (byte)(SM4_BLOCK_SIZE - sz);
1235
0
        }
1236
0
    }
1237
1238
0
    return ret;
1239
0
}
1240
1241
#endif /* WOLFSSL_SM4_CTR */
1242
1243
#ifdef WOLFSSL_SM4_GCM
1244
/* Calculate the value of H for the GMAC operation.
1245
 *
1246
 * @param [in]  sm4  SM4 algorithm object.
1247
 * @param [in]  iv   Initial IV.
1248
 */
1249
static void sm4_gcm_calc_h(wc_Sm4* sm4, byte* iv)
1250
0
{
1251
#if defined(__aarch64__) && defined(WOLFSSL_ARMASM)
1252
    word32* pt = (word32*)sm4->gcm.H;
1253
#endif
1254
1255
    /* Encrypt all zeros IV to create hash key for GCM. */
1256
0
    sm4_encrypt(sm4->ks, iv, sm4->gcm.H);
1257
0
#if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM)
1258
0
    #if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
1259
        /* Generate table from hash key. */
1260
0
        GenerateM0(&sm4->gcm);
1261
0
    #endif /* GCM_TABLE */
1262
#else
1263
    /* Reverse the bits of H for use in assembly. */
1264
    __asm__ volatile (
1265
        "LD1 {v0.16b}, [%[h]] \n"
1266
        "RBIT v0.16b, v0.16b \n"
1267
        "ST1 {v0.16b}, [%[out]] \n"
1268
        : [out] "=r" (pt)
1269
        : [h] "0" (pt)
1270
        : "cc", "memory", "v0"
1271
    );
1272
#endif
1273
0
}
1274
1275
/* Increment counter for GCM.
1276
 *
1277
 * @param [in, out] counter  4-byte big endian number.
1278
 */
1279
static WC_INLINE void sm4_increment_gcm_counter(byte* counter)
1280
0
{
1281
0
    int i;
1282
1283
    /* Big-endian number in last 4 bytes. */
1284
0
    for (i = SM4_BLOCK_SIZE - 1; i >= SM4_BLOCK_SIZE - CTR_SZ; i--) {
1285
        /* Increment byte and check for carry. */
1286
0
        if ((++counter[i]) != 0) {
1287
            /* No carry - done. */
1288
0
            break;
1289
0
        }
1290
0
    }
1291
0
}
1292
1293
/* Encrypt bytes using SM4-GCM implementation in C.
1294
 *
1295
 * @param [in]  sm4      SM4 algorithm object.
1296
 * @param [out] out      Byte array in which to place encrypted data.
1297
 * @param [in]  in       Array of bytes to encrypt.
1298
 * @param [in]  sz       Number of bytes to encrypt.
1299
 * @param [in]  nonce    Array of bytes holding nonce.
1300
 * @param [in]  nonceSz  Length of nonce in bytes.
1301
 * @param [out] tag      Authentication tag calculated using GCM.
1302
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
1303
 *                       Must be no more than SM4_BLOCK_SIZE.
1304
 * @param [in]  aad      Additional authentication data. May be NULL.
1305
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1306
 */
1307
static void sm4_gcm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1308
    const byte* nonce, word32 nonceSz, byte* tag, word32 tagSz,
1309
    const byte* aad, word32 aadSz)
1310
0
{
1311
0
    word32 blocks = sz / SM4_BLOCK_SIZE;
1312
0
    word32 partial = sz % SM4_BLOCK_SIZE;
1313
0
    byte* c = out;
1314
0
    ALIGN16 byte counter[SM4_BLOCK_SIZE];
1315
0
    ALIGN16 byte encCounter[SM4_BLOCK_SIZE];
1316
1317
    /* Check for 12 bytes of nonce to use as is with 4 bytes of counter. */
1318
0
    if (nonceSz == GCM_NONCE_MID_SZ) {
1319
        /* Counter is nonce with bottom 4 bytes set to: 0x00,0x00,0x00,0x01. */
1320
0
        XMEMCPY(counter, nonce, nonceSz);
1321
0
        XMEMSET(counter + GCM_NONCE_MID_SZ, 0, CTR_SZ - 1);
1322
0
        counter[SM4_BLOCK_SIZE - 1] = 1;
1323
0
    }
1324
0
    else {
1325
        /* Counter is GHASH of nonce. */
1326
0
        GHASH(&sm4->gcm, NULL, 0, nonce, nonceSz, counter, SM4_BLOCK_SIZE);
1327
#ifdef WOLFSSL_ARMASM
1328
        GMULT(counter, sm4->gcm.H);
1329
#endif
1330
0
    }
1331
    /* Encrypt the initial counter for GMAC. */
1332
0
    sm4_encrypt(sm4->ks, counter, encCounter);
1333
1334
0
#if defined(WOLFSSL_SM4_ECB)
1335
    /* Encrypting multiple blocks at a time can be faster. */
1336
0
    if ((c != in) && (blocks > 0)) {
1337
        /* Set the counters for a multiple of block size into the output. */
1338
0
        while (blocks--) {
1339
            /* Increment last 4 bytes of big-endian counter. */
1340
0
            sm4_increment_gcm_counter(counter);
1341
            /* Copy into output. */
1342
0
            XMEMCPY(c, counter, SM4_BLOCK_SIZE);
1343
            /* Move output position past this block. */
1344
0
            c += SM4_BLOCK_SIZE;
1345
0
        }
1346
1347
        /* Reset number of blocks. */
1348
0
        blocks = sz / SM4_BLOCK_SIZE;
1349
        /* Encrypt the counters. */
1350
0
        sm4_ecb_encrypt_blocks(sm4, out, out, SM4_BLOCK_SIZE * blocks);
1351
        /* XOR in the plaintext to create cipher text. */
1352
0
        xorbuf(out, in, SM4_BLOCK_SIZE * blocks);
1353
        /* Step over handled plaintext */
1354
0
        in += SM4_BLOCK_SIZE * blocks;
1355
0
    }
1356
0
    else
1357
0
#endif /* HAVE_SM4_ECB */
1358
0
    {
1359
0
        ALIGN32 byte scratch[SM4_BLOCK_SIZE];
1360
1361
        /* For each full block of data, encrypt. */
1362
0
        while (blocks--) {
1363
            /* Increment last 4 bytes of big-endian counter. */
1364
0
            sm4_increment_gcm_counter(counter);
1365
            /* Encrypt the counter into scratch. */
1366
0
            sm4_encrypt(sm4->ks, counter, scratch);
1367
            /* XOR encryted counter with plaintext into output. */
1368
0
            xorbufout(c, scratch, in, SM4_BLOCK_SIZE);
1369
            /* Move plaintext and cipher text position past this block. */
1370
0
            in += SM4_BLOCK_SIZE;
1371
0
            c += SM4_BLOCK_SIZE;
1372
0
        }
1373
1374
0
        ForceZero(scratch, sizeof(scratch));
1375
0
    }
1376
1377
0
    if (partial != 0) {
1378
        /* Increment last 4 bytes of big-endian counter. */
1379
0
        sm4_increment_gcm_counter(counter);
1380
        /* Encrypt the last counter. */
1381
0
        sm4_encrypt(sm4->ks, counter, counter);
1382
        /* XOR encryted counter with partial block plaintext into output. */
1383
0
        xorbufout(c, counter, in, partial);
1384
0
    }
1385
1386
    /* Calculate GHASH on additional authentication data and cipher text. */
1387
0
#ifndef WOLFSSL_ARMASM
1388
0
    GHASH(&sm4->gcm, aad, aadSz, out, sz, tag, tagSz);
1389
#else
1390
    GHASH(&sm4->gcm, aad, aadSz, out, sz, counter, SM4_BLOCK_SIZE);
1391
    GMULT(counter, sm4->gcm.H);
1392
    XMEMCPY(tag, counter, tagSz);
1393
#endif
1394
    /* XOR the encrypted initial counter into tag. */
1395
0
    xorbuf(tag, encCounter, tagSz);
1396
1397
0
    ForceZero(counter, sizeof(counter));
1398
0
    ForceZero(encCounter, sizeof(encCounter));
1399
0
}
1400
1401
/* Decrypt bytes using SM4-GCM implementation in C.
1402
 *
1403
 * @param [in]  sm4      SM4 algorithm object.
1404
 * @param [out] out      Byte array in which to place decrypted data.
1405
 * @param [in]  in       Array of bytes to decrypt.
1406
 * @param [in]  sz       Number of bytes to decrypt.
1407
 * @param [in]  nonce    Array of bytes holding initialization vector.
1408
 * @param [in]  nonceSz  Length of nonce in bytes.
1409
 * @param [in]  tag      Authentication tag calculated using GCM.
1410
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
1411
 *                       Must be no more than SM4_BLOCK_SIZE.
1412
 * @param [in]  aad      Additional authentication data. May be NULL.
1413
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1414
 * @return  0 on success.
1415
 * @return  SM4_GCM_AUTH_E when authentication tag calculated does not match
1416
 *          the one passed in.
1417
 */
1418
static int sm4_gcm_decrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1419
    const byte* nonce, word32 nonceSz, const byte* tag, word32 tagSz,
1420
    const byte* aad, word32 aadSz)
1421
0
{
1422
0
    int ret;
1423
0
    word32 blocks = sz / SM4_BLOCK_SIZE;
1424
0
    word32 partial = sz % SM4_BLOCK_SIZE;
1425
0
    byte* p = out;
1426
0
    ALIGN16 byte counter[SM4_BLOCK_SIZE];
1427
0
    ALIGN16 byte calcTag[SM4_BLOCK_SIZE];
1428
0
    ALIGN16 byte scratch[SM4_BLOCK_SIZE];
1429
0
    sword32 res;
1430
1431
0
    if (nonceSz == GCM_NONCE_MID_SZ) {
1432
        /* Counter is nonce with bottom 4 bytes set to: 0x00,0x00,0x00,0x01. */
1433
0
        XMEMCPY(counter, nonce, nonceSz);
1434
0
        XMEMSET(counter + GCM_NONCE_MID_SZ, 0, CTR_SZ - 1);
1435
0
        counter[SM4_BLOCK_SIZE - 1] = 1;
1436
0
    }
1437
0
    else {
1438
        /* Counter is GHASH of nonce. */
1439
0
        GHASH(&sm4->gcm, NULL, 0, nonce, nonceSz, counter, SM4_BLOCK_SIZE);
1440
#ifdef WOLFSSL_ARMASM
1441
        GMULT(counter, sm4->gcm.H);
1442
#endif
1443
0
    }
1444
1445
    /* Calculate GHASH on additional authentication data and cipher text. */
1446
0
#ifndef WOLFSSL_ARMASM
1447
0
    GHASH(&sm4->gcm, aad, aadSz, in, sz, calcTag, sizeof(calcTag));
1448
#else
1449
    GHASH(&sm4->gcm, aad, aadSz, in, sz, calcTag, SM4_BLOCK_SIZE);
1450
    GMULT(calcTag, sm4->gcm.H);
1451
#endif
1452
    /* Encrypt the initial counter. */
1453
0
    sm4_encrypt(sm4->ks, counter, scratch);
1454
    /* XOR the encrypted initial counter into calculated tag. */
1455
0
    xorbuf(calcTag, scratch, sizeof(calcTag));
1456
#ifdef WC_SM4_GCM_DEC_AUTH_EARLY
1457
    /* Compare tag and calculated tag in constant time. */
1458
    res = ConstantCompare(tag, calcTag, tagSz);
1459
    /* Create mask based on comparison result in constant time */
1460
    res = 0 - (sword32)(((word32)(0 - res)) >> 31U);
1461
    /* Mask error code to get return value. */
1462
    ret = res & SM4_GCM_AUTH_E;
1463
    /* Decrypt data when no error. */
1464
    if (ret == 0)
1465
#endif
1466
0
    {
1467
0
    #if defined(WOLFSSL_SM4_ECB)
1468
0
        if ((in != p) && (blocks > 0)) {
1469
            /* Set the counters for a multiple of block size into the output. */
1470
0
            while (blocks--) {
1471
                /* Increment last 4 bytes of big-endian counter. */
1472
0
                sm4_increment_gcm_counter(counter);
1473
                /* Copy into output. */
1474
0
                XMEMCPY(p, counter, SM4_BLOCK_SIZE);
1475
                /* Move output position past this block. */
1476
0
                p += SM4_BLOCK_SIZE;
1477
0
            }
1478
1479
            /* Reset number of blocks. */
1480
0
            blocks = sz / SM4_BLOCK_SIZE;
1481
            /* Encrypt the counters. */
1482
0
            sm4_ecb_encrypt_blocks(sm4, out, out, SM4_BLOCK_SIZE * blocks);
1483
            /* XOR in the plaintext to create cipher text. */
1484
0
            xorbuf(out, in, SM4_BLOCK_SIZE * blocks);
1485
            /* Step over handled plaintext */
1486
0
            in += SM4_BLOCK_SIZE * blocks;
1487
0
        }
1488
0
        else
1489
0
    #endif /* WOLFSSL_SM4_ECB */
1490
0
        {
1491
0
            while (blocks--) {
1492
                /* Increment last 4 bytes of big-endian counter. */
1493
0
                sm4_increment_gcm_counter(counter);
1494
                /* Encrypt the counter into scratch. */
1495
0
                sm4_encrypt(sm4->ks, counter, scratch);
1496
                /* XOR encryted counter with cipher text into output. */
1497
0
                xorbufout(p, scratch, in, SM4_BLOCK_SIZE);
1498
                /* Move plaintext and cipher text position past this block. */
1499
0
                p += SM4_BLOCK_SIZE;
1500
0
                in += SM4_BLOCK_SIZE;
1501
0
            }
1502
0
        }
1503
1504
0
        if (partial != 0) {
1505
            /* Increment last 4 bytes of big-endian counter. */
1506
0
            sm4_increment_gcm_counter(counter);
1507
            /* Encrypt the last counter. */
1508
0
            sm4_encrypt(sm4->ks, counter, counter);
1509
            /* XOR encryted counter with partial block cipher text into output.
1510
             */
1511
0
            xorbufout(p, counter, in, partial);
1512
0
        }
1513
1514
0
    #ifndef WC_SM4_GCM_DEC_AUTH_EARLY
1515
        /* Compare tag and calculated tag in constant time. */
1516
0
        res = ConstantCompare(tag, calcTag, (int)tagSz);
1517
        /* Create mask based on comparison result in constant time */
1518
0
        res = 0 - (sword32)(((word32)(0 - res)) >> 31U);
1519
        /* Mask error code to get return value. */
1520
0
        ret = res & SM4_GCM_AUTH_E;
1521
0
    #endif
1522
0
    }
1523
1524
0
    ForceZero(counter, sizeof(counter));
1525
0
    ForceZero(calcTag, sizeof(calcTag));
1526
0
    ForceZero(scratch, sizeof(scratch));
1527
1528
0
    return ret;
1529
0
}
1530
1531
/* Set the SM4-GCM key.
1532
 *
1533
 * Calculates key based table here.
1534
 *
1535
 * @param [in, out] sm4  SM4 algorithm object.
1536
 * @param [in]      key  Array of bytes representing key.
1537
 * @param [in]      len  Length of key. Must be SM4_KEY_SIZE.
1538
 * @return  0 on success.
1539
 * @return  BAD_FUNC_ARG when sm4 or key is NULL.
1540
 * @return  BAD_FUNC_ARG when len is not SM4_KEY_SIZE.
1541
 */
1542
int wc_Sm4GcmSetKey(wc_Sm4* sm4, const byte* key, word32 len)
1543
0
{
1544
0
    int ret = 0;
1545
0
    byte iv[SM4_BLOCK_SIZE];
1546
1547
    /* Validate parameters. */
1548
0
    if ((sm4 == NULL) || (key == NULL) || (len != SM4_KEY_SIZE)) {
1549
0
        ret = BAD_FUNC_ARG;
1550
0
    }
1551
1552
0
    if (ret == 0) {
1553
        /* Set key. */
1554
0
        sm4_set_key(sm4, key);
1555
        /* Reset IV to all zeros. */
1556
0
        XMEMSET(iv, 0, sizeof(iv));
1557
        /* Set IV. */
1558
0
        sm4_set_iv(sm4, iv);
1559
        /* Calculate H for GMAC operation */
1560
0
        sm4_gcm_calc_h(sm4, iv);
1561
0
    }
1562
1563
0
    return ret;
1564
0
}
1565
1566
/* Encrypt bytes using SM4-GCM.
1567
 *
1568
 * Assumes out is at least sz bytes long.
1569
 *
1570
 * @param [in]  sm4      SM4 algorithm object.
1571
 * @param [out] out      Byte array in which to place encrypted data.
1572
 * @param [in]  in       Array of bytes to encrypt.
1573
 * @param [in]  sz       Number of bytes to encrypt.
1574
 * @param [in]  nonce    Array of bytes holding initialization vector.
1575
 * @param [in]  nonceSz  Length of nonce in bytes.
1576
 * @param [out] tag      Authentication tag calculated using GCM.
1577
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
1578
 *                       Must be no more than SM4_BLOCK_SIZE.
1579
 * @param [in]  aad      Additional authentication data. May be NULL.
1580
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1581
 * @return  0 on success.
1582
 * @return  BAD_FUNC_ARG when sm4, in, out, nonce or tag is NULL.
1583
 * @return  BAD_FUNC_ARG when authentication tag data length is less than
1584
 *          WOLFSSL_MIN_AUTH_TAG_SZ or is more than SM4_BLOCK_SIZE.
1585
 * @return  BAD_FUNC_ARG when nonce length is 0.
1586
 * @return  MISSING_KEY when a key has not been set.
1587
 */
1588
int wc_Sm4GcmEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1589
    const byte* nonce, word32 nonceSz, byte* tag, word32 tagSz, const byte* aad,
1590
    word32 aadSz)
1591
0
{
1592
0
    int ret = 0;
1593
1594
    /* Validate parameters. */
1595
0
    if ((sm4 == NULL) || ((sz != 0) && ((in == NULL) || (out == NULL))) ||
1596
0
            (nonce == NULL) || (tag == NULL)) {
1597
0
        ret = BAD_FUNC_ARG;
1598
0
    }
1599
0
    if ((tagSz < WOLFSSL_MIN_AUTH_TAG_SZ) || (tagSz > SM4_BLOCK_SIZE)) {
1600
0
        ret = BAD_FUNC_ARG;
1601
0
    }
1602
0
    if (nonceSz == 0) {
1603
0
        ret = BAD_FUNC_ARG;
1604
0
    }
1605
1606
0
#ifdef WOLF_CRYPTO_CB_SM
1607
    /* Offer to the device before the key check: the key may live there. */
1608
0
    if (ret == 0) {
1609
0
    #ifndef WOLF_CRYPTO_CB_FIND
1610
0
        if (sm4->devId != INVALID_DEVID)
1611
0
    #endif
1612
0
        {
1613
0
            ret = wc_CryptoCb_Sm4GcmEncrypt(sm4, out, in, sz, nonce,
1614
0
                nonceSz, tag, tagSz, aad, aadSz);
1615
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1616
0
                return ret;
1617
0
            }
1618
0
            ret = 0;
1619
0
        }
1620
0
    }
1621
0
#endif
1622
1623
    /* Ensure a key has been set. */
1624
0
    if ((ret == 0) && (!sm4->keySet)) {
1625
0
        ret = MISSING_KEY;
1626
0
    }
1627
1628
0
    if (ret == 0) {
1629
    #ifdef OPENSSL_EXTRA
1630
        sm4->nonceSz = (int)nonceSz;
1631
    #endif
1632
        /* Perform encryption using C implementation. */
1633
0
        sm4_gcm_encrypt_c(sm4, out, in, sz, nonce, nonceSz, tag, tagSz, aad,
1634
0
            aadSz);
1635
0
    }
1636
1637
0
    return ret;
1638
0
}
1639
1640
/* Decrypt bytes using SM4-GCM.
1641
 *
1642
 * Assumes out is at least sz bytes long.
1643
 *
1644
 * @param [in]  sm4      SM4 algorithm object.
1645
 * @param [out] out      Byte array in which to place decrypted data.
1646
 * @param [in]  in       Array of bytes to decrypt.
1647
 * @param [in]  sz       Number of bytes to decrypt.
1648
 * @param [in]  nonce    Array of bytes holding initialization vector.
1649
 * @param [in]  nonceSz  Length of nonce in bytes.
1650
 * @param [in]  tag      Authentication tag to compare against calculated.
1651
 * @param [in]  tagSz    Length of authentication tag in bytes.
1652
 *                       Must be no more than SM4_BLOCK_SIZE.
1653
 * @param [in]  aad      Additional authentication data. May be NULL.
1654
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1655
 * @return  0 on success.
1656
 * @return  BAD_FUNC_ARG when sm4, in, out, nonce or tag is NULL.
1657
 * @return  BAD_FUNC_ARG when authentication tag data length is less than
1658
 *          WOLFSSL_MIN_AUTH_TAG_SZ or is more than SM4_BLOCK_SIZE.
1659
 * @return  BAD_FUNC_ARG when nonce length is 0.
1660
 * @return  MISSING_KEY when a key has not been set.
1661
 * @return  SM4_GCM_AUTH_E when authentication tag calculated does not match
1662
 *          the one passed in.
1663
 */
1664
int wc_Sm4GcmDecrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1665
    const byte* nonce, word32 nonceSz, const byte* tag, word32 tagSz,
1666
    const byte* aad, word32 aadSz)
1667
0
{
1668
0
    int ret = 0;
1669
1670
    /* Validate parameters. */
1671
0
    if ((sm4 == NULL) || ((sz != 0) && ((in == NULL) || (out == NULL))) ||
1672
0
            (nonce == NULL) || (tag == NULL)) {
1673
0
        ret = BAD_FUNC_ARG;
1674
0
    }
1675
0
    if ((tagSz < WOLFSSL_MIN_AUTH_TAG_SZ) || (tagSz > SM4_BLOCK_SIZE)) {
1676
0
        ret = BAD_FUNC_ARG;
1677
0
    }
1678
0
    if (nonceSz == 0) {
1679
0
        ret = BAD_FUNC_ARG;
1680
0
    }
1681
1682
0
#ifdef WOLF_CRYPTO_CB_SM
1683
    /* Offer to the device before the key check: the key may live there. */
1684
0
    if (ret == 0) {
1685
0
    #ifndef WOLF_CRYPTO_CB_FIND
1686
0
        if (sm4->devId != INVALID_DEVID)
1687
0
    #endif
1688
0
        {
1689
0
            ret = wc_CryptoCb_Sm4GcmDecrypt(sm4, out, in, sz, nonce,
1690
0
                nonceSz, tag, tagSz, aad, aadSz);
1691
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1692
0
                return ret;
1693
0
            }
1694
0
            ret = 0;
1695
0
        }
1696
0
    }
1697
0
#endif
1698
1699
    /* Ensure a key has been set. */
1700
0
    if ((ret == 0) && (!sm4->keySet)) {
1701
0
        ret = MISSING_KEY;
1702
0
    }
1703
1704
0
    if (ret == 0) {
1705
    #ifdef OPENSSL_EXTRA
1706
        sm4->nonceSz = (int)nonceSz;
1707
    #endif
1708
        /* Perform decryption using C implementation. */
1709
0
        ret = sm4_gcm_decrypt_c(sm4, out, in, sz, nonce, nonceSz, tag, tagSz,
1710
0
            aad, aadSz);
1711
0
    }
1712
1713
0
    return ret;
1714
0
}
1715
1716
#endif /* WOLFSSL_SM4_GCM */
1717
1718
#ifdef WOLFSSL_SM4_CCM
1719
1720
/* Roll up data.
1721
 *
1722
 * Encrypt each block XORed into out.
1723
 *
1724
 * @param [in]      sm4  SM4 algorithm object.
1725
 * @param [in]      in   Data to roll up.
1726
 * @param [in]      sz   Length in bytes of data.
1727
 * @param [in, out] out  Block XORed into and encrypted.
1728
 */
1729
static void sm4_ccm_roll_x(wc_Sm4* sm4, const byte* in, word32 sz, byte* out)
1730
0
{
1731
    /* XOR in each block and encrypt each result. */
1732
0
    while (sz >= SM4_BLOCK_SIZE) {
1733
        /* XOR in next block. */
1734
0
        xorbuf(out, in, SM4_BLOCK_SIZE);
1735
        /* Move on past block. */
1736
0
        in += SM4_BLOCK_SIZE;
1737
0
        sz -= SM4_BLOCK_SIZE;
1738
        /* Encrypt into self. */
1739
0
        sm4_encrypt(sm4->ks, out, out);
1740
0
    }
1741
1742
    /* XOR in a block of data and encrypt result. */
1743
0
    if (sz > 0) {
1744
        /* XOR in partial block. */
1745
0
        xorbuf(out, in, sz);
1746
        /* Encrypt into self. */
1747
0
        sm4_encrypt(sm4->ks, out, out);
1748
0
    }
1749
0
}
1750
1751
/* Roll up additional authentication data (AAD).
1752
 *
1753
 * First block has length plus ant AAD XORed in before being encrypted.
1754
 *
1755
 * @param [in]  sm4  SM4 algorithm object.
1756
 * @param [in]  in   Additional authentication data to roll up.
1757
 * @param [in]  sz   Length in bytes of data.
1758
 * @param [out] out  Block XORed into and encrypted.
1759
 */
1760
static void sm4_ccm_roll_aad(wc_Sm4* sm4, const byte* in, word32 sz, byte* out)
1761
0
{
1762
0
    word32 aadLenSz;
1763
0
    word32 remainder;
1764
1765
    /* XOR length at start of block. */
1766
0
    if (sz <= 0xFEFF) {
1767
        /* Two bytes used to represent length. */
1768
0
        aadLenSz = 2;
1769
0
        out[0] ^= ((sz & 0xFF00) >> 8);
1770
0
        out[1] ^=  (sz & 0x00FF);
1771
0
    }
1772
0
    else {
1773
        /* Four bytes used to represent length plus two unique bytes. */
1774
0
        aadLenSz = 6;
1775
0
        out[0] ^= 0xFF;
1776
0
        out[1] ^= 0xFE;
1777
0
        out[2] ^= (byte)((sz & 0xFF000000) >> 24);
1778
0
        out[3] ^= (byte)((sz & 0x00FF0000) >> 16);
1779
0
        out[4] ^= (byte)((sz & 0x0000FF00) >>  8);
1780
0
        out[5] ^= (byte) (sz & 0x000000FF);
1781
0
    }
1782
1783
    /* Calculate number of input bytes required to make up the block. */
1784
0
    remainder = SM4_BLOCK_SIZE - aadLenSz;
1785
    /* Check how much AAD available. */
1786
0
    if (sz >= remainder) {
1787
        /* XOR up to block into out. */
1788
0
        xorbuf(out + aadLenSz, in, remainder);
1789
        /* Move past data. */
1790
0
        sz -= remainder;
1791
0
        in += remainder;
1792
0
    }
1793
0
    else {
1794
        /* XOR in AAD available. */
1795
0
        xorbuf(out + aadLenSz, in, sz);
1796
        /* All AAD used. */
1797
0
        sz = 0;
1798
0
    }
1799
    /* Encrypt into self. */
1800
0
    sm4_encrypt(sm4->ks, out, out);
1801
1802
0
    if (sz > 0) {
1803
        /* Roll up any remaining AAD. */
1804
0
        sm4_ccm_roll_x(sm4, in, sz, out);
1805
0
    }
1806
0
}
1807
1808
/* Last bytes incremented as a big-endian number.
1809
 *
1810
 * Bytes not the nonce and length are incremented.
1811
 *
1812
 * @param [in, out] b      IV block.
1813
 * @param [in]      ctrSz  Length of counter.
1814
 */
1815
static WC_INLINE void sm4_ccm_ctr_inc(byte* b, word32 ctrSz)
1816
0
{
1817
0
    word32 i;
1818
1819
    /* Only last bytes that make up counter. */
1820
0
    for (i = 0; i < ctrSz; i++) {
1821
        /* Increment byte and check for carry. */
1822
0
        if ((++b[SM4_BLOCK_SIZE - 1 - i]) != 0) {
1823
            /* No carry - done. */
1824
0
            break;
1825
0
        }
1826
0
    }
1827
0
}
1828
1829
/* Encipher bytes using SM4-CCM.
1830
 *
1831
 * @param [in]       sm4    SM4 algorithm object.
1832
 * @param [out]      out    Byte array in which to place encrypted data.
1833
 * @param [in]       in     Array of bytes to encrypt.
1834
 * @param [in]       sz     Number of bytes to encrypt.
1835
 * @param [in, out]  b      IV block.
1836
 * @param [in]       ctrSz  Number of counter bytes in IV block.
1837
 */
1838
static WC_INLINE void sm4_ccm_crypt(wc_Sm4* sm4, byte* out, const byte* in,
1839
    word32 sz, byte* b, byte ctrSz)
1840
0
{
1841
0
    ALIGN16 byte a[SM4_BLOCK_SIZE];
1842
1843
    /* Nonce and length have been set and counter 0 except for last byte. */
1844
1845
    /* Set counter to 1. */
1846
0
    b[SM4_BLOCK_SIZE - 1] = 1;
1847
    /* Encrypting full blocks at a time. */
1848
0
    while (sz >= SM4_BLOCK_SIZE) {
1849
        /* Encrypt counter. */
1850
0
        sm4_encrypt(sm4->ks, b, a);
1851
        /* XOR in plaintext. */
1852
0
        xorbuf(a, in, SM4_BLOCK_SIZE);
1853
        /* Copy cipher text out. */
1854
0
        XMEMCPY(out, a, SM4_BLOCK_SIZE);
1855
1856
        /* Increment counter for next block. */
1857
0
        sm4_ccm_ctr_inc(b, ctrSz);
1858
        /* Move over block. */
1859
0
        sz -= SM4_BLOCK_SIZE;
1860
0
        in += SM4_BLOCK_SIZE;
1861
0
        out += SM4_BLOCK_SIZE;
1862
0
    }
1863
0
    if (sz > 0) {
1864
        /* Encrypt counter. */
1865
0
        sm4_encrypt(sm4->ks, b, a);
1866
        /* XOR in remaining plaintext. */
1867
0
        xorbuf(a, in, sz);
1868
        /* Copy cipher text out. */
1869
0
        XMEMCPY(out, a, sz);
1870
0
    }
1871
1872
0
    ForceZero(a, sizeof(a));
1873
0
}
1874
1875
/* Calculate authentication tag for SM4-CCM.
1876
 *
1877
 * @param [in]       sm4    SM4 algorithm object.
1878
 * @param [in]       plain  Array of bytes to encrypt.
1879
 * @param [in]       sz     Number of bytes to encrypt.
1880
 * @param [in]       aad    Additional authentication data. May be NULL.
1881
 * @param [in]       aadSz  Length of additional authentication data in bytes.
1882
 * @param [in, out]  b      IV block.
1883
 * @param [in]       ctrSz  Number of counter bytes in IV block.
1884
 * @param [out]      tag    Authentication tag calculated using CCM.
1885
 * @param [in]       tagSz  Length of authentication tag to calculate in bytes.
1886
 */
1887
static WC_INLINE void sm4_ccm_calc_auth_tag(wc_Sm4* sm4, const byte* plain,
1888
    word32 sz, const byte* aad, word32 aadSz, byte* b, byte ctrSz,
1889
    byte* tag, word32 tagSz)
1890
0
{
1891
0
    ALIGN16 byte a[SM4_BLOCK_SIZE];
1892
0
    byte t[SM4_BLOCK_SIZE];
1893
0
    word32 i;
1894
1895
    /* Nonce is in place. */
1896
1897
    /* Set first byte to length and flags. */
1898
0
    b[0] = (byte)((((aad != NULL) && (aadSz > 0)) ? 0x40 : 0x00) +
1899
0
                  (8 * (((byte)tagSz - 2) / 2)) + (ctrSz - 1));
1900
    /* Set the counter bytes to length of data - 4 bytes of length only. */
1901
0
    for (i = 0; i < ctrSz && i < sizeof(word32); i++) {
1902
0
        b[SM4_BLOCK_SIZE - 1 - i] = (byte)(sz >> (8 * i));
1903
0
    }
1904
    /* Set remaining counter bytes to 0. */
1905
0
    for (; i < ctrSz; i++) {
1906
0
        b[SM4_BLOCK_SIZE - 1 - i] = 0x00;
1907
0
    }
1908
    /* Encrypt block into authentication tag block. */
1909
0
    sm4_encrypt(sm4->ks, b, a);
1910
1911
0
    if ((aad != NULL) && (aadSz > 0)) {
1912
        /* Roll up any AAD. */
1913
0
        sm4_ccm_roll_aad(sm4, aad, aadSz, a);
1914
0
    }
1915
0
    if (sz > 0) {
1916
        /* Roll up any plaintext. */
1917
0
        sm4_ccm_roll_x(sm4, plain, sz, a);
1918
0
    }
1919
1920
    /* Nonce remains in place. */
1921
    /* Set first byte to counter size - 1. */
1922
0
    b[0] = ctrSz - 1;
1923
    /* Set counter to 0. */
1924
0
    for (i = 0; i < ctrSz; i++) {
1925
0
        b[SM4_BLOCK_SIZE - 1 - i] = 0;
1926
0
    }
1927
    /* Encrypt block into authentication tag block. */
1928
0
    sm4_encrypt(sm4->ks, b, t);
1929
    /* XOR in other authentication tag data. */
1930
0
    xorbufout(tag, t, a, tagSz);
1931
1932
0
    ForceZero(a, sizeof(a));
1933
0
    ForceZero(t, sizeof(t));
1934
0
}
1935
1936
/* Encrypt bytes using SM4-CCM implementation in C.
1937
 *
1938
 * @param [in]  sm4      SM4 algorithm object.
1939
 * @param [out] out      Byte array in which to place encrypted data.
1940
 * @param [in]  in       Array of bytes to encrypt.
1941
 * @param [in]  sz       Number of bytes to encrypt.
1942
 * @param [in]  nonce    Array of bytes holding initialization vector.
1943
 * @param [in]  nonceSz  Length of nonce in bytes.
1944
 * @param [out] tag      Authentication tag calculated using CCM.
1945
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
1946
 *                       Must be no more than SM4_BLOCK_SIZE.
1947
 * @param [in]  aad      Additional authentication data. May be NULL.
1948
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1949
 */
1950
static void sm4_ccm_encrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1951
    const byte* nonce, word32 nonceSz, byte* tag, word32 tagSz, const byte* aad,
1952
    word32 aadSz)
1953
0
{
1954
0
    ALIGN16 byte b[SM4_BLOCK_SIZE];
1955
0
    byte ctrSz;
1956
1957
    /* Calculate length of counter. */
1958
0
    ctrSz = SM4_BLOCK_SIZE - 1 - (byte)nonceSz;
1959
    /* Copy nonce in after length byte. */
1960
0
    XMEMCPY(b + 1, nonce, nonceSz);
1961
1962
    /* Calculate authentication tag. */
1963
0
    sm4_ccm_calc_auth_tag(sm4, in, sz, aad, aadSz, b, ctrSz, tag, tagSz);
1964
    /* b is left with first byte counter size - 1 and counter part set to zero.
1965
     */
1966
1967
0
    if (sz > 0) {
1968
        /* Encrypt plaintext to cipher text. */
1969
0
        sm4_ccm_crypt(sm4, out, in, sz, b, ctrSz);
1970
0
    }
1971
1972
0
    ForceZero(b, sizeof(b));
1973
0
}
1974
1975
/* Decrypt bytes using SM4-CCM implementation in C.
1976
 *
1977
 * @param [in]  sm4      SM4 algorithm object.
1978
 * @param [out] out      Byte array in which to place decrypted data.
1979
 * @param [in]  in       Array of bytes to decrypt.
1980
 * @param [in]  sz       Number of bytes to decrypt.
1981
 * @param [in]  nonce    Array of bytes holding initialization vector.
1982
 * @param [in]  nonceSz  Length of nonce in bytes.
1983
 * @param [in]  tag      Authentication tag calculated using GCM.
1984
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
1985
 *                       Must be no more than SM4_BLOCK_SIZE.
1986
 * @param [in]  aad      Additional authentication data. May be NULL.
1987
 * @param [in]  aadSz    Length of additional authentication data in bytes.
1988
 * @return  0 on success.
1989
 * @return  SM4_CCM_AUTH_E when authentication tag calculated does not match
1990
 *          the one passed in.
1991
 */
1992
static int sm4_ccm_decrypt_c(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
1993
    const byte* nonce, word32 nonceSz, const byte* tag, word32 tagSz,
1994
    const byte* aad, word32 aadSz)
1995
0
{
1996
0
    ALIGN16 byte b[SM4_BLOCK_SIZE];
1997
0
    ALIGN16 byte t[SM4_BLOCK_SIZE];
1998
0
    byte ctrSz;
1999
0
    word32 i;
2000
0
    int ret = 0;
2001
2002
    /* Calculate length of counter. */
2003
0
    ctrSz = SM4_BLOCK_SIZE - 1 - (byte)nonceSz;
2004
    /* Copy nonce in after length byte. */
2005
0
    XMEMCPY(b + 1, nonce, nonceSz);
2006
2007
    /* Set length byte to counter size - 1. */
2008
0
    b[0] = ctrSz - 1;
2009
    /* Set all bytes but least significant of counter to 0. */
2010
0
    for (i = 1; i < ctrSz; i++) {
2011
0
        b[SM4_BLOCK_SIZE - 1 - i] = 0;
2012
0
    }
2013
0
    if (sz > 0) {
2014
        /* Decrypt cipher text to plaintext. */
2015
0
        sm4_ccm_crypt(sm4, out, in, sz, b, ctrSz);
2016
        /* b still has nonce in place. */
2017
0
    }
2018
2019
    /* Calculate authentication tag. */
2020
0
    sm4_ccm_calc_auth_tag(sm4, out, sz, aad, aadSz, b, ctrSz, t, tagSz);
2021
2022
    /* Compare calculated tag with passed in tag. */
2023
0
    if (ConstantCompare(t, tag, (int)tagSz) != 0) {
2024
        /* Set CCM authentication error return. */
2025
0
        ret = SM4_CCM_AUTH_E;
2026
0
    }
2027
2028
0
    ForceZero(b, sizeof(b));
2029
0
    ForceZero(t, sizeof(t));
2030
2031
0
    return ret;
2032
0
}
2033
2034
/* Encrypt bytes using SM4-CCM.
2035
 *
2036
 * Assumes out is at least sz bytes long.
2037
 *
2038
 * @param [in]  sm4      SM4 algorithm object.
2039
 * @param [out] out      Byte array in which to place encrypted data.
2040
 * @param [in]  in       Array of bytes to encrypt.
2041
 * @param [in]  sz       Number of bytes to encrypt.
2042
 * @param [in]  nonce    Array of bytes holding initialization vector.
2043
 * @param [in]  nonceSz  Length of nonce in bytes.
2044
 * @param [out] tag      Authentication tag calculated using CCM.
2045
 * @param [in]  tagSz    Length of authentication tag to calculate in bytes.
2046
 *                       Must be no more than SM4_BLOCK_SIZE.
2047
 * @param [in]  aad      Additional authentication data. May be NULL.
2048
 * @param [in]  aadSz    Length of additional authentication data in bytes.
2049
 * @return  0 on success.
2050
 * @return  BAD_FUNC_ARG when sm4, in, out, nonce or tag is NULL.
2051
 * @return  BAD_FUNC_ARG when authentication tag data length is less than
2052
 *          4 or is more than SM4_BLOCK_SIZE or an odd value.
2053
 * @return  BAD_FUNC_ARG when nonce length is less than CCM_NONCE_MIN_SZ or
2054
 *          greater than CCM_NONCE_MAX_SZ.
2055
 * @return  MISSING_KEY when a key has not been set.
2056
 */
2057
int wc_Sm4CcmEncrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
2058
    const byte* nonce, word32 nonceSz, byte* tag, word32 tagSz, const byte* aad,
2059
    word32 aadSz)
2060
0
{
2061
0
    int ret = 0;
2062
2063
    /* Validate parameters. */
2064
0
    if ((sm4 == NULL) || ((sz != 0) && ((in == NULL) || (out == NULL))) ||
2065
0
            (nonce == NULL) || (tag == NULL)) {
2066
0
        ret = BAD_FUNC_ARG;
2067
0
    }
2068
    /* Tag size is even number 4..16. */
2069
0
    if ((tagSz < 4) || (tagSz > SM4_BLOCK_SIZE) || ((tagSz & 1) == 1)) {
2070
0
        ret = BAD_FUNC_ARG;
2071
0
    }
2072
    /* Nonce must be within supported range. */
2073
0
    if ((nonceSz < CCM_NONCE_MIN_SZ) || (nonceSz > CCM_NONCE_MAX_SZ)) {
2074
0
        ret = BAD_FUNC_ARG;
2075
0
    }
2076
    /* Message length must fit the CCM length field of (15 - nonceSz) bytes. */
2077
0
    if (ret == 0) {
2078
0
        word32 ctrSz = (word32)SM4_BLOCK_SIZE - 1 - nonceSz;
2079
0
        if ((ctrSz < sizeof(sz)) && (sz > (((word32)1 << (8 * ctrSz)) - 1))) {
2080
0
            ret = BAD_FUNC_ARG;
2081
0
        }
2082
0
    }
2083
2084
0
#ifdef WOLF_CRYPTO_CB_SM
2085
    /* Offer to the device before the key check: the key may live there. */
2086
0
    if (ret == 0) {
2087
0
    #ifndef WOLF_CRYPTO_CB_FIND
2088
0
        if (sm4->devId != INVALID_DEVID)
2089
0
    #endif
2090
0
        {
2091
0
            ret = wc_CryptoCb_Sm4CcmEncrypt(sm4, out, in, sz, nonce,
2092
0
                nonceSz, tag, tagSz, aad, aadSz);
2093
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
2094
0
                return ret;
2095
0
            }
2096
0
            ret = 0;
2097
0
        }
2098
0
    }
2099
0
#endif
2100
2101
    /* Ensure a key has been set. */
2102
0
    if ((ret == 0) && (!sm4->keySet)) {
2103
0
        ret = MISSING_KEY;
2104
0
    }
2105
2106
0
    if (ret == 0) {
2107
    #ifdef OPENSSL_EXTRA
2108
        sm4->nonceSz = (int)nonceSz;
2109
    #endif
2110
        /* Perform encryption using C implementation. */
2111
0
        sm4_ccm_encrypt_c(sm4, out, in, sz, nonce, nonceSz, tag, tagSz, aad,
2112
0
            aadSz);
2113
0
    }
2114
2115
0
    return ret;
2116
0
}
2117
2118
/* Decrypt bytes using SM4-CCM.
2119
 *
2120
 * Assumes out is at least sz bytes long.
2121
 *
2122
 * @param [in]  sm4      SM4 algorithm object.
2123
 * @param [out] out      Byte array in which to place decrypted data.
2124
 * @param [in]  in       Array of bytes to decrypt.
2125
 * @param [in]  sz       Number of bytes to decrypt.
2126
 * @param [in]  nonce    Array of bytes holding initialization vector.
2127
 * @param [in]  nonceSz  Length of nonce in bytes.
2128
 * @param [in]  tag      Authentication tag to compare against calculated.
2129
 * @param [in]  tagSz    Length of authentication tag in bytes.
2130
 *                       Must be no more than SM4_BLOCK_SIZE.
2131
 * @param [in]  aad      Additional authentication data. May be NULL.
2132
 * @param [in]  aadSz    Length of additional authentication data in bytes.
2133
 * @return  0 on success.
2134
 * @return  BAD_FUNC_ARG when sm4, in, out, nonce or tag is NULL.
2135
 * @return  BAD_FUNC_ARG when authentication tag data length is less than
2136
 *          4 or is more than SM4_BLOCK_SIZE or an odd value.
2137
 * @return  BAD_FUNC_ARG when nonce length is less than CCM_NONCE_MIN_SZ or
2138
 *          greater than CCM_NONCE_MAX_SZ.
2139
 * @return  MISSING_KEY when a key has not been set.
2140
 * @return  SM4_CCM_AUTH_E when authentication tag calculated does not match
2141
 *          the one passed in.
2142
 */
2143
int wc_Sm4CcmDecrypt(wc_Sm4* sm4, byte* out, const byte* in, word32 sz,
2144
    const byte* nonce, word32 nonceSz, const byte* tag, word32 tagSz,
2145
    const byte* aad, word32 aadSz)
2146
0
{
2147
0
    int ret = 0;
2148
2149
    /* Validate parameters. */
2150
0
    if ((sm4 == NULL) || ((sz != 0) && ((in == NULL) || (out == NULL))) ||
2151
0
            (nonce == NULL) || (tag == NULL)) {
2152
0
        ret = BAD_FUNC_ARG;
2153
0
    }
2154
    /* Tag size is even number 4..16. */
2155
0
    if ((tagSz < 4) || (tagSz > SM4_BLOCK_SIZE) || ((tagSz & 1) == 1)) {
2156
0
        ret = BAD_FUNC_ARG;
2157
0
    }
2158
    /* Nonce must be within supported range. */
2159
0
    if ((nonceSz < CCM_NONCE_MIN_SZ) || (nonceSz > CCM_NONCE_MAX_SZ)) {
2160
0
        ret = BAD_FUNC_ARG;
2161
0
    }
2162
    /* Message length must fit the CCM length field of (15 - nonceSz) bytes. */
2163
0
    if (ret == 0) {
2164
0
        word32 ctrSz = (word32)SM4_BLOCK_SIZE - 1 - nonceSz;
2165
0
        if ((ctrSz < sizeof(sz)) && (sz > (((word32)1 << (8 * ctrSz)) - 1))) {
2166
0
            ret = BAD_FUNC_ARG;
2167
0
        }
2168
0
    }
2169
2170
0
#ifdef WOLF_CRYPTO_CB_SM
2171
    /* Offer to the device before the key check: the key may live there. */
2172
0
    if (ret == 0) {
2173
0
    #ifndef WOLF_CRYPTO_CB_FIND
2174
0
        if (sm4->devId != INVALID_DEVID)
2175
0
    #endif
2176
0
        {
2177
0
            ret = wc_CryptoCb_Sm4CcmDecrypt(sm4, out, in, sz, nonce,
2178
0
                nonceSz, tag, tagSz, aad, aadSz);
2179
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
2180
0
                return ret;
2181
0
            }
2182
0
            ret = 0;
2183
0
        }
2184
0
    }
2185
0
#endif
2186
2187
    /* Ensure a key has been set. */
2188
0
    if ((ret == 0) && (!sm4->keySet)) {
2189
0
        ret = MISSING_KEY;
2190
0
    }
2191
2192
0
    if (ret == 0) {
2193
    #ifdef OPENSSL_EXTRA
2194
        sm4->nonceSz = (int)nonceSz;
2195
    #endif
2196
        /* Perform decryption using C implementation. */
2197
0
        ret = sm4_ccm_decrypt_c(sm4, out, in, sz, nonce, nonceSz, tag, tagSz,
2198
0
            aad, aadSz);
2199
0
    }
2200
2201
0
    return ret;
2202
0
}
2203
2204
#endif
2205
2206
#endif /* WOLFSSL_SM4 */
2207