Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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