Coverage Report

Created: 2026-07-22 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/wolfcrypt/src/sm2.c
Line
Count
Source
1
/* sm2.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
/* Based on 'SM2 Digital Signature Algorithm draft-shen-sm2-ecdsa-02'
23
 *   https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02
24
 */
25
26
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
27
28
#if defined(WOLFSSL_SM2) && defined(HAVE_ECC)
29
30
#include <wolfssl/wolfcrypt/sm2.h>
31
#include <wolfssl/wolfcrypt/sp.h>
32
#include <wolfssl/wolfcrypt/hash.h>
33
#include <wolfssl/wolfcrypt/coding.h>
34
#include <wolfssl/wolfcrypt/asn.h>
35
#include <wolfssl/wolfcrypt/logging.h>
36
#include <wolfssl/wolfcrypt/logging.h>
37
38
#ifdef NO_INLINE
39
    #include <wolfssl/wolfcrypt/misc.h>
40
#else
41
    #define WOLFSSL_MISC_INCLUDED
42
    #include <wolfcrypt/src/misc.c>
43
#endif
44
45
/* Maximum number of signature generations to attempt before giving up. */
46
0
#define ECC_SM2_MAX_SIG_GEN     64
47
48
#ifndef NO_HASH_WRAPPER
49
/* Convert hex string to binary and hash it.
50
 *
51
 * @param [in] hash      Hash algorithm object.
52
 * @param [in] hashType  Type of hash to perform.
53
 * @param [in] hexIn     Hexadecimal string.
54
 * @param [in] hexSz     Number of characters to hash.
55
 * @param [in] tmp       Buffer to encode into.
56
 * @return  0 on success
57
 * @return  MEMORY_E on dynamic memory allocation failure.
58
 */
59
static int ecc_sm2_digest_hashin(wc_HashAlg* hash, enum wc_HashType hashType,
60
    const char* hexIn, int hexSz, byte* tmp)
61
0
{
62
0
    int err = 0;
63
0
    word32 tmpSz;
64
65
    /* Number of bytes in binary as type word32. */
66
0
    tmpSz = (word32)hexSz;
67
0
    if (err == 0) {
68
        /* Convert hexadecimal string to binary. */
69
0
        err = Base16_Decode((const byte*)hexIn, tmpSz, tmp, &tmpSz);
70
0
    }
71
0
    if (err == 0) {
72
        /* Update the hash with the binary data. */
73
0
        err = wc_HashUpdate(hash, hashType, tmp, tmpSz);
74
0
    }
75
76
0
    return err;
77
0
}
78
79
/* Calculate ZA with hash type specified for sign/verify.
80
 *
81
 * 5.1.4.4:
82
 *   ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA)
83
 *
84
 * @param [in]  id        ID of A to be hashed.
85
 * @param [in]  idSz      Size of ID of A in bytes.
86
 * @param [in]  hash      Hash algorithm object.
87
 * @param [in]  hashType  Hash type to use.
88
 * @param [in]  key       SM2 ECC key that has already been setup.
89
 * @param [out] out       Buffer to hold final digest.
90
 * @return  0 on success.
91
 * @return  Negative on failure.
92
 */
93
static int _ecc_sm2_calc_za(const byte *id, word16 idSz,
94
    wc_HashAlg* hash, enum wc_HashType hashType, ecc_key* key, byte* out)
