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