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