Coverage Report

Created: 2025-11-16 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/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
    XFREE(pub, key->heap, DYNAMIC_TYPE_ECC);
580
0
    XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
581
0
#endif
582
#else
583
    (void)hashSz;
584
585
    err = NOT_COMPILED_IN;
586
#endif
587
588
0
    return err;
589
0
}
590
591
/* Calculate the signature from the hash with a key on the SM2 curve.
592
 *
593
 * Use wc_ecc_sm2_create_digest to calculate the digest.
594
 *
595
 * @param [in]  hash    Array of bytes holding hash value.
596
 * @param [in]  hashSz  Size of hash in bytes.
597
 * @param [in]  rng     Random number generator.
598
 * @param [in]  key     ECC private key.
599
 * @param [out] sig     DER encoded DSA signature.
600
 * @param [out] sigSz   On in, size of signature buffer in bytes.
601
 *                      On out, length of signature in bytes.
602
 * @return  MP_OKAY on success.
603
 * @return  ECC_BAD_ARGE_E when hash, r, s, key or rng is NULL.
604
 * @return  ECC_BAD_ARGE_E when key is not on SM2 curve.
605
 */
606
int wc_ecc_sm2_sign_hash(const byte* hash, word32 hashSz, byte* sig,
607
    word32 *sigSz, WC_RNG* rng, ecc_key* key)
608
0
{
609
0
    int err = MP_OKAY;
610
0
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)
611
0
#ifdef WOLFSSL_SMALL_STACK
612
0
    mp_int *r = NULL, *s = NULL;
613
#else
614
    mp_int r[1], s[1];
615
#endif
616
0
#endif
617
618
    /* Validate parameters. */
619
0
    if ((hash == NULL) || (sig == NULL) || (sigSz == NULL) || (key == NULL) ||
620
0
            (key->dp == NULL) || (rng == NULL)) {
621
0
        err = BAD_FUNC_ARG;
622
0
    }
623
    /* SM2 signature must be with a key on the SM2 curve. */
624
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
625
0
        (key->idx != ECC_CUSTOM_IDX)) {
626
0
        err = BAD_FUNC_ARG;
627
0
    }
628
629
0
#ifdef WOLFSSL_SMALL_STACK
630
0
    if (err == MP_OKAY) {
631
        /* Allocate MP integers. */
632
0
        r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
633
0
        if (r == NULL)
634
0
            err = MEMORY_E;
635
0
    }
636
0
    if (err == MP_OKAY) {
637
0
        s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
638
0
        if (s == NULL) {
639
0
            err = MEMORY_E;
640
0
        }
641
0
    }
642
0
#endif
643
    /* Clear out MP integers. */
644
0
#ifdef WOLFSSL_SMALL_STACK
645
0
    if (r != NULL)
646
0
#endif
647
0
        XMEMSET(r, 0, sizeof(mp_int));
648
0
#ifdef WOLFSSL_SMALL_STACK
649
0
    if (s != NULL)
650
0
#endif
651
0
        XMEMSET(s, 0, sizeof(mp_int));
652
653
    /* Initialize MP integers. */
654
0
    if (err == MP_OKAY)
655
0
        err = mp_init_multi(r, s, NULL, NULL, NULL, NULL);
656
    /* Generate signature into numbers. */
657
0
    if (err == MP_OKAY)
658
0
        err = wc_ecc_sm2_sign_hash_ex(hash, hashSz, rng, key, r, s);
659
660
    /* Encode r and s in DER DSA signature format. */
661
0
    if (err == MP_OKAY)
662
0
        err = StoreECC_DSA_Sig(sig, sigSz, r, s);
663
664
    /* Dispose of temporaries. */
665
0
    mp_clear(r);
666
0
    mp_clear(s);
667
668
0
#ifdef WOLFSSL_SMALL_STACK
669
    /* Free allocated data. */
670
0
    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
671
0
    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
672
0
#endif
673
674
0
    return err;
