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