95
0
{
96
0
    int err = 0;
97
0
    byte entla[2];  /* RFC draft states ID size is always encoded in 2 bytes. */
98
0
    word16 sz = 0;
99
0
#ifdef WOLFSSL_SMALL_STACK
100
0
    byte* xA = NULL;
101
0
    byte* yA = NULL;
102
#else
103
    /* Modify if more than one SM2 curve. */
104
    byte xA[33];
105
    byte yA[33];
106
#endif
107
0
    word32 xASz;
108
0
    word32 yASz;
109
110
    /* Get ID of A size in bits. */
111
0
    sz = idSz * WOLFSSL_BIT_SIZE;
112
    /* Set big-endian 16-bit word. */
113
0
    entla[0] = (byte)(sz >> WOLFSSL_BIT_SIZE);
114
0
    entla[1] = (byte)(sz & 0xFF);
115
116
#ifdef DEBUG_ECC_SM2
117
    WOLFSSL_MSG("ENTLA");
118
    WOLFSSL_BUFFER(entla, 2);
119
#endif
120
121
    /* Get ordinate size. */
122
0
    xASz = yASz = (word32)wc_ecc_size(key);
123
0
#ifdef WOLFSSL_SMALL_STACK
124
    /* Allocate memory for the x-ordinate. */
125
0
    xA = (byte*)XMALLOC(xASz  + 1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
126
0
    if (xA == NULL) {
127
0
        err = MEMORY_E;
128
0
    }
129
0
    if (err == 0) {
130
        /* Allocate memory for the y-ordinate. */
131
0
        yA = (byte*)XMALLOC(yASz  + 1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
132
0
        if (yA == NULL) {
133
0
            err = MEMORY_E;
134
0
        }
135
0
    }
136
0
#endif
137
138
139
0
    if (err == 0) {
140
        /* Hash the ENTLA - length of ID of A. */
141
0
        err = wc_HashUpdate(hash, hashType, (byte*)&entla, 2);
142
0
    }
143
0
    if (err == 0) {
144
        /* Hash the ID of A. */
145
0
        err = wc_HashUpdate(hash, hashType, id, idSz);
146
0
    }
147
148
0
    if (err == 0) {
149
        /* Hash the a coefficient of the curve. */
150
0
        err = ecc_sm2_digest_hashin(hash, hashType, key->dp->Af,
151
0
                (int)XSTRLEN(key->dp->Af), xA);
152
0
    }
153
0
    if (err == 0) {
154
        /* Hash the b coefficient of the curve. */
155
0
        err = ecc_sm2_digest_hashin(hash, hashType, key->dp->Bf,
156
0
                (int)XSTRLEN(key->dp->Bf), xA);
157
0
    }
158
0
    if (err == 0) {
159
        /* Hash the x-ordinate of the base point. */
160
0
        err = ecc_sm2_digest_hashin(hash, hashType, key->dp->Gx,
161
0
                (int)XSTRLEN(key->dp->Gx), xA);
162
0
    }
163
0
    if (err == 0) {
164
        /* Hash the y-ordinate of the base point. */
165
0
        err = ecc_sm2_digest_hashin(hash, hashType, key->dp->Gy,
166
0
                (int)XSTRLEN(key->dp->Gy), xA);
167
0
    }
168
169
0
    if (err == 0) {
170
        /* Get the x and y ordinates. */
171
0
        err = wc_ecc_export_public_raw(key, xA, &xASz, yA, &yASz);
172
0
    }
173
0
    if (err == 0) {
174
        /* Hash the x-ordinate of the public key. */
175
0
        err = wc_HashUpdate(hash, hashType, xA, xASz);
176
0
    }
177
0
#ifdef WOLFSSL_SMALL_STACK
178
0
    XFREE(xA, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
179
0
#endif
180
181
0
    if (err == 0) {
182
        /* Hash the y-ordinate of the public key. */
183
0
        err = wc_HashUpdate(hash, hashType, yA, yASz);
184
0
    }
185
0
#ifdef WOLFSSL_SMALL_STACK
186
0
    XFREE(yA, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
187
0
#endif
188
189
0
    if (err == 0) {
190
        /* Output the hash - ZA. */
191
0
        err = wc_HashFinal(hash, hashType, out);
192
0
    }
193
#ifdef DEBUG_ECC_SM2
194
    if (err == 0) {
195
        WOLFSSL_MSG("ZA");
196
        WOLFSSL_BUFFER(out, wc_HashGetDigestSize(hashType));
197
    }
198
#endif
199
200
0
    return err;
201
0
}
202
203
/* Calculate SM2 hash of the type specified for sign/verify.
204
 *
205
 * 5.2.1, A2:
206
 *   Hash Out = Hash(ZA || M)
207
 *
208
 * @param [in]  za        ZA to be hashed.
209
 * @param [in]  zaSz      Size of ZA in bytes.
210
 * @param [in]  msg       Message to be signed.
211
 * @param [in]  msgSz     Size of message in bytes.
212
 * @param [in]  hash      Hash algorithm object.
213
 * @param [in]  hashType  Hash type to use.
214
 * @param [out] out       Buffer to hold final digest.
215
 * @return  0 on success.
216
 * @return  Negative on failure.
217
 */
218
static int _ecc_sm2_calc_msg_hash(const byte* za, int zaSz, const byte* msg,
219
    int msgSz, wc_HashAlg* hash, enum wc_HashType hashType, byte* out)
220
0
{
221
0
    int err;
222
223
    /* Initialize the hash for new operation. */
224
0
    err = wc_HashInit_ex(hash, hashType, NULL, 0);
225
0
    if (err == 0) {
226
        /* Hash ZA. */
227
0
        err = wc_HashUpdate(hash, hashType, za, (word32)zaSz);
228
0
    }
229
0
    if (err == 0) {
230
        /* Hash the message. */
231
0
        err = wc_HashUpdate(hash, hashType, msg, (word32)msgSz);
232
0
    }
233
0
    if (err == 0) {
234
        /* Output the hash. */
235
0
        err = wc_HashFinal(hash, hashType, out);
236
0
    }
237
#ifdef DEBUG_ECC_SM2
238
    if (err == 0) {
239
        WOLFSSL_MSG("Hv(ZA || M)");
240
        WOLFSSL_BUFFER(out, wc_HashGetDigestSize(hashType));
241
    }
242
#endif
243
244
0
    return err;
245
0
}
246
247
/* Create SM2 hash of the type specified for sign/verify.
248
 *
249
 * 5.1.4.4:
250
 *   ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA)
251
 * 5.2.1:
252
 *   A1: M~=ZA || M
253
 *   A2: e=Hv(M~)
254
 *
255
 * @param [in]  id        ID of A to be hashed.
256
 * @param [in]  idSz      Size of ID of A in bytes.
257
 * @param [in]  msg       Message to be signed.
258
 * @param [in]  msgSz     Size of message in bytes.
259
 * @param [in]  hashType  Hash type to use.
260
 * @param [out] out       Buffer to hold final digest.
261
 * @param [in]  outSz     Size of output buffer in bytes.
262
 * @param [in]  key       SM2 ECC key that has already been setup.
263
 * @return  0 on success.
264
 * @return  BAD_FUNC_ARG when key, out, msg or id is NULL.
265
 * @return  BAD_FUNC_ARG when hash type is not supported.
266
 * @return  BUFFER_E when hash size is larger than output size.
267
 * @return  MEMORY_E on dynamic memory allocation failure.
268
 */
269
int wc_ecc_sm2_create_digest(const byte *id, word16 idSz,
270
    const byte* msg, int msgSz, enum wc_HashType hashType, byte* out, int outSz,
271
    ecc_key* key)
272
0
{
273
0
    int err = 0;
274
0
    int hashSz = 0;
275
0
#ifdef WOLFSSL_SMALL_STACK
276
0
    wc_HashAlg* hash = NULL;
277
#else
278
    wc_HashAlg hash[1];
279
#endif
280
0
    int hash_inited = 0;
281
282
    /* Validate parameters. */
283
0
    if ((key == NULL) || (key->dp == NULL) || (out == NULL) || (msg == NULL) ||
284
0
            (id == NULL)) {
285
0
        err = BAD_FUNC_ARG;
286
0
    }
287
    /* Get hash size. */
288
0
    if ((err == 0) && ((hashSz = wc_HashGetDigestSize(hashType)) < 0)) {
289
0
        err = BAD_FUNC_ARG;
290
0
    }
291
    /* Check hash size fits in output. */
292
0
    if ((err == 0) && (hashSz > outSz)) {
293
0
        err = BUFFER_E;
294
0
    }
295
296
0
#ifdef WOLFSSL_SMALL_STACK
297
0
    if (err == 0) {
298
0
        hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), key->heap,
299
0
            DYNAMIC_TYPE_HASHES);
300
0
        if (hash == NULL) {
301
0
            err = MEMORY_E;
302
0
        }
303
0
    }
304
0
#endif
305
306
0
    if (err == 0) {
307
        /* Initialize hash algorithm object. */
308
0
        err = wc_HashInit_ex(hash, hashType, key->heap, 0);
309
0
    }
310
311
0
    if (err == 0) {
312
0
        hash_inited = 1;
313
0
    }
314
315
    /* Calculate ZA. */
316
0
    if (err == 0) {
317
0
        err = _ecc_sm2_calc_za(id, idSz, hash, hashType, key, out);
318
0
    }
319
    /* Calculate message hash. */
320
0
    if (err == 0) {
321
0
        err = _ecc_sm2_calc_msg_hash(out, hashSz, msg, msgSz, hash, hashType,
322
0
            out);
323
0
    }
324
325
    /* Dispose of allocated data. */
326
0
    if (hash_inited) {
327
0
        (void)wc_HashFree(hash, hashType);
328
0
    }
329
0
#ifdef WOLFSSL_SMALL_STACK
330
0
    XFREE(hash, key->heap, DYNAMIC_TYPE_HASHES);
331
0
#endif
332
0
    return err;
333
0
}
334
#endif /* NO_HASH_WRAPPER */
335
336
/* Make a key on the SM2 curve.
337
 *
338
 * @param [in]  rng    Random number generator.
339
 * @param [out] key    ECC key to hold generated key.
340
 * @param [in]  flags  Flags to set against ECC key.
341
 * @return  0 on success.
342
 */
343
int wc_ecc_sm2_make_key(WC_RNG* rng, ecc_key* key, int flags)
344
0
{
345
0
    return wc_ecc_make_key_ex2(rng, 32, key, ECC_SM2P256V1, flags);
346
0
}
347
348
/* Create a shared secret from the private key and peer's public key.
349
 *
350
 * @param [in]      priv    Private key.
351
 * @param [in]      pub     Peer's public key.
352
 * @param [out]     out     Array containing secret.
353
 * @param [in, out] outLen  On in, length of array in bytes.
354
 *                          On out, number of bytes in secret.
355
 */
356
int wc_ecc_sm2_shared_secret(ecc_key* priv, ecc_key* pub, byte* out,
357
    word32* outLen)
358
0
{
359
0
    return wc_ecc_shared_secret(priv, pub, out, outLen);
360
0
}
361
362
#ifdef HAVE_ECC_SIGN
363
#ifndef WOLFSSL_SP_MATH
364
/* Calculate r and s of signature.
365
 *
366
 * @param [in]  x      Private key.
367
 * @param [in]  px     Ephemeral point's x-ordinate.
368
 * @param [in]  k      Ephemeral private key.
369
 * @param [in]  e      Hash of message.
370
 * @param [in]  order  Order of curve.
371
 * @param [in]  b      Blinding value.
372
 * @param [out] r      'r' value of signature.
373
 * @param [out] s      's' value of signature.
374
 * @return  MP_OKAY on success.
375
 * @return  MP_MEM when dynamic memory allocation fails.
376
 */
377
static int _ecc_sm2_calc_r_s(mp_int* x, mp_int* px, mp_int* k, mp_int* e,
378
    mp_int* order, mp_int* b, mp_int* r, mp_int* s)
379
0
{
380
0
    int err;
381
382
    /* r = p->x + e */
383
0
    err = mp_addmod_ct(px, e, order, r);
384
    /* Check r != 0 */
385
0
    if ((err == MP_OKAY) && mp_iszero(r)) {
386
0
        err = MP_ZERO_E;
387
0
    }
388
    /* Calc r + k */
389
0
    if (err == MP_OKAY) {
390
0
        err = mp_addmod_ct(r, k, order, s);
391
0
    }
392
    /* Check r + k != 0 */
393
0
    if ((err == MP_OKAY) && mp_iszero(s)) {
394
0
        err = MP_ZERO_E;
395
0
    }
396
397
    /* s = x.r */
398
0
    if (err == MP_OKAY) {
399
0
        err = mp_mulmod(r, x, order, s);
400
0
    }
401
402
    /* x' = x + 1 */
403
0
    if (err == MP_OKAY) {
404
0
        err = mp_add_d(x, 1, x);
405
0
    }
406
    /* x'' = x'.b = (x+1).b */
407
0
    if (err == MP_OKAY) {
408
0
        err = mp_mulmod(x, b, order, x);
409
0
    }
410
    /* x''' = 1/x'' = 1/((x+1).b) */
411
0
    if (err == MP_OKAY) {
412
0
        err = mp_invmod(x, order, x);
413
0
    }
414
415
    /* k' = k * x''' = k / ((x+1).b) */
416
0
    if (err == MP_OKAY) {
417
0
        err = mp_mulmod(k, x, order, k);
418
0
    }
419
420
    /* s' = s * x''' = x.r / ((x+1).b) */
421
0
    if (err == MP_OKAY) {
422
0
        err = mp_mulmod(s, x, order, s);
423
0
    }
424
    /* s'' = k' - s' = (k - x.r) / ((x+1).b) */
425
0
    if (err == MP_OKAY) {
426
0
        err = mp_submod_ct(k, s, order, s);
427
0
    }
428
    /* s''' = s'' * b = (k - x.r) / (x+1) */
429
0
    if (err == MP_OKAY) {
430
0
        err = mp_mulmod(s, b, order, s);
431
0
    }
432
433
0
    return err;
434
0
}
435
#endif
436
437
/* Calculate the signature from the hash with a key on the SM2 curve.
438
 *
439
 * Use wc_ecc_sm2_create_digest to calculate the digest.
440
 *
441
 * @param [in]  hash    Array of bytes holding hash value.
442
 * @param [in]  hashSz  Size of hash in bytes.
443
 * @param [in]  rng     Random number generator.
444
 * @param [in]  key     ECC private key.
445
 * @param [out] r       'r' part of signature as an MP integer.
446
 * @param [out] s       's' part of signature as an MP integer.
447
 * @return  MP_OKAY on success.
448
 * @return  ECC_BAD_ARGE_E when hash, r, s, key or rng is NULL.
449
 * @return  ECC_BAD_ARGE_E when key is not on SM2 curve.
450
 */
451
int wc_ecc_sm2_sign_hash_ex(const byte* hash, word32 hashSz, WC_RNG* rng,
452
    ecc_key* key, mp_int* r, mp_int* s)
453
0
{
454
0
    int err = MP_OKAY;
455
0
#ifndef WOLFSSL_SP_MATH
456
0
    mp_int* x = NULL;
457
0
    mp_int* e = NULL;
458
0
    mp_int* b = NULL;
459
0
    mp_int* order = NULL;
460
0
#ifdef WOLFSSL_SMALL_STACK
461
0
    ecc_key* pub = NULL;
462
0
    mp_int* data = NULL;
463
#else
464
    ecc_key pub[1];
465
    mp_int data[4];
466
#endif
467
0
    int i;
468
0
#endif
469
470
    /* Validate parameters. */
471
0
    if ((hash == NULL) || (r == NULL) || (s == NULL) || (key == NULL) ||
472
0
            (key->dp == NULL) || (rng == NULL)) {
473
0
        err = BAD_FUNC_ARG;
474
0
    }
475
    /* SM2 signature must be with a key on the SM2 curve. */
476
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
477
0
        (key->idx != ECC_CUSTOM_IDX)) {
478
0
        err = BAD_FUNC_ARG;
479
0
    }
480
481
#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_SM2)
482
    if ((err == MP_OKAY) && (key->dp->id == ECC_SM2P256V1)) {
483
        /* Use optimized code in SP to perform signing. */
484
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
485
        err = sp_ecc_sign_sm2_256(hash, hashSz, rng, key->k, r, s, NULL,
486
            key->heap);
487
        RESTORE_VECTOR_REGISTERS();
488
        return err;
489
    }
490
#endif
491
492
0
#ifndef WOLFSSL_SP_MATH
493
0
#ifdef WOLFSSL_SMALL_STACK
494
0
    if (err == MP_OKAY) {
495
        /* Allocate ECC key. */
496
0
        pub = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC);
497
0
        if (pub == NULL) {
498
0
            err = MEMORY_E;
499
0
        }
500
0
    }
501
0
    if (err == MP_OKAY) {
502
        /* Allocate MP integers. */
503
0
        data = (mp_int*)XMALLOC(sizeof(mp_int) * 4, key->heap,
504
0
            DYNAMIC_TYPE_ECC);
505
0
        if (data == NULL) {
506
0
            err = MEMORY_E;
507
0
        }
508
0
    }
509
0
#endif
510
0
    if (err == MP_OKAY) {
511
0
        x = data;
512
0
        e = data + 1;
513
0
        b = data + 2;
514
0
        order = data + 3;
515
0
    }
516
517
    /* Initialize MP integers needed. */
518
0
    if (err == MP_OKAY) {
519
0
        err = mp_init_multi(x, e, b, order, NULL, NULL);
520
0
    }
521
0
    if (err == MP_OKAY) {
522
        /* Initialize ephemeral key. */
523
0
        err = wc_ecc_init_ex(pub, key->heap, INVALID_DEVID);
524
0
        if (err == MP_OKAY) {
525
           /* Load the order into an MP integer for generating blinding value.
526
            */
527
0
            err = mp_read_radix(order, key->dp->order, MP_RADIX_HEX);
528
0
        }
529
0
        if (err == MP_OKAY) {
530
            /* Convert hash to a number. */
531
0
            err = mp_read_unsigned_bin(e, hash, hashSz);
532
0
        }
533
0
        if (err == MP_OKAY) {
534
            /* Reduce the hash value to that of the order once. */
535
0
            err = mp_mod(e, order, e);
536
0
        }
537
0
        if (err == MP_OKAY) {
538
0
            do {
539
                /* Generate blinding value. */
540
0
                err = wc_ecc_gen_k(rng, 32, b, order);
541
0
            }
542
0
            while (err == MP_ZERO_E);
543
544
            /* Try generating a signature a number of times. */
545
0
            for (i = 0; (err == MP_OKAY) && (i < ECC_SM2_MAX_SIG_GEN); i++) {
546
                /* Make a new ephemeral key. */
547
0
                err = wc_ecc_sm2_make_key(rng, pub, WC_ECC_FLAG_NONE);
548
0
                if (err == MP_OKAY) {
549
                    /* Copy the private key into temporary. */
550
0
                    err = mp_copy(wc_ecc_key_get_priv(key), x);
551
0
                }
552
0
                if (err == MP_OKAY) {
553
                    /* Calculate R and S. */
554
0
                    err = _ecc_sm2_calc_r_s(x, pub->pubkey.x,
555
0
                        wc_ecc_key_get_priv(pub), e, order, b, r, s);
556
0
                }
557
                /* Done if it worked. */
558
0
                if (err == MP_OKAY) {
559
0
                    break;
560
0
                }
561
                /* Try again if random values not usable. */
562
0
                if (err == MP_ZERO_E) {
563
0
                    err = MP_OKAY;
564
0
                }
565
0
            }
566
567
            /* Dispose of emphemeral key. */
568
0
            wc_ecc_free(pub);
569
0
        }
570
571
        /* Dispose of temproraries - x and b are sensitive data. */
572
0
        mp_forcezero(x);
573
0
        mp_forcezero(b);
574
0
        mp_free(e);
575
0
        mp_free(order);
576
0
    }
577
578
0
#ifdef WOLFSSL_SMALL_STACK
579
0
    if (key != NULL) {
580
0
        XFREE(pub, key->heap, DYNAMIC_TYPE_ECC);
581
0
        XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
582
0
    }
583
0
#endif
584
#else
585
    (void)hashSz;
586
587
    if (err == MP_OKAY) {
588
        err = NOT_COMPILED_IN;
589
    }
590
#endif
591
592
0
    return err;
593
0
}
594
595
/* Calculate the signature from the hash with a key on the SM2 curve.
596
 *
597
 * Use wc_ecc_sm2_create_digest to calculate the digest.
598
 *
599
 * @param [in]  hash    Array of bytes holding hash value.
600
 * @param [in]  hashSz  Size of hash in bytes.
601
 * @param [in]  rng     Random number generator.
602
 * @param [in]  key     ECC private key.
603
 * @param [out] sig     DER encoded DSA signature.
604
 * @param [out] sigSz   On in, size of signature buffer in bytes.
605
 *                      On out, length of signature in bytes.
606
 * @return  MP_OKAY on success.
607
 * @return  ECC_BAD_ARGE_E when hash, r, s, key or rng is NULL.
608
 * @return  ECC_BAD_ARGE_E when key is not on SM2 curve.
609
 */
