Coverage Report

Created: 2026-09-20 06:33

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