675
0
}
676
#endif
677
678
#ifdef HAVE_ECC_VERIFY
679
#ifndef WOLFSSL_SP_MATH
680
/* Scalar multiply two scalars against respective points and add result.
681
 *
682
 * @param [in]  mG       First point to multiply.
683
 * @param [in]  u1       First scalar.
684
 * @param [in]  mQ       Second point to multiply.
685
 * @param [in]  u2       Second scalar.
686
 * @param [out] mR       Point to store result in.
687
 * @param [in]  a        Coefficient a of the curve.
688
 * @param [in]  modulus  Modulus of curve.
689
 * @param [in]  heap     Dynamic memory allocation hint.
690
 * @return  MP_OKAY on success.
691
 * @return  MP_VAL when a parameter is invalid.
692
 * @return  MP_MEM when dynamic memory allocation fails.
693
 */
694
static int ecc_sm2_mul2add(ecc_point* mG, mp_int* u1, ecc_point* mQ, mp_int* u2,
695
    ecc_point* mR, mp_int* a, mp_int* modulus, void* heap)
696
0
{
697
0
    int err;
698
#ifndef ECC_SHAMIR
699
    mp_digit mp = 0;
700
701
    /* Calculate the Montgomery multiplier. */
702
    err = mp_montgomery_setup(modulus, &mp);
703
    if ((err == 0) && (!mp_iszero(u1))) {
704
        /* Compute mR = u1 * mG + u2 * mQ */
705
706
        /* mG = u1 * mG */
707
        err = wc_ecc_mulmod_ex(u1, mG, mG, a, modulus, 0, heap);
708
        if (err == MP_OKAY) {
709
            /* mQ = u2 * mQ */
710
            err = wc_ecc_mulmod_ex(u2, mQ, mR, a, modulus, 0, heap);
711
        }
712
713
        if (err == MP_OKAY) {
714
            /* mR = mQ + mG */
715
            err = ecc_projective_add_point(mR, mG, mR, a, modulus, mp);
716
        }
717
        if (err == MP_OKAY && mp_iszero(mR->z)) {
718
            /* When all zero then should have done a double instead. */
719
            if (mp_iszero(mR->x) && mp_iszero(mR->y)) {
720
                /* mR = mQ * 2 (mG = mQ) */
721
                err = ecc_projective_dbl_point(mQ, mR, a, modulus, mp);
722
            }
723
            else {
724
                /* When only Z zero then result is infinity. */
725
                err = mp_set(mR->x, 0);
726
                if (err == MP_OKAY)
727
                    err = mp_set(mR->y, 0);
728
                if (err == MP_OKAY)
729
                    err = mp_set(mR->z, 1);
730
            }
731
        }
732
    }
733
    else if (err == 0) {
734
        /* Compute mR = 0 * mG + u2 * mQ  =>  mR = u2 * mQ */
735
        err = wc_ecc_mulmod_ex(u2, mQ, mR, a, modulus, 0, heap);
736
    }
737
738
    /* Convert from Jacobian to affine. */
739
    if (err == MP_OKAY) {
740
        err = ecc_map(mR, modulus, mp);
741
    }
742
#else
743
    /* Use Shamir's trick to compute u1 * mG + u2 * mQ using half the doubles.
744
     */
745
0
    err = ecc_mul2add(mG, u1, mQ, u2, mR, a, modulus, heap);
746
0
#endif /* ECC_SHAMIR */
747
748
0
    return err;
749
0
}
750
#endif /* !WOLFSSL_SP_MATH */
751
752
/* Verify digest of hash(ZA || M) using key on SM2 curve and R and S.
753
 *
754
 * res gets set to 1 on successful verify and 0 on failure
755
 *
756
 * Use wc_ecc_sm2_create_digest to calculate the digest.
757
 *
758
 * @param [in]  r       MP integer holding r part of signature.
759
 * @param [in]  s       MP integer holding s part of signature.
760
 * @param [in]  hash    Array of bytes holding hash value.
761
 * @param [in]  hashSz  Size of hash in bytes.
762
 * @param [out] res     1 on successful verify and 0 on failure.
763
 * @param [in]  key     Public key on SM2 curve.
764
 * @return  0 on success (note this is even when successfully finding verify is
765
 * incorrect)
766
 * @return  BAD_FUNC_ARG when key, res, r, s or hash is NULL.
767
 * @return  MP_VAL when r + s = 0.
768
 * @return  MEMORY_E on dynamic memory allocation failure.
769
 * @return  MP_MEM when dynamic memory allocation fails.
770
 */