610
int wc_ecc_sm2_sign_hash(const byte* hash, word32 hashSz, byte* sig,
611
    word32 *sigSz, WC_RNG* rng, ecc_key* key)
612
0
{
613
0
    int err = MP_OKAY;
614
0
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)
615
0
#ifdef WOLFSSL_SMALL_STACK
616
0
    mp_int *r = NULL, *s = NULL;
617
#else
618
    mp_int r[1], s[1];
619
#endif
620
0
#endif
621
622
    /* Validate parameters. */
623
0
    if ((hash == NULL) || (sig == NULL) || (sigSz == NULL) || (key == NULL) ||
624
0
            (key->dp == NULL) || (rng == NULL)) {
625
0
        err = BAD_FUNC_ARG;
626
0
    }
627
    /* SM2 signature must be with a key on the SM2 curve. */
628
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
629
0
        (key->idx != ECC_CUSTOM_IDX)) {
630
0
        err = BAD_FUNC_ARG;
631
0
    }
632
633
0
#ifdef WOLFSSL_SMALL_STACK
634
0
    if (err == MP_OKAY) {
635
        /* Allocate MP integers. */
636
0
        r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
637
0
        if (r == NULL)
638
0
            err = MEMORY_E;
639
0
    }
640
0
    if (err == MP_OKAY) {
641
0
        s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
642
0
        if (s == NULL) {
643
0
            err = MEMORY_E;
644
0
        }
645
0
    }
