Coverage Report

Created: 2025-04-11 06:45

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