Coverage Report

Created: 2024-06-28 06:19

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