646
0
#endif
647
    /* Clear out MP integers. */
648
0
#ifdef WOLFSSL_SMALL_STACK
649
0
    if (r != NULL)
650
0
#endif
651
0
        XMEMSET(r, 0, sizeof(mp_int));
652
0
#ifdef WOLFSSL_SMALL_STACK
653
0
    if (s != NULL)
654
0
#endif
655
0
        XMEMSET(s, 0, sizeof(mp_int));
656
657
    /* Initialize MP integers. */
658
0
    if (err == MP_OKAY)
659
0
        err = mp_init_multi(r, s, NULL, NULL, NULL, NULL);
660
    /* Generate signature into numbers. */
661
0
    if (err == MP_OKAY)
662
0
        err = wc_ecc_sm2_sign_hash_ex(hash, hashSz, rng, key, r, s);
663
664
    /* Encode r and s in DER DSA signature format. */
665
0
    if (err == MP_OKAY)
666
0
        err = StoreECC_DSA_Sig(sig, sigSz, r, s);
667
668
    /* Dispose of temporaries. */
669
0
    mp_clear(r);
670
0
    mp_clear(s);
671
672
0
#ifdef WOLFSSL_SMALL_STACK
673
    /* Free allocated data. */
674
0
    if (key != NULL) {
675
0
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
676
0
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
677
0
    }