771
int wc_ecc_sm2_verify_hash_ex(mp_int *r, mp_int *s, const byte *hash,
772
    word32 hashSz, int *res, ecc_key *key)
773
0
{
774
0
    int err = MP_OKAY;
775
0
#ifndef WOLFSSL_SP_MATH
776
0
    ecc_point* PO = NULL;
777
0
    ecc_point* G = NULL;
778
0
    mp_int* t = NULL;
779
0
    mp_int* e = NULL;
780
0
    mp_int* prime = NULL;
781
0
    mp_int* Af = NULL;
782
0
    mp_int* order = NULL;
783
0
#ifdef WOLFSSL_SMALL_STACK
784
0
    mp_int* data = NULL;
785
#else
786
    mp_int data[5];
787
#endif
788
0
#endif
789
790
    /* Validate parameters. */
791
0
    if ((key == NULL) || (key->dp == NULL) || (res == NULL) || (r == NULL) ||
792
0
            (s == NULL) || (hash == NULL)) {
793
0
        err = BAD_FUNC_ARG;
794
0
    }
795
    /* SM2 signature must be with a key on the SM2 curve. */
796
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
797
0
        (key->idx != ECC_CUSTOM_IDX)) {
798
0
        err = BAD_FUNC_ARG;
799
0
    }
800
801
#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_SM2)
802
    if ((err == MP_OKAY) && (key->dp->id == ECC_SM2P256V1)) {
803
        /* Use optimized code in SP to perform verification. */
804
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
805
        err = sp_ecc_verify_sm2_256(hash, hashSz, key->pubkey.x,
806
            key->pubkey.y, key->pubkey.z, r, s, res, key->heap);
807
        RESTORE_VECTOR_REGISTERS();
808
        return err;
809
    }
810
#endif
811
812
0
#ifndef WOLFSSL_SP_MATH
813
0
    if (res != NULL) {
814
        /* Assume failure. */
815
0
        *res = 0;
816
0
    }
817
818
0
#ifdef WOLFSSL_SMALL_STACK
819
0
    if (err == MP_OKAY) {
820
        /* Allocate temporary MP integer. */
821
0
        data = (mp_int*)XMALLOC(sizeof(mp_int) * 5, key->heap,
822
0
            DYNAMIC_TYPE_ECC);
823
0
        if (data == NULL) {
824
0
            err = MEMORY_E;
825
0
        }
826
0
    }
827
0
#endif
828
0
    if (err == MP_OKAY) {
829
0
        t = data;
830
0
        e = data + 1;
831
0
        prime = data + 2;
832
0
        Af = data + 3;
833
0
        order = data + 4;
834
0
    }
835
836
0
    if (err == MP_OKAY) {
837
        /* Initialize temporary MP integers. */
838
0
        err = mp_init_multi(e, t, prime, Af, order, NULL);
839
0
    }
840
0
    if (err == MP_OKAY) {
841
        /* Get order. */
842
0
        err = mp_read_radix(order, key->dp->order, MP_RADIX_HEX);
843
0
    }
844
    /* B5: calculate t = (r' + s') modn -- if t is 0 then failed */
845
0
    if (err == MP_OKAY) {
846
        /* t = r + s */
847
0
        err = mp_addmod(r, s, order, t);
848
0
    }
849
0
    if (err == MP_OKAY) {
850
        /* Check sum is valid. */
851
0
        if (mp_iszero(t) == MP_YES)
852
0
            err = MP_VAL;
853
0
    }
854
#ifdef DEBUG_ECC_SM2
855
    mp_dump("t = ", t, 0);
856
#endif
857
858
    /* B6: calculate the point (x1', y1')=[s']G + [t]PA */
859
0
    if (err == MP_OKAY) {
860
        /* Create two new points. */
861
0
        PO = wc_ecc_new_point_h(key->heap);
862
0
        if (PO == NULL) {
863
0
            err = MEMORY_E;
864
0
        }
865
0
    }
866
0
    if (err == MP_OKAY) {
867
0
        G  = wc_ecc_new_point_h(key->heap);
868
0
        if (G == NULL) {
869
0
            err = MEMORY_E;
870
0
        }
871
0
    }
