/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 | | |