678
0
#endif
679
680
0
    return err;
681
0
}
682
#endif
683
684
#ifdef HAVE_ECC_VERIFY
685
#ifndef WOLFSSL_SP_MATH
686
/* Scalar multiply two scalars against respective points and add result.
687
 *
688
 * @param [in]  mG       First point to multiply.
689
 * @param [in]  u1       First scalar.
690
 * @param [in]  mQ       Second point to multiply.
691
 * @param [in]  u2       Second scalar.
692
 * @param [out] mR       Point to store result in.
693
 * @param [in]  a        Coefficient a of the curve.
694
 * @param [in]  modulus  Modulus of curve.
695
 * @param [in]  heap     Dynamic memory allocation hint.
696
 * @return  MP_OKAY on success.
697
 * @return  MP_VAL when a parameter is invalid.
698
 * @return  MP_MEM when dynamic memory allocation fails.
699
 */
700
static int ecc_sm2_mul2add(ecc_point* mG, mp_int* u1, ecc_point* mQ, mp_int* u2,
701
    ecc_point* mR, mp_int* a, mp_int* modulus, void* heap)
702
0
{
703
0
    int err;
704
#ifndef ECC_SHAMIR
705
    mp_digit mp = 0;
706
707
    /* Calculate the Montgomery multiplier. */
708
    err = mp_montgomery_setup(modulus, &mp);
709
    if ((err == 0) && (!mp_iszero(u1))) {
710
        /* Compute mR = u1 * mG + u2 * mQ */
711
712
        /* mG = u1 * mG */
713
        err = wc_ecc_mulmod_ex(u1, mG, mG, a, modulus, 0, heap);
714
        if (err == MP_OKAY) {
715
            /* mQ = u2 * mQ */
716
            err = wc_ecc_mulmod_ex(u2, mQ, mR, a, modulus, 0, heap);
717
        }
718
719
        if (err == MP_OKAY) {
720
            /* mR = mQ + mG */
721
            err = ecc_projective_add_point(mR, mG, mR, a, modulus, mp);
722
        }
723
        if (err == MP_OKAY && mp_iszero(mR->z)) {
724
            /* When all zero then should have done a double instead. */
725
            if (mp_iszero(mR->x) && mp_iszero(mR->y)) {
726
                /* mR = mQ * 2 (mG = mQ) */
727
                err = ecc_projective_dbl_point(mQ, mR, a, modulus, mp);
728
            }
729
            else {
730
                /* When only Z zero then result is infinity. */
731
                err = mp_set(mR->x, 0);
732
                if (err == MP_OKAY)
733
                    err = mp_set(mR->y, 0);
734
                if (err == MP_OKAY)
735
                    err = mp_set(mR->z, 1);
736
            }
737
        }
738
    }
739
    else if (err == 0) {
740
        /* Compute mR = 0 * mG + u2 * mQ  =>  mR = u2 * mQ */
741
        err = wc_ecc_mulmod_ex(u2, mQ, mR, a, modulus, 0, heap);
742
    }
743
744
    /* Convert from Jacobian to affine. */
745
    if (err == MP_OKAY) {
746
        err = ecc_map(mR, modulus, mp);
747
    }
748
#else
749
    /* Use Shamir's trick to compute u1 * mG + u2 * mQ using half the doubles.
750
     */
751
0
    err = ecc_mul2add(mG, u1, mQ, u2, mR, a, modulus, heap);
752
0
#endif /* ECC_SHAMIR */
753
754
0
    return err;
755
0
}
756
#endif /* !WOLFSSL_SP_MATH */
757
758
/* Verify digest of hash(ZA || M) using key on SM2 curve and R and S.
759
 *
760
 * res gets set to 1 on successful verify and 0 on failure
761
 *
762
 * Use wc_ecc_sm2_create_digest to calculate the digest.
763
 *
764
 * @param [in]  r       MP integer holding r part of signature.
765
 * @param [in]  s       MP integer holding s part of signature.
766
 * @param [in]  hash    Array of bytes holding hash value.
767
 * @param [in]  hashSz  Size of hash in bytes.
768
 * @param [out] res     1 on successful verify and 0 on failure.
769
 * @param [in]  key     Public key on SM2 curve.
770
 * @return  0 on success (note this is even when successfully finding verify is
771
 * incorrect)
772
 * @return  BAD_FUNC_ARG when key, res, r, s or hash is NULL.
773
 * @return  MP_VAL when r + s = 0.
774
 * @return  MEMORY_E on dynamic memory allocation failure.
775
 * @return  MP_MEM when dynamic memory allocation fails.
776
 */
