/src/wolfssl-sp-math-all/wolfcrypt/src/sm3.c
Line | Count | Source |
1 | | /* sm3.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-oscca-cfrg-sm3-02 |
24 | | */ |
25 | | |
26 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
27 | | |
28 | | #ifdef WOLFSSL_SM3 |
29 | | |
30 | | #include <wolfssl/wolfcrypt/sm3.h> |
31 | | #include <wolfssl/wolfcrypt/cpuid.h> |
32 | | #ifdef WOLF_CRYPTO_CB_SM |
33 | | #include <wolfssl/wolfcrypt/cryptocb.h> |
34 | | #endif |
35 | | #include <wolfssl/wolfcrypt/hash.h> |
36 | | |
37 | | #ifdef NO_INLINE |
38 | | #include <wolfssl/wolfcrypt/misc.h> |
39 | | #else |
40 | | #define WOLFSSL_MISC_INCLUDED |
41 | | #include <wolfcrypt/src/misc.c> |
42 | | #endif |
43 | | |
44 | | #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) |
45 | | #if defined(__GNUC__) && ((__GNUC__ < 4) || \ |
46 | | (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) |
47 | | #undef NO_AVX2_SUPPORT |
48 | | #define NO_AVX2_SUPPORT |
49 | | #endif |
50 | | #if defined(__clang__) && ((__clang_major__ < 3) || \ |
51 | | (__clang_major__ == 3 && __clang_minor__ <= 5)) |
52 | | #define NO_AVX2_SUPPORT |
53 | | #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) |
54 | | #undef NO_AVX2_SUPPORT |
55 | | #endif |
56 | | |
57 | | #define HAVE_INTEL_AVX1 |
58 | | #ifndef NO_AVX2_SUPPORT |
59 | | #define HAVE_INTEL_AVX2 |
60 | | #endif |
61 | | #else |
62 | | #undef HAVE_INTEL_AVX1 |
63 | | #undef HAVE_INTEL_AVX2 |
64 | | #endif /* WOLFSSL_X86_64_BUILD && USE_INTEL_SPEEDUP */ |
65 | | |
66 | | #if defined(HAVE_INTEL_AVX2) |
67 | | #define HAVE_INTEL_RORX |
68 | | #endif |
69 | | |
70 | | /******************************************************************************/ |
71 | | |
72 | | /* To support different implementations at the same time, replace these |
73 | | * functions with ones that vector off to the appropriate implementation. |
74 | | * |
75 | | * Have SM3_COMPRESS call the function in a global function pointer if the |
76 | | * choice can be made up front. |
77 | | * Same for SM3_COMPRESS_LEN if available. |
78 | | */ |
79 | | |
80 | | /* Compression process applied to one block. Block's endian has been fixed. */ |
81 | | typedef void (*SM3_COMPRESS_FUNC)(wc_Sm3* sm3, const word32* block); |
82 | | /* Compression process applied to one or more blocks. Data big-endian. */ |
83 | | typedef void (*SM3_COMPRESS_LEN_FUNC)(wc_Sm3* sm3, const byte* data, |
84 | | word32 len); |
85 | | |
86 | | /* Prototype for platforms where it is the default implementation. */ |
87 | | static void sm3_compress_c(wc_Sm3* sm3, const word32* block); |
88 | | static void sm3_compress_len_c(wc_Sm3* sm3, const byte* data, word32 len); |
89 | | |
90 | | |
91 | | #ifdef USE_INTEL_SPEEDUP |
92 | | |
93 | | /* C and x64 assembly implementations available. */ |
94 | | |
95 | | /* Compression process function that is changed depending on CPUs capabilities. |
96 | | * Default is C implementation. |
97 | | */ |
98 | | SM3_COMPRESS_FUNC sm3_compress_func = &sm3_compress_c; |
99 | | /* Compression process with length function that is changed depending on CPUs |
100 | | * capabilities. Default is C implementation. |
101 | | */ |
102 | | SM3_COMPRESS_LEN_FUNC sm3_compress_len_func = &sm3_compress_len_c; |
103 | | |
104 | | /* Prototype of assembly functions. */ |
105 | | extern void sm3_compress_avx1_rorx(wc_Sm3* sm3, const word32* block); |
106 | | extern void sm3_compress_len_avx1_rorx(wc_Sm3* sm3, const byte* data, |
107 | | word32 len); |
108 | | extern void sm3_compress_avx1(wc_Sm3* sm3, const word32* block); |
109 | | extern void sm3_compress_len_avx1(wc_Sm3* sm3, const byte* data, word32 len); |
110 | | |
111 | | /* Sets the compression process functions based on CPU information. |
112 | | */ |
113 | | static void sm3_set_compress_x64(void) |
114 | | { |
115 | | /* Boolean indicating choice of compression functions made. */ |
116 | | static int compress_funcs_set = 0; |
117 | | /* Intel CPU Id flags. */ |
118 | | static int intel_cpuid_flags; |
119 | | |
120 | | /* Only set functions once. */ |
121 | | if (!compress_funcs_set) { |
122 | | /* Get CPU Id flags. */ |
123 | | intel_cpuid_flags = cpuid_get_flags(); |
124 | | #ifdef HAVE_INTEL_AVX1 |
125 | | /* Use AVX1 assembly implementation if flags say AVX1 available. */ |
126 | | if (IS_INTEL_AVX1(intel_cpuid_flags)) { |
127 | | if (IS_INTEL_BMI2(intel_cpuid_flags) && |
128 | | IS_INTEL_BMI1(intel_cpuid_flags)) { |
129 | | sm3_compress_func = &sm3_compress_avx1_rorx; |
130 | | sm3_compress_len_func = &sm3_compress_len_avx1_rorx; |
131 | | } |
132 | | else { |
133 | | sm3_compress_func = &sm3_compress_avx1; |
134 | | sm3_compress_len_func = &sm3_compress_len_avx1; |
135 | | } |
136 | | } |
137 | | #endif |
138 | | /* Compression functions set - don't set again. */ |
139 | | compress_funcs_set = 1; |
140 | | } |
141 | | } |
142 | | |
143 | | /* Set the compression functions to use. */ |
144 | | #define SM3_SET_COMPRESS() sm3_set_compress_x64() |
145 | | /* Compression process for a block uses function pointer. */ |
146 | | #define SM3_COMPRESS(sm3, block) (*sm3_compress_func)(sm3, block) |
147 | | /* Compression process with length uses function pointer. */ |
148 | | #define SM3_COMPRESS_LEN(sm3, data, len) \ |
149 | | (*sm3_compress_len_func)(sm3, data, len) |
150 | | /* Only use C implementation of final process. */ |
151 | | #define sm3_final(sm3) sm3_final_c(sm3) |
152 | | |
153 | | #else |
154 | | |
155 | | /* Only C implementation compiled in. */ |
156 | | |
157 | | /* No global function pointers to set. */ |
158 | | #define SM3_SET_COMPRESS() |
159 | | /* Only use C implementation of compression process. */ |
160 | 0 | #define SM3_COMPRESS(sm3, block) sm3_compress_c(sm3, block) |
161 | | /* Only use C implementation of multi-block compression process. */ |
162 | 0 | #define SM3_COMPRESS_LEN(sm3, data, len) sm3_compress_len_c(sm3, data, len) |
163 | | /* Only use C implementation of final process. */ |
164 | 0 | #define sm3_final(sm3) sm3_final_c(sm3) |
165 | | |
166 | | #endif |
167 | | |
168 | | /******************************************************************************/ |
169 | | |
170 | | /* To replace C implementation use #ifdef around this code. |
171 | | * Also around prototypes. |
172 | | */ |
173 | | |
174 | | /* Reverse block size worth of 32-bit words. |
175 | | * |
176 | | * @param [out] out Output buffer to write to. |
177 | | * @param [in] in Buffer to reverse. |
178 | | */ |
179 | | #define BSWAP32_16(out, in) \ |
180 | 0 | ByteReverseWords((word32*)(out), (const word32*)(in), WC_SM3_BLOCK_SIZE) |
181 | | |
182 | | /* Reverse digest size worth of 32-bit words. |
183 | | * |
184 | | * @param [out] out Output buffer to write to. |
185 | | * @param [in] in Buffer to reverse. |
186 | | */ |
187 | | #define BSWAP32_8(out, in) \ |
188 | 0 | ByteReverseWords((word32*)(out), (const word32*)(in), WC_SM3_DIGEST_SIZE) |
189 | | |
190 | | #if !(defined(WOLFSSL_X86_64_BUILD) || defined(WOLFSSL_X86_BUILD)) |
191 | | /* Permutation function within the compression function. |
192 | | * |
193 | | * @param [in] x Value to use. |
194 | | * @return Permutated result. |
195 | | */ |
196 | | #define P0(x) ((x) ^ rotlFixed((x), 9) ^ rotlFixed((x), 17)) |
197 | | /* Permutation function within the message expansion. |
198 | | * |
199 | | * @param [in] x Value to use. |
200 | | * @return Permutated result. |
201 | | */ |
202 | | #define P1(x) ((x) ^ rotlFixed((x), 15) ^ rotlFixed((x), 23)) |
203 | | #else |
204 | | /* These are faster when you don't have 3 argument rotate instructions. */ |
205 | | |
206 | | /* Permutation function within the compression function. |
207 | | * |
208 | | * @param [in] x Value to use. |
209 | | * @return Permutated result. |
210 | | */ |
211 | 0 | #define P0(x) ((x) ^ rotlFixed((x) ^ rotlFixed((x), 8), 9)) |
212 | | /* Permutation function within the message expansion. |
213 | | * |
214 | | * @param [in] x Value to use. |
215 | | * @return Permutated result. |
216 | | */ |
217 | 0 | #define P1(x) ((x) ^ rotlFixed((x) ^ rotlFixed((x), 8), 15)) |
218 | | #endif |
219 | | |
220 | | /* Calculates w based on previous values and j. |
221 | | * |
222 | | * @param [in] w Array of 32-bit values. |
223 | | * @param [in] j Index into array to use. |
224 | | * @return New 32-bit value to be placed into array. |
225 | | */ |
226 | 0 | #define W(w, j) P1((w)[(j)-16] ^ (w)[(j)-9] ^ rotlFixed((w)[(j)-3], 15)) ^ \ |
227 | 0 | rotlFixed((w)[(j)-13], 7) ^ (w)[(j)-6] |
228 | | |
229 | | #ifdef SM3_STANDARD |
230 | | /* Boolean function FF. |
231 | | * |
232 | | * Original function as described in standard. |
233 | | * |
234 | | * @param [in] x First value. |
235 | | * @param [in] y Second value. |
236 | | * @param [in] z Third value. |
237 | | * @param [in] j Iteration count. |
238 | | * @return 32-bit value that is the FF calculation. |
239 | | */ |
240 | | #define FF(x, y, z, j) (((j) < 16) ? ((x) ^ (y) ^ (z)) : \ |
241 | | (((x) & (y)) | ((x) & (z)) | ((y) & (z)))) |
242 | | #else |
243 | | /* Boolean function FF. |
244 | | * |
245 | | * Equivalent to standard but fewer operations. |
246 | | * |
247 | | * @param [in] x First value. |
248 | | * @param [in] y Second value. |
249 | | * @param [in] z Third value. |
250 | | * @param [in] j Iteration count. |
251 | | * @return 32-bit value that is the FF calculation. |
252 | | */ |
253 | 0 | #define FF(x, y, z, j) (((j) < 16) ? ((x) ^ (y) ^ (z)) : \ |
254 | 0 | ((((y) ^ (x)) & ((y) ^ (z))) ^ (y))) |
255 | | #endif /* SM3_STANDARD */ |
256 | | |
257 | | /* Boolean function GG. |
258 | | * |
259 | | * @param [in] x First value. |
260 | | * @param [in] y Second value. |
261 | | * @param [in] z Third value. |
262 | | * @param [in] j Iteration count. |
263 | | * @return 32-bit value that is the GG calculation. |
264 | | */ |
265 | 0 | #define GG(x, y, z, j) (((j) < 16) ? ((x) ^ (y) ^ (z)) : \ |
266 | 0 | (((x) & (y)) | ((~(x)) & (z)))) |
267 | | /* Alternative that is no faster: ((((y) ^ (z)) & (x)) ^ (z))) */ |
268 | | |
269 | | /* Unrolled loop when not small. */ |
270 | | #ifndef WOLFSSL_SM3_SMALL |
271 | | |
272 | | /* A-H values for iteration i. */ |
273 | 0 | #define A(i) v[(0-(i)) & 7] |
274 | 0 | #define B(i) v[(1-(i)) & 7] |
275 | | #define C(i) v[(2-(i)) & 7] |
276 | 0 | #define D(i) v[(3-(i)) & 7] |
277 | 0 | #define E(i) v[(4-(i)) & 7] |
278 | 0 | #define F(i) v[(5-(i)) & 7] |
279 | | #define G(i) v[(6-(i)) & 7] |
280 | 0 | #define H(i) v[(7-(i)) & 7] |
281 | | |
282 | | /* An iteration of merged message expansion and compression function. |
283 | | * Loop unrolled by 8 so that registers are not rotated around. |
284 | | * |
285 | | * Call when: i + j < 12 |
286 | | * |
287 | | * @param [in] i Index of unrolled 8 iterations. |
288 | | * @param [in] j Index of iteration - multiple of 8. |
289 | | */ |
290 | | #define SM3_ITER_INIT(i, j) \ |
291 | 0 | ss2 = rotlFixed(A(i), 12); \ |
292 | 0 | ss1 = rotlFixed((ss2 + E(i) + SM3_T[(j)+(i)]), 7); \ |
293 | 0 | ss2 ^= ss1; \ |
294 | 0 | ss1 += w[(j)+(i)]; \ |
295 | 0 | ss2 += w[(j)+(i)] ^ w[(j)+(i)+4]; \ |
296 | 0 | tt1 = FF(A(i), B(i), C(i), (j)+(i)) + D(i) + ss2; \ |
297 | 0 | tt2 = GG(E(i), F(i), G(i), (j)+(i)) + H(i) + ss1; \ |
298 | 0 | B(i) = rotlFixed(B(i), 9); \ |
299 | 0 | F(i) = rotlFixed(F(i), 19); \ |
300 | 0 | H(i) = tt1; \ |
301 | 0 | D(i) = P0(tt2) |
302 | | |
303 | | /* An iteration of merged message expansion and compression function. |
304 | | * Loop unrolled by 8 so that registers are not rotated around. |
305 | | * |
306 | | * Call when: i + j >= 12 |
307 | | * |
308 | | * @param [in] i Index of unrolled 8 iterations. |
309 | | * @param [in] j Index of iteration - multiple of 8. |
310 | | */ |
311 | | #define SM3_ITER(i, j) \ |
312 | 0 | w[(j)+(i)+4] = W(w, (j)+(i)+4); \ |
313 | 0 | ss2 = rotlFixed(A(i), 12); \ |
314 | 0 | ss1 = rotlFixed((ss2 + E(i) + SM3_T[(j)+(i)]), 7); \ |
315 | 0 | ss2 ^= ss1; \ |
316 | 0 | ss1 += w[(j)+(i)]; \ |
317 | 0 | ss2 += w[(j)+(i)] ^ w[(j)+(i)+4]; \ |
318 | 0 | tt1 = FF(A(i), B(i), C(i), (j)+(i)) + D(i) + ss2; \ |
319 | 0 | tt2 = GG(E(i), F(i), G(i), (j)+(i)) + H(i) + ss1; \ |
320 | 0 | B(i) = rotlFixed(B(i), 9); \ |
321 | 0 | F(i) = rotlFixed(F(i), 19); \ |
322 | 0 | H(i) = tt1; \ |
323 | 0 | D(i) = P0(tt2) |
324 | | |
325 | | #endif /* !WOLFSSL_SM3_SMALL */ |
326 | | |
327 | | #ifdef SM3_PREPROCESSOR_CALC_T |
328 | | /* Rotate left by r. */ |
329 | | #define ROTL(v, r) (((word32)(v) << (r)) | ((word32)(v) >> (32 - (r)))) |
330 | | /* First table value - rotated by 0. */ |
331 | | #define T_00_00(i) 0x79cc4519 |
332 | | /* Table value calculation for iterations: 1 - 16. */ |
333 | | #define T_01_15(i) ROTL(0x79cc4519, (i)) |
334 | | /* Table value calculation for iterations: 16 - 63. */ |
335 | | #define T_16_63(i) ROTL(0x7a879d8a, (i)) |
336 | | /* Table value for iteration 32 - rotated by 0. */ |
337 | | #define T_32_32(i) 0x7a879d8a |
338 | | |
339 | | /* Constants for each iteration. */ |
340 | | static const FLASH_QUALIFIER word32 SM3_T[64] = { |
341 | | T_00_00( 0), T_01_15( 1), T_01_15( 2), T_01_15( 3), |
342 | | #if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM3) |
343 | | T_01_15( 4), T_01_15( 5), T_01_15( 6), T_01_15( 7), |
344 | | T_01_15( 8), T_01_15( 9), T_01_15(10), T_01_15(11), |
345 | | T_01_15(12), T_01_15(13), T_01_15(14), T_01_15(15), |
346 | | #endif |
347 | | T_16_63(16), T_16_63(17), T_16_63(18), T_16_63(19), |
348 | | #if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM3) |
349 | | T_16_63(20), T_16_63(21), T_16_63(22), T_16_63(23), |
350 | | T_16_63(24), T_16_63(25), T_16_63(26), T_16_63(27), |
351 | | T_16_63(28), T_16_63(29), T_16_63(30), T_16_63(31), |
352 | | T_32_32( 0), T_16_63( 1), T_16_63( 2), T_16_63( 3), |
353 | | T_16_63( 4), T_16_63( 5), T_16_63( 6), T_16_63( 7), |
354 | | T_16_63( 8), T_16_63( 9), T_16_63(10), T_16_63(11), |
355 | | T_16_63(12), T_16_63(13), T_16_63(14), T_16_63(15), |
356 | | T_16_63(16), T_16_63(17), T_16_63(18), T_16_63(19), |
357 | | T_16_63(20), T_16_63(21), T_16_63(22), T_16_63(23), |
358 | | T_16_63(24), T_16_63(25), T_16_63(26), T_16_63(27), |
359 | | T_16_63(28), T_16_63(29), T_16_63(30), T_16_63(31), |
360 | | #endif |
361 | | }; |
362 | | #else |
363 | | /* Constants for each iteration. */ |
364 | | static const FLASH_QUALIFIER word32 SM3_T[64] = { |
365 | | 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb, |
366 | | #if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM3) |
367 | | 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc, |
368 | | 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce, |
369 | | 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6, |
370 | | #endif |
371 | | 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, |
372 | | #if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM3) |
373 | | 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, |
374 | | 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, |
375 | | 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5, |
376 | | 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53, |
377 | | 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d, |
378 | | 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4, |
379 | | 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43, |
380 | | 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, |
381 | | 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, |
382 | | 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, |
383 | | 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5 |
384 | | #endif |
385 | | }; |
386 | | #endif |
387 | | |
388 | | |
389 | | /* Compression process applied to a block of data and current values. |
390 | | * |
391 | | * 32-bit words are in appropriate order for CPU. |
392 | | * |
393 | | * @param [in, out] sm3 SM3 hash object. |
394 | | * @param [in] block Block of data that is 512 bits (64 byte) long. |
395 | | */ |
396 | | static void sm3_compress_c(wc_Sm3* sm3, const word32* block) |
397 | 0 | { |
398 | 0 | #if !defined(__aarch64__) || !defined(WOLFSSL_ARMASM_CRYPTO_SM3) |
399 | |
|
400 | | #ifdef WOLFSSL_SM3_SMALL |
401 | | #ifndef WOLFSSL_SMALL_STACK |
402 | | word32 w[68]; |
403 | | #else |
404 | | word32* w = sm3->w; |
405 | | #endif |
406 | | word32 v[8]; |
407 | | int j; |
408 | | |
409 | | /* Copy in first 16 32-bit words. */ |
410 | | XMEMCPY(w, block, WC_SM3_BLOCK_SIZE); |
411 | | |
412 | | /* Copy values into temporary. */ |
413 | | v[0] = sm3->v[0]; |
414 | | v[1] = sm3->v[1]; |
415 | | v[2] = sm3->v[2]; |
416 | | v[3] = sm3->v[3]; |
417 | | v[4] = sm3->v[4]; |
418 | | v[5] = sm3->v[5]; |
419 | | v[6] = sm3->v[6]; |
420 | | v[7] = sm3->v[7]; |
421 | | |
422 | | /* Do 64 iterations of the compression process. */ |
423 | | for (j = 0; j < 64; j++) { |
424 | | word32 ss1; |
425 | | word32 ss2; |
426 | | word32 tt1; |
427 | | word32 tt2; |
428 | | |
429 | | /* Need 4 ahead of the expanded message value. */ |
430 | | if ((j + 4) >= 16) { |
431 | | w[j+4] = W(w, j+4); |
432 | | } |
433 | | /* Compression function. */ |
434 | | ss1 = rotlFixed((rotlFixed(v[0], 12) + v[4] + SM3_T[j]), 7); |
435 | | ss2 = ss1 ^ rotlFixed(v[0], 12); |
436 | | tt1 = FF(v[0], v[1], v[2], j) + v[3] + ss2 + (w[j] ^ w[j+4]); |
437 | | tt2 = GG(v[4], v[5], v[6], j) + v[7] + ss1 + w[j]; |
438 | | v[3] = v[2]; |
439 | | v[2] = rotlFixed(v[1], 9); |
440 | | v[1] = v[0]; |
441 | | v[0] = tt1; |
442 | | v[7] = v[6]; |
443 | | v[6] = rotlFixed(v[5], 19); |
444 | | v[5] = v[4]; |
445 | | v[4] = P0(tt2); |
446 | | } |
447 | | |
448 | | /* XOR result into current values. */ |
449 | | sm3->v[0] ^= v[0]; |
450 | | sm3->v[1] ^= v[1]; |
451 | | sm3->v[2] ^= v[2]; |
452 | | sm3->v[3] ^= v[3]; |
453 | | sm3->v[4] ^= v[4]; |
454 | | sm3->v[5] ^= v[5]; |
455 | | sm3->v[6] ^= v[6]; |
456 | | sm3->v[7] ^= v[7]; |
457 | | #else |
458 | | #ifndef WOLFSSL_SMALL_STACK |
459 | | word32 w[68]; |
460 | | #else |
461 | 0 | word32* w = sm3->w; |
462 | 0 | #endif |
463 | 0 | word32 v[8]; |
464 | 0 | word32 ss1; |
465 | 0 | word32 ss2; |
466 | 0 | word32 tt1; |
467 | 0 | word32 tt2; |
468 | 0 | int j; |
469 | | |
470 | | /* Copy in first 16 32-bit words. */ |
471 | 0 | XMEMCPY(w, block, WC_SM3_BLOCK_SIZE); |
472 | | |
473 | | /* Copy values into temporary. */ |
474 | 0 | v[0] = sm3->v[0]; |
475 | 0 | v[1] = sm3->v[1]; |
476 | 0 | v[2] = sm3->v[2]; |
477 | 0 | v[3] = sm3->v[3]; |
478 | 0 | v[4] = sm3->v[4]; |
479 | 0 | v[5] = sm3->v[5]; |
480 | 0 | v[6] = sm3->v[6]; |
481 | 0 | v[7] = sm3->v[7]; |
482 | | |
483 | | /* First 8 iterations of the compression process. */ |
484 | 0 | SM3_ITER_INIT(0, 0); SM3_ITER_INIT(1, 0); |
485 | 0 | SM3_ITER_INIT(2, 0); SM3_ITER_INIT(3, 0); |
486 | 0 | SM3_ITER_INIT(4, 0); SM3_ITER_INIT(5, 0); |
487 | 0 | SM3_ITER_INIT(6, 0); SM3_ITER_INIT(7, 0); |
488 | | /* Next 8 iterations of the compression process. |
489 | | * Last 4 iterations need to to calculate expansion values. |
490 | | */ |
491 | 0 | SM3_ITER_INIT(0, 8); SM3_ITER_INIT(1, 8); |
492 | 0 | SM3_ITER_INIT(2, 8); SM3_ITER_INIT(3, 8); |
493 | 0 | SM3_ITER(4, 8); SM3_ITER(5, 8); SM3_ITER(6, 8); SM3_ITER(7, 8); |
494 | | /* Remaining iterations of the compression process. |
495 | | * Different FF and GG operations. |
496 | | */ |
497 | 0 | for (j = 16; j < 64; j += 8) { |
498 | 0 | SM3_ITER(0, j); SM3_ITER(1, j); SM3_ITER(2, j); SM3_ITER(3, j); |
499 | 0 | SM3_ITER(4, j); SM3_ITER(5, j); SM3_ITER(6, j); SM3_ITER(7, j); |
500 | 0 | } |
501 | | |
502 | | /* XOR result into current values. */ |
503 | 0 | sm3->v[0] ^= v[0]; |
504 | 0 | sm3->v[1] ^= v[1]; |
505 | 0 | sm3->v[2] ^= v[2]; |
506 | 0 | sm3->v[3] ^= v[3]; |
507 | 0 | sm3->v[4] ^= v[4]; |
508 | 0 | sm3->v[5] ^= v[5]; |
509 | 0 | sm3->v[6] ^= v[6]; |
510 | 0 | sm3->v[7] ^= v[7]; |
511 | 0 | #endif |
512 | |
|
513 | | #else |
514 | | |
515 | | word32 w[WC_SM3_BLOCK_SIZE / 4]; |
516 | | word32 v[8]; |
517 | | word32* wt; |
518 | | word32* vt = v; |
519 | | |
520 | | /* Use passed in buffer if aligned. */ |
521 | | if (((size_t)block & 0x3) == 0) { |
522 | | wt = (word32*)block; |
523 | | } |
524 | | /* Copy into aligned buffer. */ |
525 | | else { |
526 | | XMEMCPY(w, block, WC_SM3_BLOCK_SIZE); |
527 | | wt = w; |
528 | | } |
529 | | |
530 | | /* Copy values into temporary. */ |
531 | | v[0] = sm3->v[3]; |
532 | | v[1] = sm3->v[2]; |
533 | | v[2] = sm3->v[1]; |
534 | | v[3] = sm3->v[0]; |
535 | | v[4] = sm3->v[7]; |
536 | | v[5] = sm3->v[6]; |
537 | | v[6] = sm3->v[5]; |
538 | | v[7] = sm3->v[4]; |
539 | | |
540 | | /* Do 64 iterations of the compression process. */ |
541 | | __asm__ volatile ( |
542 | | "LD1 {v8.16b-v11.16b}, [%[w]], #64\n\t" |
543 | | "LD1 {v0.16b, v1.16b}, [%[v]]\n\t" |
544 | | "LD1 {v3.16b}, [%[t]]\n\t" |
545 | | |
546 | | /* Compression function. */ |
547 | | "MOV v12.16b, v8.16b\n\t" |
548 | | "MOV v13.16b, v9.16b\n\t" |
549 | | "MOV v14.16b, v10.16b\n\t" |
550 | | "MOV v15.16b, v11.16b\n\t" |
551 | | "MOV x4, #3\n\t" |
552 | | "2:\n\t" |
553 | | "EOR v6.16b, v13.16b, v12.16b\n\t" |
554 | | |
555 | | "EXT v7.16b, v7.16b, v3.16b, #4\n\t" |
556 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
557 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
558 | | /* Vm=v6[0], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
559 | | "SM3TT1A v0.4S, v2.4S, v6.S[0]\n\t" |
560 | | /* Vm=v4[0], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
561 | | "SM3TT2A v1.4S, v2.4S, v12.S[0]\n\t" |
562 | | |
563 | | "EXT v7.16b, v7.16b, v3.16b, #8\n\t" |
564 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
565 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
566 | | /* Vm=v6[1], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
567 | | "SM3TT1A v0.4S, v2.4S, v6.S[1]\n\t" |
568 | | /* Vm=v4[1], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
569 | | "SM3TT2A v1.4S, v2.4S, v12.S[1]\n\t" |
570 | | |
571 | | "EXT v7.16b, v7.16b, v3.16b, #12\n\t" |
572 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
573 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
574 | | /* Vm=v6[2], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
575 | | "SM3TT1A v0.4S, v2.4S, v6.S[2]\n\t" |
576 | | /* Vm=v4[2], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
577 | | "SM3TT2A v1.4S, v2.4S, v12.S[2]\n\t" |
578 | | |
579 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
580 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v3.4s\n\t" |
581 | | /* Vm=v6[3], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
582 | | "SM3TT1A v0.4S, v2.4S, v6.S[3]\n\t" |
583 | | /* Vm=v4[3], Vn=ss1, V d=[v[7],v[6],v[5],v[4]] */ |
584 | | "SM3TT2A v1.4S, v2.4S, v12.S[3]\n\t" |
585 | | |
586 | | "SUBS x4, x4, #1\n\t" |
587 | | "MOV v12.16B, v13.16B\n\t" |
588 | | "SHL v4.4S, v3.4S, #4\n\t" |
589 | | "MOV v13.16B, v14.16B\n\t" |
590 | | "SRI v4.4S, v3.4S, #28\n\t" |
591 | | "MOV v14.16B, v15.16B\n\t" |
592 | | "MOV v3.16B, v4.16B\n\t" |
593 | | "BNE 2b\n\t" |
594 | | |
595 | | /* W[-13] */ |
596 | | "EXT v4.16b, v8.16b, v9.16b, #12\n\t" |
597 | | /* W[-9] */ |
598 | | "EXT v5.16b, v9.16b, v10.16b, #12\n\t" |
599 | | /* W[-6] */ |
600 | | "EXT v6.16b, v10.16b, v11.16b, #8\n\t" |
601 | | /* Vd=W-16=v8, Vn=W-9=v5, Vm=W-4=v11 */ |
602 | | "SM3PARTW1 v8.4S, v5.4S, v11.4S\n\t" |
603 | | /* Vd=v8, Vn=W-6=v6, Vm=W-13=v4 */ |
604 | | "SM3PARTW2 v8.4S, v6.4S, v4.4S\n\t" |
605 | | |
606 | | /* Compression function. */ |
607 | | "EOR v6.16b, v8.16b, v11.16b\n\t" |
608 | | |
609 | | "EXT v7.16b, v7.16b, v3.16b, #4\n\t" |
610 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
611 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
612 | | /* Vm=v6[0], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
613 | | "SM3TT1A v0.4S, v2.4S, v6.S[0]\n\t" |
614 | | /* Vm=v11[0], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
615 | | "SM3TT2A v1.4S, v2.4S, v11.S[0]\n\t" |
616 | | |
617 | | "EXT v7.16b, v7.16b, v3.16b, #8\n\t" |
618 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
619 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
620 | | /* Vm=v6[1], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
621 | | "SM3TT1A v0.4S, v2.4S, v6.S[1]\n\t" |
622 | | /* Vm=v11[1], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
623 | | "SM3TT2A v1.4S, v2.4S, v11.S[1]\n\t" |
624 | | |
625 | | "EXT v7.16b, v7.16b, v3.16b, #12\n\t" |
626 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
627 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
628 | | /* Vm=v6[2], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
629 | | "SM3TT1A v0.4S, v2.4S, v6.S[2]\n\t" |
630 | | /* Vm=v11[2], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
631 | | "SM3TT2A v1.4S, v2.4S, v11.S[2]\n\t" |
632 | | |
633 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
634 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v3.4s\n\t" |
635 | | /* Vm=v6[3], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
636 | | "SM3TT1A v0.4S, v2.4S, v6.S[3]\n\t" |
637 | | /* Vm=v11[3], Vn=ss1, V d=[v[7],v[6],v[5],v[4]] */ |
638 | | "SM3TT2A v1.4S, v2.4S, v11.S[3]\n\t" |
639 | | |
640 | | "MOV x4, #3\n\t" |
641 | | "LD1 {v3.16b}, [%[t2]]\n\t" |
642 | | "1:\n\t" |
643 | | /* W[-13] */ |
644 | | "EXT v4.16b, v9.16b, v10.16b, #12\n\t" |
645 | | /* W[-9] */ |
646 | | "EXT v5.16b, v10.16b, v11.16b, #12\n\t" |
647 | | /* W[-6] */ |
648 | | "EXT v6.16b, v11.16b, v8.16b, #8\n\t" |
649 | | /* Vd=W-16=v9, Vn=W-9=v5, Vm=W-4=v8 */ |
650 | | "SM3PARTW1 v9.4S, v5.4S, v8.4S\n\t" |
651 | | /* Vd=v9, Vn=W-6=v6, Vm=W-13=v4 */ |
652 | | "SM3PARTW2 v9.4S, v6.4S, v4.4S\n\t" |
653 | | |
654 | | /* W[-13] */ |
655 | | "EXT v4.16b, v10.16b, v11.16b, #12\n\t" |
656 | | /* W[-9] */ |
657 | | "EXT v5.16b, v11.16b, v8.16b, #12\n\t" |
658 | | /* W[-6] */ |
659 | | "EXT v6.16b, v8.16b, v9.16b, #8\n\t" |
660 | | /* Vd=W-16=v10, Vn=W-9=v5, Vm=W-4=v9 */ |
661 | | "SM3PARTW1 v10.4S, v5.4S, v9.4S\n\t" |
662 | | /* Vd=v10, Vn=W-6=v6, Vm=W-13=v4 */ |
663 | | "SM3PARTW2 v10.4S, v6.4S, v4.4S\n\t" |
664 | | |
665 | | /* W[-13] */ |
666 | | "EXT v4.16b, v11.16b, v8.16b, #12\n\t" |
667 | | /* W[-9] */ |
668 | | "EXT v5.16b, v8.16b, v9.16b, #12\n\t" |
669 | | /* W[-6] */ |
670 | | "EXT v6.16b, v9.16b, v10.16b, #8\n\t" |
671 | | /* Vd=W-16=v11, Vn=W-9=v5, Vm=W-4=v10 */ |
672 | | "SM3PARTW1 v11.4S, v5.4S, v10.4S\n\t" |
673 | | /* Vd=v11, Vn=W-6=v6, Vm=W-13=v4 */ |
674 | | "SM3PARTW2 v11.4S, v6.4S, v4.4S\n\t" |
675 | | |
676 | | "MOV v12.16B, v8.16B\n\t" |
677 | | /* W[-13] */ |
678 | | "EXT v4.16b, v8.16b, v9.16b, #12\n\t" |
679 | | /* W[-9] */ |
680 | | "EXT v5.16b, v9.16b, v10.16b, #12\n\t" |
681 | | /* W[-6] */ |
682 | | "EXT v6.16b, v10.16b, v11.16b, #8\n\t" |
683 | | /* Vd=W-16=v8, Vn=W-9=v5, Vm=W-4=v11 */ |
684 | | "SM3PARTW1 v8.4S, v5.4S, v11.4S\n\t" |
685 | | /* Vd=v8, Vn=W-6=v6, Vm=W-13=v4 */ |
686 | | "SM3PARTW2 v8.4S, v6.4S, v4.4S\n\t" |
687 | | |
688 | | "MOV x5, #4\n\t" |
689 | | "MOV v13.16B, v9.16B\n\t" |
690 | | "MOV v14.16B, v10.16B\n\t" |
691 | | "MOV v15.16B, v11.16B\n\t" |
692 | | "MOV v4.16B, v8.16B\n\t" |
693 | | "3:\n\t" |
694 | | "EOR v6.16b, v13.16b, v12.16b\n\t" |
695 | | |
696 | | "EXT v7.16b, v7.16b, v3.16b, #4\n\t" |
697 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
698 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
699 | | /* Vm=v6[0], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
700 | | "SM3TT1B v0.4S, v2.4S, v6.S[0]\n\t" |
701 | | /* Vm=v12[0], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
702 | | "SM3TT2B v1.4S, v2.4S, v12.S[0]\n\t" |
703 | | |
704 | | "EXT v7.16b, v7.16b, v3.16b, #8\n\t" |
705 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
706 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
707 | | /* Vm=v6[1], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
708 | | "SM3TT1B v0.4S, v2.4S, v6.S[1]\n\t" |
709 | | /* Vm=v12[1], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
710 | | "SM3TT2B v1.4S, v2.4S, v12.S[1]\n\t" |
711 | | |
712 | | "EXT v7.16b, v7.16b, v3.16b, #12\n\t" |
713 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
714 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v7.4s\n\t" |
715 | | /* Vm=v6[2], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
716 | | "SM3TT1B v0.4S, v2.4S, v6.S[2]\n\t" |
717 | | /* Vm=v12[2], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
718 | | "SM3TT2B v1.4S, v2.4S, v12.S[2]\n\t" |
719 | | |
720 | | /* Vm[3]=v[4], Vn[3]=v[0], Vd=v2, Va[3]=SM3_T[j] */ |
721 | | "SM3SS1 v2.4S, v0.4s, v1.4s, v3.4s\n\t" |
722 | | /* Vm=v6[3], Vn=ss1, Vd=[v[3],v[2],v[1],v[0]] */ |
723 | | "SM3TT1B v0.4S, v2.4S, v6.S[3]\n\t" |
724 | | /* Vm=v12[3], Vn=ss1, Vd=[v[7],v[6],v[5],v[4]] */ |
725 | | "SM3TT2B v1.4S, v2.4S, v12.S[3]\n\t" |
726 | | |
727 | | "SUBS x5, x5, #1\n\t" |
728 | | "MOV v12.16B, v13.16B\n\t" |
729 | | "SHL v7.4S, v3.4S, #4\n\t" |
730 | | "MOV v13.16B, v14.16B\n\t" |
731 | | "SRI v7.4S, v3.4S, #28\n\t" |
732 | | "MOV v14.16B, v15.16B\n\t" |
733 | | "MOV v3.16B, v7.16B\n\t" |
734 | | "MOV v15.16B, v4.16B\n\t" |
735 | | "BNE 3b\n\t" |
736 | | |
737 | | "SUBS x4, x4, #1\n\t" |
738 | | "BNE 1b\n\t" |
739 | | |
740 | | /* Store result of hash. */ |
741 | | "ST1 {v0.16b, v1.16b}, [%[v]]\n\t" |
742 | | : |
743 | | : [w] "r" (wt), [v] "r" (vt), [t] "r" (SM3_T), [t2] "r" (SM3_T + 4) |
744 | | : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", |
745 | | "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", |
746 | | "x4", "x5" |
747 | | ); |
748 | | |
749 | | /* XOR result into current values. */ |
750 | | sm3->v[0] ^= v[3]; |
751 | | sm3->v[1] ^= v[2]; |
752 | | sm3->v[2] ^= v[1]; |
753 | | sm3->v[3] ^= v[0]; |
754 | | sm3->v[4] ^= v[7]; |
755 | | sm3->v[5] ^= v[6]; |
756 | | sm3->v[6] ^= v[5]; |
757 | | sm3->v[7] ^= v[4]; |
758 | | |
759 | | #endif |
760 | 0 | } |
761 | | |
762 | | /* Compression process applied to a multiplie blocks of data and current values. |
763 | | * |
764 | | * @param [in, out] sm3 SM3 hash object. |
765 | | * @param [in] data Data to compress as a byte array. |
766 | | * @param [in] len Number of bytes of data. |
767 | | */ |
768 | | static void sm3_compress_len_c(wc_Sm3* sm3, const byte* data, word32 len) |
769 | 0 | { |
770 | 0 | do { |
771 | | /* Compress one block at a time. */ |
772 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
773 | 0 | word32* buffer = sm3->buffer; |
774 | | /* Convert big-endian bytes to little-endian 32-bit words. */ |
775 | 0 | BSWAP32_16(buffer, data); |
776 | | /* Process block of data. */ |
777 | 0 | SM3_COMPRESS(sm3, buffer); |
778 | | #else |
779 | | /* Process block of data. */ |
780 | | SM3_COMPRESS(sm3, (word32*)data); |
781 | | #endif |
782 | | /* Move over processed data. */ |
783 | 0 | data += WC_SM3_BLOCK_SIZE; |
784 | 0 | len -= WC_SM3_BLOCK_SIZE; |
785 | 0 | } |
786 | 0 | while (len > 0); |
787 | 0 | } |
788 | | |
789 | | /* Finalize last block of hash. |
790 | | * |
791 | | * @param [in, out] sm3 SM4 hash object. |
792 | | * @return 0 on success. |
793 | | */ |
794 | | static void sm3_final_c(wc_Sm3* sm3) |
795 | 0 | { |
796 | | /* Convert length in bytes to length in bits and store in buffer. */ |
797 | 0 | sm3->buffer[14] = (sm3->hiLen << 3) | (sm3->loLen >> (32 - 3)); |
798 | 0 | sm3->buffer[15] = (sm3->loLen << 3); |
799 | | |
800 | | /* Process last block. */ |
801 | 0 | SM3_COMPRESS(sm3, sm3->buffer); |
802 | | /* No data unprocessed. */ |
803 | 0 | sm3->buffLen = 0; |
804 | 0 | } |
805 | | |
806 | | /******************************************************************************/ |
807 | | |
808 | | /* Initialize the state of the hash. |
809 | | * |
810 | | * @param [in] sm3 SM3 hash object. |
811 | | */ |
812 | | static WC_INLINE void sm3_init(wc_Sm3* sm3) |
813 | 0 | { |
814 | 0 | SM3_SET_COMPRESS(); |
815 | | |
816 | | /* Set IV into values. */ |
817 | 0 | sm3->v[0] = 0x7380166f; |
818 | 0 | sm3->v[1] = 0x4914b2b9; |
819 | 0 | sm3->v[2] = 0x172442d7; |
820 | 0 | sm3->v[3] = 0xda8a0600; |
821 | 0 | sm3->v[4] = 0xa96f30bc; |
822 | 0 | sm3->v[5] = 0x163138aa; |
823 | 0 | sm3->v[6] = 0xe38dee4d; |
824 | 0 | sm3->v[7] = 0xb0fb0e4e; |
825 | | |
826 | | /* No cached message data. */ |
827 | 0 | sm3->buffLen = 0; |
828 | | /* No message data seen. */ |
829 | 0 | sm3->loLen = 0; |
830 | 0 | sm3->hiLen = 0; |
831 | 0 | } |
832 | | |
833 | | /* Initialize the SM3 hash object. |
834 | | * |
835 | | * @param [in, out] sm3 SM3 hash object. |
836 | | * @param [in] heap Dynamic memory hint. |
837 | | * @param [in] devId Device ID. |
838 | | * @return 0 on success. |
839 | | * @return BAD_FUNC_ARG when sm3 is NULL. |
840 | | */ |
841 | | int wc_InitSm3(wc_Sm3* sm3, void* heap, int devId) |
842 | 0 | { |
843 | 0 | int ret = 0; |
844 | |
|
845 | 0 | #ifndef WOLF_CRYPTO_CB_SM |
846 | 0 | (void)devId; |
847 | 0 | #endif |
848 | | |
849 | | /* Validate parameters. */ |
850 | 0 | if (sm3 == NULL) { |
851 | 0 | ret = BAD_FUNC_ARG; |
852 | 0 | } |
853 | |
|
854 | 0 | if (ret == 0) { |
855 | | /* Initialize hash state. */ |
856 | 0 | sm3_init(sm3); |
857 | |
|
858 | 0 | sm3->heap = heap; |
859 | | #ifdef WOLF_CRYPTO_CB_SM |
860 | | /* Cache the device to offer hashing to. */ |
861 | | sm3->devId = devId; |
862 | | sm3->devCtx = NULL; |
863 | | #endif |
864 | 0 | #ifdef WOLFSSL_HASH_FLAGS |
865 | 0 | sm3->flags = 0; |
866 | 0 | #endif |
867 | 0 | } |
868 | |
|
869 | 0 | return ret; |
870 | 0 | } |
871 | | |
872 | | /* Increase the number of bytes in the message being hashed. |
873 | | * |
874 | | * @param [in, out] sm3 SM3 hash object. |
875 | | * @param [in] len Number of new bytes of message. |
876 | | */ |
877 | | static WC_INLINE void sm3_add_to_len(wc_Sm3* sm3, word32 len) |
878 | 0 | { |
879 | 0 | sm3->loLen += len; |
880 | | /* Detect overflow. */ |
881 | 0 | if (sm3->loLen < len) { |
882 | 0 | sm3->hiLen++; |
883 | 0 | } |
884 | 0 | } |
885 | | |
886 | | /* Buffer message bytes. |
887 | | * |
888 | | * Processes the block if filled. |
889 | | * |
890 | | * @param [in, out] sm3 SM3 hash object. |
891 | | * @param [in] data Message data. |
892 | | * @param [in] len Length of message data not processed yet. |
893 | | * @param [out] used Number of bytes used. |
894 | | */ |
895 | | static WC_INLINE void sm3_buffer_msg_bytes(wc_Sm3* sm3, const byte* data, |
896 | | word32 len, word32* used) |
897 | 0 | { |
898 | 0 | word32 add = min(len, WC_SM3_BLOCK_SIZE - sm3->buffLen); |
899 | 0 | unsigned char* buffer = (unsigned char*)sm3->buffer; |
900 | | |
901 | | /* Put in bytes in big-endian order. */ |
902 | 0 | XMEMCPY(buffer + sm3->buffLen, data, add); |
903 | | |
904 | | /* Update count of bytes buffered. */ |
905 | 0 | sm3->buffLen += add; |
906 | | /* Check for full block. */ |
907 | 0 | if (sm3->buffLen == WC_SM3_BLOCK_SIZE) { |
908 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
909 | | /* Convert big-endian bytes to little-endian 32-bit words. */ |
910 | 0 | BSWAP32_16(buffer, buffer); |
911 | 0 | #endif |
912 | | /* Process block of data. */ |
913 | 0 | SM3_COMPRESS(sm3, sm3->buffer); |
914 | | /* No more cached data. */ |
915 | 0 | sm3->buffLen = 0; |
916 | 0 | } |
917 | |
|
918 | 0 | *used = add; |
919 | 0 | } |
920 | | |
921 | | /* Update the hash with more message data. |
922 | | * |
923 | | * @param [in, out] sm3 SM3 hash object. |
924 | | * @param [in] data Message data. |
925 | | * @param [in] len Number of bytes in message data. |
926 | | * @return 0 on success. |
927 | | * @return BAD_FUNC_ARG when sm3 is NULL or len > 0 and data is NULL. |
928 | | * @return BAD_COND_E when internal state invalid. |
929 | | */ |
930 | | int wc_Sm3Update(wc_Sm3* sm3, const byte* data, word32 len) |
931 | 0 | { |
932 | 0 | int ret = 0; |
933 | | |
934 | | /* Validate parameters. */ |
935 | 0 | if ((sm3 == NULL) || ((len > 0) && (data == NULL))) { |
936 | 0 | ret = BAD_FUNC_ARG; |
937 | 0 | } |
938 | |
|
939 | | #ifdef DEBUG_WOLFSSL |
940 | | /* Check internal state - buffer length is a valid value. */ |
941 | | if ((ret == 0) && (sm3->buffLen >= WC_SM3_BLOCK_SIZE)) { |
942 | | ret = BAD_COND_E; |
943 | | } |
944 | | #endif |
945 | |
|
946 | | #ifdef WOLF_CRYPTO_CB_SM |
947 | | if (ret == 0) { |
948 | | #ifndef WOLF_CRYPTO_CB_FIND |
949 | | if (sm3->devId != INVALID_DEVID) |
950 | | #endif |
951 | | { |
952 | | ret = wc_CryptoCb_Sm3Hash(sm3, data, len, NULL); |
953 | | if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { |
954 | | return ret; |
955 | | } |
956 | | ret = 0; |
957 | | } |
958 | | } |
959 | | #endif |
960 | |
|
961 | 0 | if ((ret == 0) && (len > 0)) { |
962 | | /* Always add to length. */ |
963 | 0 | sm3_add_to_len(sm3, len); |
964 | | |
965 | | /* Check for unprocessed data. */ |
966 | 0 | if (sm3->buffLen > 0) { |
967 | 0 | word32 used = 0; |
968 | | |
969 | | /* Add to existing message bytes. */ |
970 | 0 | sm3_buffer_msg_bytes(sm3, data, len, &used); |
971 | 0 | len -= used; |
972 | 0 | data += used; |
973 | 0 | } |
974 | 0 | } |
975 | 0 | if ((ret == 0) && (len >= WC_SM3_BLOCK_SIZE)) { |
976 | | /* Mask out bits that are not a multiple of 64. */ |
977 | 0 | word32 l = len & (word32)(~(WC_SM3_BLOCK_SIZE - 1)); |
978 | | |
979 | | /* Compress complete blocks of data. */ |
980 | 0 | SM3_COMPRESS_LEN(sm3, data, l); |
981 | 0 | data += l; |
982 | 0 | len -= l; |
983 | 0 | } |
984 | |
|
985 | 0 | if ((ret == 0) && (len > 0)) { |
986 | | /* Store unprocessed data less than a block. */ |
987 | 0 | XMEMCPY(sm3->buffer, data, len); |
988 | 0 | sm3->buffLen = len; |
989 | 0 | } |
990 | |
|
991 | 0 | return ret; |
992 | 0 | } |
993 | | |
994 | | /* Last block with data to be hashed. |
995 | | * |
996 | | * @param [in, out] sm3 SM3 hash object. |
997 | | */ |
998 | | static WC_INLINE void sm3_last_data_block(wc_Sm3* sm3) |
999 | 0 | { |
1000 | 0 | byte* buffer8 = (byte*)sm3->buffer; |
1001 | | |
1002 | | /* Fill rest of block with 0s. */ |
1003 | 0 | XMEMSET(buffer8 + sm3->buffLen, 0, WC_SM3_BLOCK_SIZE - sm3->buffLen); |
1004 | |
|
1005 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
1006 | | /* Convert big-endian bytes to little-endian 32-bit words. */ |
1007 | 0 | BSWAP32_16(sm3->buffer, sm3->buffer); |
1008 | 0 | #endif |
1009 | | /* Process last data block. */ |
1010 | 0 | SM3_COMPRESS(sm3, sm3->buffer); |
1011 | | |
1012 | | /* No data unprocessed. */ |
1013 | 0 | sm3->buffLen = 0; |
1014 | 0 | } |
1015 | | |
1016 | | /* Hash last block. |
1017 | | * |
1018 | | * @param [in, out] sm3 SM3 hash object. |
1019 | | * @return 0 on success. |
1020 | | */ |
1021 | | static WC_INLINE void sm3_last_block(wc_Sm3* sm3) |
1022 | 0 | { |
1023 | 0 | byte* buffer8 = (byte*)sm3->buffer; |
1024 | | |
1025 | | /* Fill rest of block with 0s except 64-bits of length. */ |
1026 | 0 | XMEMSET(buffer8 + sm3->buffLen, 0, WC_SM3_PAD_SIZE - sm3->buffLen); |
1027 | |
|
1028 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
1029 | | /* Reverse as many words as had data in them. (Reverse of 0 is 0). */ |
1030 | 0 | ByteReverseWords(sm3->buffer, sm3->buffer, |
1031 | 0 | (sm3->buffLen + 3) & (word32)(~3)); |
1032 | 0 | #endif |
1033 | | /* Hash last block. */ |
1034 | 0 | sm3_final(sm3); |
1035 | 0 | } |
1036 | | |
1037 | | /* Get raw hash. |
1038 | | * |
1039 | | * @param [in, out] sm3 SM3 hash object. |
1040 | | * @param [out] hash Final hash value. |
1041 | | * @return 0 on success. |
1042 | | * @return BAD_FUNC_ARG when sm3 or hash is NULL. |
1043 | | */ |
1044 | | int wc_Sm3FinalRaw(wc_Sm3* sm3, byte* hash) |
1045 | 0 | { |
1046 | 0 | int ret = 0; |
1047 | | |
1048 | | /* Validate parameters. */ |
1049 | 0 | if ((sm3 == NULL) || (hash == NULL)) { |
1050 | 0 | ret = BAD_FUNC_ARG; |
1051 | 0 | } |
1052 | |
|
1053 | 0 | if (ret == 0) { |
1054 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
1055 | | /* Convert little-endian 32-bit words to big-endian bytes. */ |
1056 | 0 | BSWAP32_8(hash, sm3->v); |
1057 | | #else |
1058 | | XMEMCPY(hash, sm3->v, WC_SM3_DIGEST_SIZE); |
1059 | | #endif |
1060 | 0 | } |
1061 | |
|
1062 | 0 | return ret; |
1063 | 0 | } |
1064 | | |
1065 | | /* Finalize hash. |
1066 | | * |
1067 | | * Initializes the state once final hash produced. |
1068 | | * |
1069 | | * @param [in, out] sm3 SM3 hash object. |
1070 | | * @param [out] hash Final hash value. |
1071 | | * @return 0 on success. |
1072 | | * @return BAD_FUNC_ARG when sm3 or hash is NULL. |
1073 | | */ |
1074 | | int wc_Sm3Final(wc_Sm3* sm3, byte* hash) |
1075 | 0 | { |
1076 | 0 | int ret = 0; |
1077 | | |
1078 | | /* Validate parameters. */ |
1079 | 0 | if ((sm3 == NULL) || (hash == NULL)) { |
1080 | 0 | ret = BAD_FUNC_ARG; |
1081 | 0 | } |
1082 | |
|
1083 | | #ifdef WOLF_CRYPTO_CB_SM |
1084 | | if (ret == 0) { |
1085 | | #ifndef WOLF_CRYPTO_CB_FIND |
1086 | | if (sm3->devId != INVALID_DEVID) |
1087 | | #endif |
1088 | | { |
1089 | | ret = wc_CryptoCb_Sm3Hash(sm3, NULL, 0, hash); |
1090 | | if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { |
1091 | | return ret; |
1092 | | } |
1093 | | ret = 0; |
1094 | | } |
1095 | | } |
1096 | | #endif |
1097 | |
|
1098 | 0 | if (ret == 0) { |
1099 | 0 | byte* buffer8 = (byte*)sm3->buffer; |
1100 | | |
1101 | | /* Append a "1" bit to end of message. */ |
1102 | 0 | buffer8[sm3->buffLen++] = 0x80; |
1103 | 0 | if (sm3->buffLen > WC_SM3_PAD_SIZE) { |
1104 | | /* Hash the last data block. |
1105 | | * l + 1 > 448 bits so need to do this block first. */ |
1106 | 0 | sm3_last_data_block(sm3); |
1107 | 0 | } |
1108 | 0 | } |
1109 | 0 | if (ret == 0) { |
1110 | | /* Hash the last block. Data length added to end. */ |
1111 | 0 | sm3_last_block(sm3); |
1112 | | /* Get the hash. */ |
1113 | 0 | #ifdef LITTLE_ENDIAN_ORDER |
1114 | | /* Convert little-endian 32-bit words to big-endian bytes. */ |
1115 | 0 | BSWAP32_8(hash, sm3->v); |
1116 | | #else |
1117 | | XMEMCPY(hash, sm3->v, WC_SM3_DIGEST_SIZE); |
1118 | | #endif |
1119 | | |
1120 | | /* Initialize hash state. */ |
1121 | 0 | sm3_init(sm3); |
1122 | 0 | } |
1123 | |
|
1124 | 0 | return ret; |
1125 | 0 | } |
1126 | | |
1127 | | /* Dispose of any dynamically allocated data in object. |
1128 | | * |
1129 | | * @param [in, out] sm3 SM3 hash object. |
1130 | | */ |
1131 | | void wc_Sm3Free(wc_Sm3* sm3) |
1132 | 0 | { |
1133 | | #if defined(WOLF_CRYPTO_CB_SM) && \ |
1134 | | defined(WOLF_CRYPTO_CB_FREE) |
1135 | | /* Check we have something to work with. */ |
1136 | | if (sm3 != NULL) { |
1137 | | #ifndef WOLF_CRYPTO_CB_FIND |
1138 | | if (sm3->devId != INVALID_DEVID) |
1139 | | #endif |
1140 | | { |
1141 | | /* Let the device release any state it holds for this context. */ |
1142 | | (void)wc_CryptoCb_Free(sm3->devId, WC_ALGO_TYPE_HASH, |
1143 | | WC_HASH_TYPE_SM3, 0, sm3); |
1144 | | } |
1145 | | } |
1146 | | #endif |
1147 | 0 | (void)sm3; |
1148 | 0 | } |
1149 | | |
1150 | | /* Copy the SM3 hash object. |
1151 | | * |
1152 | | * Assumes src and dst are valid pointers. |
1153 | | * |
1154 | | * @param [in] src SM3 hash object to copy. |
1155 | | * @param [in, out] dst SM3 hash object to copy into. |
1156 | | */ |
1157 | | /* Defined below; used by wc_Sm3GetHash() for a device aware copy. */ |
1158 | | int wc_Sm3Copy(const wc_Sm3* src, wc_Sm3* dst); |
1159 | | |
1160 | | static void sm3_copy(const wc_Sm3* src, wc_Sm3* dst) |
1161 | 0 | { |
1162 | 0 | XMEMCPY(dst, src, sizeof(wc_Sm3)); |
1163 | 0 | #ifdef WOLFSSL_HASH_FLAGS |
1164 | | /* Mark destination as a copy. */ |
1165 | 0 | dst->flags |= WC_HASH_FLAG_ISCOPY; |
1166 | 0 | #endif |
1167 | 0 | } |
1168 | | |
1169 | | /* Get the final hash for the message data seen. |
1170 | | * |
1171 | | * More message data can be added to this object. |
1172 | | * |
1173 | | * @param [in] sm3 SM3 hash object. |
1174 | | * @param [out] hash Final hash value for message data up to this point. |
1175 | | * @return 0 on success. |
1176 | | * @return BAD_FUNC_ARG when sm3 or hash is NULL. |
1177 | | */ |
1178 | | int wc_Sm3GetHash(wc_Sm3* sm3, byte* hash) |
1179 | 0 | { |
1180 | 0 | int ret = 0; |
1181 | 0 | #ifdef WOLFSSL_SMALL_STACK |
1182 | 0 | wc_Sm3* sm3Copy = NULL; |
1183 | | #else |
1184 | | wc_Sm3 sm3Copy[1]; |
1185 | | #endif |
1186 | | |
1187 | | /* Validate parameters. */ |
1188 | 0 | if ((sm3 == NULL) || (hash == NULL)) { |
1189 | 0 | ret = BAD_FUNC_ARG; |
1190 | 0 | } |
1191 | |
|
1192 | 0 | #ifdef WOLFSSL_SMALL_STACK |
1193 | 0 | if (ret == 0) { |
1194 | | /* Allocate a SM3 hash object to do final on. */ |
1195 | 0 | sm3Copy = (wc_Sm3*)XMALLOC(sizeof(wc_Sm3), sm3->heap, |
1196 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
1197 | 0 | if (sm3Copy == NULL) { |
1198 | 0 | ret = MEMORY_E; |
1199 | 0 | } |
1200 | 0 | } |
1201 | 0 | #endif |
1202 | 0 | if (ret == 0) { |
1203 | 0 | ret = wc_Sm3Copy(sm3, sm3Copy); |
1204 | 0 | } |
1205 | 0 | if (ret == 0) { |
1206 | | /* Calculate final hash value. */ |
1207 | 0 | ret = wc_Sm3Final(sm3Copy, hash); |
1208 | | /* Dispose of hash object. */ |
1209 | 0 | wc_Sm3Free(sm3Copy); |
1210 | 0 | } |
1211 | |
|
1212 | 0 | #ifdef WOLFSSL_SMALL_STACK |
1213 | 0 | if (sm3Copy != NULL) { |
1214 | | /* Free the SM3 hash object that was the copy. */ |
1215 | 0 | XFREE(sm3Copy, sm3->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1216 | 0 | } |
1217 | 0 | #endif |
1218 | |
|
1219 | 0 | return ret; |
1220 | 0 | } |
1221 | | |
1222 | | /* Copy the SM3 hash object. |
1223 | | * |
1224 | | * @param [in] src SM3 hash object to copy. |
1225 | | * @param [in, out] dst SM3 hash object to copy into. |
1226 | | * @return 0 on success. |
1227 | | * @return BAD_FUNC_ARG when src or dst is NULL. |
1228 | | */ |
1229 | | int wc_Sm3Copy(const wc_Sm3* src, wc_Sm3* dst) |
1230 | 0 | { |
1231 | 0 | int ret = 0; |
1232 | | |
1233 | | /* Validate parameters. */ |
1234 | 0 | if ((src == NULL) || (dst == NULL)) { |
1235 | 0 | ret = BAD_FUNC_ARG; |
1236 | 0 | } |
1237 | |
|
1238 | | #if defined(WOLF_CRYPTO_CB_SM) && \ |
1239 | | defined(WOLF_CRYPTO_CB_COPY) |
1240 | | if (ret == 0) { |
1241 | | #ifndef WOLF_CRYPTO_CB_FIND |
1242 | | if (src->devId != INVALID_DEVID) |
1243 | | #endif |
1244 | | { |
1245 | | /* The struct copy below would alias the device context, leaving |
1246 | | * two objects sharing one handle. Let the device duplicate it. */ |
1247 | | ret = wc_CryptoCb_Copy(src->devId, WC_ALGO_TYPE_HASH, |
1248 | | WC_HASH_TYPE_SM3, (void*)src, (void*)dst); |
1249 | | if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { |
1250 | | return ret; |
1251 | | } |
1252 | | /* Fall through to software when the device declines. */ |
1253 | | ret = 0; |
1254 | | } |
1255 | | } |
1256 | | #endif |
1257 | |
|
1258 | 0 | if (ret == 0) { |
1259 | 0 | sm3_copy(src, dst); |
1260 | 0 | } |
1261 | |
|
1262 | 0 | return ret; |
1263 | 0 | } |
1264 | | |
1265 | | #ifdef WOLFSSL_HASH_FLAGS |
1266 | | /* Set the flags of the SM3 hash object. |
1267 | | * |
1268 | | * @param [in, out] sm3 SM3 hash object. |
1269 | | * @param [in] flags Flags to set. |
1270 | | * @return 0 on success. |
1271 | | */ |
1272 | | int wc_Sm3SetFlags(wc_Sm3* sm3, word32 flags) |
1273 | 0 | { |
1274 | 0 | if (sm3 != NULL) { |
1275 | 0 | sm3->flags = flags; |
1276 | 0 | } |
1277 | 0 | return 0; |
1278 | 0 | } |
1279 | | |
1280 | | /* Get the flags of the SM3 hash object. |
1281 | | * |
1282 | | * @param [in] sm3 SM3 hash object. |
1283 | | * @param [out] flags Flags from hash object. |
1284 | | * @return 0 on success. |
1285 | | */ |
1286 | | int wc_Sm3GetFlags(const wc_Sm3* sm3, word32* flags) |
1287 | 0 | { |
1288 | 0 | if ((sm3 != NULL) && (flags != NULL)) { |
1289 | 0 | *flags = sm3->flags; |
1290 | 0 | } |
1291 | 0 | return 0; |
1292 | 0 | } |
1293 | | #endif |
1294 | | |
1295 | | #endif /* WOLFSSL_SM3 */ |
1296 | | |