872
873
0
    if (err == MP_OKAY) {
874
        /* Get the base point x-ordinate for SM2 curve. */
875
0
        err = mp_read_radix(G->x, key->dp->Gx, MP_RADIX_HEX);
876
0
    }
877
0
    if (err == MP_OKAY) {
878
        /* Get the base point y-ordinate for SM2 curve. */
879
0
        err = mp_read_radix(G->y, key->dp->Gy, MP_RADIX_HEX);
880
0
    }
881
0
    if (err == MP_OKAY) {
882
        /* Base point is in affine so z-ordinate is one. */
883
0
        err = mp_set(G->z, 1);
884
0
    }
885
0
    if (err == MP_OKAY) {
886
        /* Get a coefficient of SM2 curve. */
887
0
        err = mp_read_radix(Af, key->dp->Af, MP_RADIX_HEX);
888
0
    }
889
0
    if (err == MP_OKAY) {
890
        /* Get a prime of SM2 curve. */
891
0
        err = mp_read_radix(prime, key->dp->prime, MP_RADIX_HEX);
892
0
    }
893
#ifdef DEBUG_ECC_SM2
894
    printf("\n");
895
    mp_dump("G->x = ", G->x, 0);
896
    mp_dump("G->y = ", G->y, 0);
897
    mp_dump("s    = ", s, 0);
898
    mp_dump("P->x = ", key->pubkey.x, 0);
899
    mp_dump("P->y = ", key->pubkey.y, 0);
900
    mp_dump("t    = ", t, 0);
901
    mp_dump("Af   = ", Af, 0);
902
    mp_dump("prime= ", prime, 0);
903
#endif
904
0
    if (err == MP_OKAY) {
905
        /* [s']G + [t]PA */
906
0
        err = ecc_sm2_mul2add(G, s, &(key->pubkey), t, PO, Af, prime,
907
0
                key->heap);
908
0
    }
909
#ifdef DEBUG_ECC_SM2
910
    mp_dump("PO->x = ", PO->x, 0);
911
    mp_dump("PO->y = ", PO->y, 0);
912
    printf("\n\n");
913
#endif
914
915
916
    /* B7: calculate R=(e'+x1') modn, if R=r then passed */
917
0
    if (err == MP_OKAY) {
918
        /* Convert hash to an MP integer. */
919
0
        err = mp_read_unsigned_bin(e, hash, hashSz);
920
0
    }
921
0
    if (err == MP_OKAY) {
922
        /* e' + x1' */
923
0
        err = mp_addmod(e, PO->x, order, t);
924
0
    }
925
    /* Calculated value must be same as r. */
926
0
    if (err == MP_OKAY && mp_cmp(t, r) == MP_EQ) {
927
0
        *res = 1;
928
0
    }
929
930
    /* Dispose of allocated points. */
931
0
    if (PO != NULL) {
932
0
        wc_ecc_del_point_h(PO, key->heap);
933
0
    }
934
0
    if (G != NULL) {
935
0
        wc_ecc_del_point_h(G, key->heap);
936
0
    }
937
938
    /* Dispose of allocated MP integers. */
939
0
    if (e != NULL) {
940
0
        mp_free(e);
941
0
    }
942
0
    if (t != NULL) {
943
0
        mp_free(t);
944
0
    }
945
0
    if (prime != NULL) {
946
0
        mp_free(prime);
947
0
    }
948
0
    if (Af != NULL) {
949
0
        mp_free(Af);
950
0
    }
951
0
    if (order != NULL) {
952
0
        mp_free(order);
953
0
    }
954
955
0
#ifdef WOLFSSL_SMALL_STACK
956
    /* Free allocated data. */
957
0
    XFREE(data, key->heap, DYNAMIC_TYPE_ECC);
958
0
#endif
959
#else
960
    (void)hashSz;
961
962
    err = NOT_COMPILED_IN;
963
#endif
964
965
0
    return err;