777
int wc_ecc_sm2_verify_hash_ex(mp_int *r, mp_int *s, const byte *hash,
778
    word32 hashSz, int *res, ecc_key *key)
779
0
{
780
0
    int err = MP_OKAY;
781
0
#ifndef WOLFSSL_SP_MATH
782
0
    ecc_point* PO = NULL;
783
0
    ecc_point* G = NULL;
784
0
    mp_int* t = NULL;
785
0
    mp_int* e = NULL;
786
0
    mp_int* prime = NULL;
787
0
    mp_int* Af = NULL;
788
0
    mp_int* order = NULL;
789
0
#ifdef WOLFSSL_SMALL_STACK
790
0
    mp_int* data = NULL;
791
#else
792
    mp_int data[5];
793
#endif
794
0
#endif
795
796
    /* Validate parameters. */
797
0
    if ((key == NULL) || (key->dp == NULL) || (res == NULL) || (r == NULL) ||
798
0
            (s == NULL) || (hash == NULL)) {
799
0
        err = BAD_FUNC_ARG;
800
0
    }
801
    /* SM2 signature must be with a key on the SM2 curve. */
802
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
803
0
        (key->idx != ECC_CUSTOM_IDX)) {
804
0
        err = BAD_FUNC_ARG;
805
0
    }
