Coverage Report

Created: 2025-11-16 07:15

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