966
0
}
967
968
969
#ifndef NO_ASN
970
/* Verify digest of hash(ZA || M) using key on SM2 curve and encoded signature.
971
 *
972
 * res gets set to 1 on successful verify and 0 on failure
973
 *
974
 * Use wc_ecc_sm2_create_digest to calculate the digest.
975
 *
976
 * @param [in]  sig     DER encoded DSA signature.
977
 * @param [in]  sigSz   Length of signature in bytes.
978
 * @param [in]  hash    Array of bytes holding hash value.
979
 * @param [in]  hashSz  Size of hash in bytes.
980
 * @param [out] res     1 on successful verify and 0 on failure.
981
 * @param [in]  key     Public key on SM2 curve.
982
 * @return  0 on success (note this is even when successfully finding verify is
983
 * incorrect)
984
 * @return  BAD_FUNC_ARG when key, res, sig or hash is NULL.
985
 * @return  MP_VAL when r + s = 0.
986
 * @return  MEMORY_E on dynamic memory allocation failure.
987
 * @return  MP_MEM when dynamic memory allocation fails.
988
 */
989
int wc_ecc_sm2_verify_hash(const byte* sig, word32 sigSz, const byte* hash,
990
    word32 hashSz, int* res, ecc_key* key)
991
0
{
992
0
    int err = 0;
993
0
#ifdef WOLFSSL_SMALL_STACK
994
0
    mp_int* r = NULL;
995
0
    mp_int* s = NULL;
996
#else
997
    mp_int r[1];
998
    mp_int s[1];
999
#endif
1000
1001
    /* Validate parameters. */
1002
0
    if ((sig == NULL) || (hash == NULL) || (res == NULL) || (key == NULL) ||
1003
0
            (key->dp == NULL)) {
1004
0
        err = BAD_FUNC_ARG;
1005
0
    }
1006
    /* SM2 signature must be with a key on the SM2 curve. */
1007
0
    if ((err == MP_OKAY) && (key->dp->id != ECC_SM2P256V1) &&
1008
0
        (key->idx != ECC_CUSTOM_IDX)) {
1009
0
        err = BAD_FUNC_ARG;
1010
0
    }
1011
1012
0
#ifdef WOLFSSL_SMALL_STACK
1013
0
    if (err == 0) {
1014
        /* Allocate MP integers. */
1015
0
        r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
1016
0
        if (r == NULL) {
1017
0
            err = MEMORY_E;
1018
0
        }
1019
0
        else {
1020
0
            XMEMSET(r, 0, sizeof(*r));
1021
0
        }
1022
0
    }
1023
0
    if (err == MP_OKAY) {
1024
0
        s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
1025
0
        if (s == NULL) {
1026
0
            err = MEMORY_E;
1027
0
        }
1028
0
        else {
1029
0
            XMEMSET(s, 0, sizeof(*s));
1030
0
        }
1031
0
    }
1032
#else
1033
    XMEMSET(r, 0, sizeof(*r));
1034
    XMEMSET(s, 0, sizeof(*s));
1035
#endif
1036
1037
0
    if (err == 0) {
1038
        /* Decode the signature into R and S. */
1039
0
        err = DecodeECC_DSA_Sig(sig, sigSz, r, s);
1040
0
    }
1041
0
    if (err == 0) {
1042
        /* Verify the signature with hash, key, R and S. */
1043
0
        err = wc_ecc_sm2_verify_hash_ex(r, s, hash, hashSz, res, key);
1044
0
    }
1045
1046
    /* Dispose of allocated data. */
1047
0
#ifdef WOLFSSL_SMALL_STACK
1048
0
    if (r != NULL)
1049
0
#endif
1050
0
    {
1051
0
        mp_free(r);
1052
0
     }
1053
0
#ifdef WOLFSSL_SMALL_STACK
1054
0
    if (s != NULL)
1055
0
#endif
1056
0
    {
1057
0
        mp_free(s);
1058
0
    }
1059
1060
0
#ifdef WOLFSSL_SMALL_STACK
1061
    /* Free allocated data. */
1062
0
    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
1063
0
    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
1064
0
#endif
1065
1066
0
    return err;
1067
0
}
1068
#endif /* NO_ASN */
1069
#endif /* HAVE_ECC_VERIFY */
1070
1071
#endif /* WOLFSSL_SM2 && HAVE_ECC */