806
807
#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_SM2)
808
    if ((err == MP_OKAY) && (key->dp->id == ECC_SM2P256V1)) {
809
        /* Use optimized code in SP to perform verification. */
810
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
811
        err = sp_ecc_verify_sm2_256(hash, hashSz, key->pubkey.x,
812
            key->pubkey.y, key->pubkey.z, r, s, res, key->heap);
813
        RESTORE_VECTOR_REGISTERS();
814
        return err;
815
    }
816
#endif
817
818
0
#ifndef WOLFSSL_SP_MATH
819
0
    if (res != NULL) {
820
        /* Assume failure. */
821
0
        *res = 0;
822
0
    }
823
824
0
#ifdef WOLFSSL_SMALL_STACK
825
0
    if (err == MP_OKAY) {
826
        /* Allocate temporary MP integer. */
827
0
        data = (mp_int*)XMALLOC(sizeof(mp_int) * 5, key->heap,
828
0
            DYNAMIC_TYPE_ECC);
829
0
        if (data == NULL) {
830
0
            err = MEMORY_E;
831
0
        }
832
0
    }
833
0
#endif
834
0
    if (err == MP_OKAY) {
835
0
        t = data;
836
0
        e = data + 1;
837
0
        prime = data + 2;
838
0
        Af = data + 3;
839
0
        order = data + 4;
840
0
    }
841
842
0
    if (err == MP_OKAY) {
843
        /* Initialize temporary MP integers. */
844
0
        err = mp_init_multi(e, t, prime, Af, order, NULL);
845
0
    }
846
0
    if (err == MP_OKAY) {
847
        /* Get order. */
848
0
        err = mp_read_radix(order, key->dp->order, MP_RADIX_HEX);
849
0
    }
850
    /* B5: calculate t = (r' + s') modn -- if t is 0 then failed */
851
0
    if (err == MP_OKAY) {
852
        /* t = r + s */
853
0
        err = mp_addmod(r, s, order, t);
854
0
    }
855
0
    if (err == MP_OKAY) {
856
        /* Check sum is valid. */
857
0
        if (mp_iszero(t) == MP_YES)
858
0
            err = MP_VAL;
859
0
    }
860
#ifdef DEBUG_ECC_SM2
861
    mp_dump("t = ", t, 0);
862
#endif
863
864
    /* B6: calculate the point (x1', y1')=[s']G + [t]PA */
865
0
    if (err == MP_OKAY) {
866
        /* Create two new points. */
867
0
        PO = wc_ecc_new_point_h(key->heap);
868
0
        if (PO == NULL) {
869
0
            err = MEMORY_E;
870
0
        }
871
0
    }
872
0
    if (err == MP_OKAY) {
873
0
        G  = wc_ecc_new_point_h(key->heap);
874
0
        if (G == NULL) {
875
0
            err = MEMORY_E;
876
0
        }
877
0
    }
878
879
0
    if (err == MP_OKAY) {
880
        /* Get the base point x-ordinate for SM2 curve. */
881
0
        err = mp_read_radix(G->x, key->dp->Gx, MP_RADIX_HEX);
882
0
    }
883
0
    if (err == MP_OKAY) {
884
        /* Get the base point y-ordinate for SM2 curve. */
885
0
        err = mp_read_radix(G->y, key->dp->Gy, MP_RADIX_HEX);
886
0
    }
887
0
    if (err == MP_OKAY) {
888
        /* Base point is in affine so z-ordinate is one. */
889
0
        err = mp_set(G->z, 1);
890
0
    }
891
0
    if (err == MP_OKAY) {
892
        /* Get a coefficient of SM2 curve. */
893
0
        err = mp_read_radix(Af, key->dp->Af, MP_RADIX_HEX);
894
0
    }
895
0
    if (err == MP_OKAY) {
896
        /* Get a prime of SM2 curve. */
897
0
        err = mp_read_radix(prime, key->dp->prime, MP_RADIX_HEX);
898
0
    }
899
#ifdef DEBUG_ECC_SM2
900
    printf("\n");
901
    mp_dump("G->x = ", G->x, 0);
902
    mp_dump("G->y = ", G->y, 0);
903
    mp_dump("s    = ", s, 0);
904
    mp_dump("P->x = ", key->pubkey.x, 0);
905
    mp_dump("P->y = ", key->pubkey.y, 0);
906
    mp_dump("t    = ", t, 0);
907
    mp_dump("Af   = ", Af, 0);
908
    mp_dump("prime= ", prime, 0);
909
#endif
910
0
    if (err == MP_OKAY) {
911
        /* [s']G + [t]PA */
912
0
        err = ecc_sm2_mul2add(G, s, &(key->pubkey), t, PO, Af, prime,
913
0
                key->heap);
914
0
    }
915
#ifdef DEBUG_ECC_SM2
916
    mp_dump("PO->x = ", PO->x, 0);
917
    mp_dump("PO->y = ", PO->y, 0);
918
    printf("\n\n");
919
#endif
920
921
922
    /* B7: calculate R=(e'+x1') modn, if R=r then passed */
923
0
    if (err == MP_OKAY) {
924
        /* Convert hash to an MP integer. */
925
0
        err = mp_read_unsigned_bin(e, hash, hashSz);
926
0
    }
927
0
    if (err == MP_OKAY) {
928
        /* e' + x1' */
929
0
        err = mp_addmod(e, PO->x, order, t);
930
0
    }
931
    /* Calculated value must be same as r. */
932
0
    if (err == MP_OKAY && mp_cmp(t, r) == MP_EQ) {
933
0
        *res = 1;
934
0
    }
935
936
    /* Dispose of allocated points. */
937
0
    if (PO != NULL) {
938
0
        wc_ecc_del_point_h(PO, key->heap);
939
0
    }
940
0
    if (G != NULL) {
941
0
        wc_ecc_del_point_h(G, key->heap);
942
0
    }
943
944
    /* Dispose of allocated MP integers. */
945
0
    if (e != NULL) {
946
0
        mp_free(e);
947
0
    }
948
0
    if (t != NULL) {
949
0
        mp_free(t);
950
0
    }
951
0
    if (prime != NULL) {
952
0
        mp_free(prime);
953
0
    }
954
0
    if (Af != NULL) {
955
0
        mp_free(Af);
956
0
    }
957
0
    if (order != NULL) {
958
0
        mp_free(order);
959
0
    }
960
961
0
#ifdef WOLFSSL_SMALL_STACK
962
    /* Free allocated data. */
963
0
    if (key != NULL) {
964
0
        XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
965
0
    }
966
0
#endif
967
#else
968
    (void)hashSz;
969
970
    if (err == MP_OKAY) {
971
        err = NOT_COMPILED_IN;
972
    }
973
#endif
974
975
0
    return err;
976
0
}
977
978
979
#ifndef NO_ASN
980
/* Verify digest of hash(ZA || M) using key on SM2 curve and encoded signature.
981
 *
982
 * res gets set to 1 on successful verify and 0 on failure
983
 *
984
 * Use wc_ecc_sm2_create_digest to calculate the digest.
985
 *
986
 * @param [in]  sig     DER encoded DSA signature.
987
 * @param [in]  sigSz   Length of signature in bytes.
988
 * @param [in]  hash    Array of bytes holding hash value.
989
 * @param [in]  hashSz  Size of hash in bytes.
990
 * @param [out] res     1 on successful verify and 0 on failure.
991
 * @param [in]  key     Public key on SM2 curve.
992
 * @return  0 on success (note this is even when successfully finding verify is
993
 * incorrect)
994
 * @return  BAD_FUNC_ARG when key, res, sig or hash is NULL.
995
 * @return  MP_VAL when r + s = 0.
996
 * @return  MEMORY_E on dynamic memory allocation failure.
997
 * @return  MP_MEM when dynamic memory allocation fails.
998
 */
999
int wc_ecc_sm2_verify_hash(const byte* sig, word32 sigSz, const byte* hash,
1000
    word32 hashSz, int* res, ecc_key* key)
1001
0
{
1002
0
    int err = 0;
1003
0
#ifdef WOLFSSL_SMALL_STACK
1004
0
    mp_int* r = NULL;
1005
0
    mp_int* s = NULL;
1006
#else
1007
    mp_int r[1];
1008
    mp_int s[1];
1009
#endif
1010
1011
    /* Validate parameters. */
1012
0
    if ((sig == NULL) || (hash == NULL) || (res == NULL) || (key == NULL) ||
1013
0
            (key->dp == NULL)) {
1014
0
        err = BAD_FUNC_ARG;
1015
0
    }
1016
    /* SM2 signature must be with a key on the SM2 curve. */
1017
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
1018
0
        (key->idx != ECC_CUSTOM_IDX)) {
1019
0
        err = BAD_FUNC_ARG;
1020
0
    }
1021
1022
0
#ifdef WOLFSSL_SMALL_STACK
1023
0
    if (err == 0) {
1024
        /* Allocate MP integers. */
1025
0
        r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
1026
0
        if (r == NULL) {
1027
0
            err = MEMORY_E;
1028
0
        }
1029
0
        else {
1030
0
            XMEMSET(r, 0, sizeof(*r));
1031
0
        }
1032
0
    }
1033
0
    if (err == MP_OKAY) {
1034
0
        s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
1035
0
        if (s == NULL) {
1036
0
            err = MEMORY_E;
1037
0
        }
1038
0
        else {
1039
0
            XMEMSET(s, 0, sizeof(*s));
1040
0
        }
1041
0
    }
1042
#else
1043
    XMEMSET(r, 0, sizeof(*r));
1044
    XMEMSET(s, 0, sizeof(*s));
1045
#endif
1046
1047
0
    if (err == 0) {
1048
        /* Decode the signature into R and S. */
1049
0
        err = DecodeECC_DSA_Sig(sig, sigSz, r, s);
1050
0
    }
1051
0
    if (err == 0) {
1052
        /* Verify the signature with hash, key, R and S. */
1053
0
        err = wc_ecc_sm2_verify_hash_ex(r, s, hash, hashSz, res, key);
1054
0
    }
1055
1056
    /* Dispose of allocated data. */
1057
0
#ifdef WOLFSSL_SMALL_STACK
1058
0
    if (r != NULL)
1059
0
#endif
1060
0
    {
1061
0
        mp_free(r);
1062
0
     }
1063
0
#ifdef WOLFSSL_SMALL_STACK
1064
0
    if (s != NULL)
1065
0
#endif
1066
0
    {
1067
0
        mp_free(s);
1068
0
    }
1069
1070
0
#ifdef WOLFSSL_SMALL_STACK
1071
    /* Free allocated data. */
1072
0
    if (key != NULL) {
1073
0
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
1074
0
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
1075
0
    }
1076
0
#endif
1077
1078
0
    return err;
1079
0
}
1080
#endif /* NO_ASN */
1081
#endif /* HAVE_ECC_VERIFY */
1082
1083
#endif /* WOLFSSL_SM2 && HAVE_ECC */