Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/wolfcrypt/src/eccsi.c
Line
Count
Source
1
/* eccsi.c
2
 *
3
 * Copyright (C) 2006-2026 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 3 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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#ifdef NO_INLINE
25
    #include <wolfssl/wolfcrypt/misc.h>
26
#else
27
    #define WOLFSSL_MISC_INCLUDED
28
    #include <wolfcrypt/src/misc.c>
29
#endif
30
31
#ifdef WOLFCRYPT_HAVE_ECCSI
32
33
#include <wolfssl/wolfcrypt/eccsi.h>
34
#include <wolfssl/wolfcrypt/asn_public.h>
35
#ifdef WOLFSSL_HAVE_SP_ECC
36
    #include <wolfssl/wolfcrypt/sp.h>
37
#endif
38
39
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
40
    /* FIPS build has replaced ecc.h. */
41
    #define wc_ecc_key_get_priv(key)  (&((key)->k))
42
    #define ecc_get_k_raw(key)        (&((key)->k))
43
    #define ecc_blind_k_rng(key, rng) 0
44
    #define ecc_forcezero_k(key)      mp_forcezero(&((key)->k))
45
    #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
46
#endif
47
48
/**
49
 * Initialize the components of the ECCSI key and use the specified curve.
50
 *
51
 * Must be called before performing any operations.
52
 * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed.
53
 *
54
 * @param  [in]  key    ECCSI key to initialize.
55
 * @param  [in]  heap   Heap hint.
56
 * @param  [in]  devId  Device identifier.
57
 *                      Use INVALID_DEVID when no device used.
58
 * @return  0 on success.
59
 * @return  BAD_FUNC_ARG when key is NULL.
60
 * @return  MEMORY_E when dynamic memory allocation fails.
61
 */
62
int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap,
63
        int devId)
64
95
{
65
95
    int err = 0;
66
95
    EccsiKeyParams* params = NULL;
67
68
95
    if (key == NULL) {
69
0
        err = BAD_FUNC_ARG;
70
0
    }
71
72
95
    if (err == 0) {
73
95
        XMEMSET(key, 0, sizeof(*key));
74
95
        key->heap = heap;
75
95
        params = &key->params;
76
77
95
        err = wc_ecc_init_ex(&key->ecc, heap, devId);
78
95
    }
79
95
    if (err == 0) {
80
95
        err = wc_ecc_init_ex(&key->pubkey, heap, devId);
81
95
    }
82
95
    if (err == 0) {
83
95
        key->pvt = wc_ecc_new_point_h(heap);
84
95
        if (key->pvt == NULL) {
85
6
            err = MEMORY_E;
86
6
        }
87
95
    }
88
95
    if (err == 0) {
89
89
        err = mp_init_multi(&params->order,
90
89
#ifdef WOLFCRYPT_ECCSI_CLIENT
91
89
                &params->a, &params->b, &params->prime, &key->tmp, &key->ssk
92
#else
93
                NULL, NULL, NULL, NULL, NULL
94
#endif
95
89
                );
96
89
    }
97
95
    if (err == 0) {
98
89
        err = wc_ecc_set_curve(&key->ecc, keySz, curveId);
99
89
    }
100
95
    if (err == 0) {
101
89
        err = wc_ecc_set_curve(&key->pubkey, keySz, curveId);
102
89
    }
103
104
95
    if (err != 0) {
105
6
        wc_FreeEccsiKey(key);
106
6
    }
107
108
95
    return err;
109
95
}
110
111
/**
112
 * Initialize the components of the ECCSI key.
113
 * Default curve used: NIST_P256 (ECC_SECP256R1)
114
 *
115
 * Must be called before performing any operations.
116
 * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed.
117
 *
118
 * @param  [in]  key    ECCSI key to initialize.
119
 * @param  [in]  heap   Heap hint.
120
 * @param  [in]  devId  Device identifier.
121
 *                      Use INVALID_DEVID when no device used.
122
 * @return  0 on success.
123
 * @return  BAD_FUNC_ARG when key is NULL.
124
 * @return  MEMORY_E when dynamic memory allocation fails.
125
 */
126
int wc_InitEccsiKey(EccsiKey* key, void* heap, int devId)
127
0
{
128
0
    return wc_InitEccsiKey_ex(key, 32, ECC_SECP256R1, heap, devId);
129
0
}
130
131
/**
132
 * Frees memory associated with components of the ECCIS key.
133
 *
134
 * Must be called when finished with the ECCIS key.
135
 *
136
 * @param  [in]  key  ECCIS key.
137
 */
138
void wc_FreeEccsiKey(EccsiKey* key)
139
95
{
140
95
    if (key != NULL) {
141
95
        EccsiKeyParams* params = &key->params;
142
143
95
        wc_ecc_del_point_h(params->base, key->heap);
144
95
#ifdef WOLFCRYPT_ECCSI_CLIENT
145
95
        mp_free(&key->ssk);
146
95
        mp_free(&key->tmp);
147
95
        mp_free(&params->prime);
148
95
        mp_free(&params->b);
149
95
        mp_free(&params->a);
150
95
#endif
151
95
        mp_free(&params->order);
152
95
        wc_ecc_del_point_h(key->pvt, key->heap);
153
95
        wc_ecc_free(&key->pubkey);
154
95
        wc_ecc_free(&key->ecc);
155
95
        XMEMSET(key, 0, sizeof(*key));
156
95
    }
157
95
}
158
159
/*
160
 * Order, as a hex string in the ECC object, loaded into mp_int in key.
161
 * Flags that the order is available so it isn't loaded multiple times.
162
 *
163
 * @param  [in]  key  ECCSI key.
164
 * @return  0 on success.
165
 * @return  MEMORY_E when dynamic memory allocation fails.
166
 */
167
static int eccsi_load_order(EccsiKey* key)
168
0
{
169
0
    int err = 0;
170
171
0
    if (!key->params.haveOrder) {
172
0
        err = mp_read_radix(&key->params.order, key->ecc.dp->order,
173
0
                MP_RADIX_HEX);
174
0
        if (err == 0) {
175
0
            key->params.haveOrder = 1;
176
0
        }
177
0
    }
178
179
0
    return err;
180
0
}
181
182
#ifdef WOLFCRYPT_ECCSI_CLIENT
183
/*
184
 * Parameters, as a hex strings in the ECC object, loaded into mp_ints in key.
185
 *
186
 * Parameters loaded: order, A, B, prime.
187
 * Flags that each parameter is available so they aren't loaded multiple times.
188
 *
189
 * @param  [in]  key  ECCSI key.
190
 * @return  0 on success.
191
 * @return  MEMORY_E when dynamic memory allocation fails.
192
 */
193
static int eccsi_load_ecc_params(EccsiKey* key)
194
0
{
195
0
    int err = 0;
196
0
    EccsiKeyParams* params = &key->params;
197
198
0
    err = eccsi_load_order(key);
199
0
    if ((err == 0) && (!params->haveA)) {
200
0
        err = mp_read_radix(&params->a, key->ecc.dp->Af, MP_RADIX_HEX);
201
0
        if (err == 0) {
202
0
            params->haveA = 1;
203
0
        }
204
0
    }
205
0
    if ((err == 0) && (!params->haveB)) {
206
0
        err = mp_read_radix(&params->b, key->ecc.dp->Bf, MP_RADIX_HEX);
207
0
        if (err == 0) {
208
0
            params->haveB = 1;
209
0
        }
210
0
    }
211
0
    if ((err == 0) && (!params->havePrime)) {
212
0
        err = mp_read_radix(&params->prime, key->ecc.dp->prime, MP_RADIX_HEX);
213
0
        if (err == 0) {
214
0
            params->havePrime = 1;
215
0
        }
216
0
    }
217
218
0
    return err;
219
0
}
220
#endif /* WOLFCRYPT_ECCSI_CLIENT */
221
222
/*
223
 * Get the base point, hex encoded in the ECC object, as an ecc_point.
224
 *
225
 * Flags that base is available so it isn't loaded multiple times.
226
227
 * @param  [in]   key   ECCSI key.
228
 * @param  [out]  base  Base point of curve.
229
 * @return  0 on success.
230
 * @return  MEMORY_E when dynamic memory allocation fails.
231
 */
232
static int eccsi_load_base(EccsiKey* key)
233
0
{
234
0
    int err = 0;
235
0
    EccsiKeyParams* params = &key->params;
236
237
0
    if (!params->haveBase) {
238
0
        if (params->base == NULL) {
239
0
            params->base = wc_ecc_new_point_h(key->heap);
240
0
            if (params->base == NULL) {
241
0
                err = MEMORY_E;
242
0
            }
243
0
        }
244
0
        if (err == 0) {
245
0
            err = mp_read_radix(params->base->x, key->ecc.dp->Gx, MP_RADIX_HEX);
246
0
        }
247
0
        if (err == 0) {
248
0
            err = mp_read_radix(params->base->y, key->ecc.dp->Gy, MP_RADIX_HEX);
249
0
        }
250
0
        if (err == 0) {
251
0
            err = mp_set(params->base->z, 1);
252
0
        }
253
0
        if (err == 0) {
254
0
            params->haveBase = 1;
255
0
        }
256
0
    }
257
258
0
    return err;
259
0
}
260
261
/*
262
 * Encode the base point of the curve.
263
 *
264
 * Base point is hex encoded in the ECC object or cached as an ECC point from
265
 * previous load calls.
266
 *
267
 * @param  [in]   key     ECCSI key.
268
 * @param  [out]  data    Buffer to encode base point into.
269
 * @param  [out]  dataSz  Length of base point in bytes.
270
 * @return  0 on success.
271
 * @return  MEMORY_E when dynamic memory allocation fails.
272
 * @return  Other -ve value when an internal operation fails.
273
 */
274
static int eccsi_encode_base(EccsiKey* key, byte* data, word32* dataSz)
275
0
{
276
0
    int err;
277
0
    int idx = wc_ecc_get_curve_idx(key->ecc.dp->id);
278
279
0
    err = eccsi_load_base(key);
280
0
    if (err == 0) {
281
0
        err = wc_ecc_export_point_der(idx, key->params.base, data, dataSz);
282
0
    }
283
284
0
    return err;
285
0
}
286
287
#ifndef WOLFSSL_HAVE_SP_ECC
288
/*
289
 * Convert the KPAK to montgomery form.
290
 *
291
 * The KPAK is needed in Montgomery form for verification.
292
 *
293
 * @param  [in]  key      ECCSI key.
294
 * @return  0 on success.
295
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
296
 * @return  Other -ve value when an internal operation fails.
297
 */
298
static int eccsi_kpak_to_mont(EccsiKey* key)
299
0
{
300
0
    int err = 0;
301
0
    ecc_point* kpak = &key->ecc.pubkey;
302
0
    mp_int* mu = &key->tmp;
303
0
    mp_int* prime = &key->params.prime;
304
305
0
    if (!key->kpakMont) {
306
0
        err = mp_montgomery_calc_normalization(mu, prime);
307
0
        if (err == 0) {
308
0
            err = mp_mulmod(kpak->x, mu, prime, kpak->x);
309
0
        }
310
0
        if (err == 0) {
311
0
            err = mp_mulmod(kpak->y, mu, prime, kpak->y);
312
0
        }
313
0
        if (err == 0) {
314
0
            err = mp_mulmod(kpak->z, mu, prime, kpak->z);
315
0
        }
316
0
        if (err == 0) {
317
0
            key->kpakMont = 1;
318
0
        }
319
0
    }
320
321
0
    return err;
322
0
}
323
#endif
324
325
/*
326
 * Convert the KPAK from montgomery form.
327
 *
328
 * The KPAK is needed in Montgomery form for verification.
329
 *
330
 * @param  [in]  key      ECCSI key.
331
 * @return  0 on success.
332
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
333
 * @return  Other -ve value when an internal operation fails.
334
 */
335
static int eccsi_kpak_from_mont(EccsiKey* key)
336
0
{
337
0
    int err = 0;
338
0
    ecc_point* kpak = &key->ecc.pubkey;
339
0
    mp_digit mp;
340
0
    mp_int* prime = &key->params.prime;
341
342
0
    if (key->kpakMont) {
343
0
        err = mp_montgomery_setup(prime, &mp);
344
0
        if (err == 0) {
345
0
            err = mp_montgomery_reduce(kpak->x, prime, mp);
346
0
        }
347
0
        if (err == 0) {
348
0
            err = mp_montgomery_reduce(kpak->y, prime, mp);
349
0
        }
350
0
        if (err == 0) {
351
0
            err = mp_montgomery_reduce(kpak->z, prime, mp);
352
0
        }
353
0
        if (err == 0) {
354
0
            key->kpakMont = 0;
355
0
        }
356
0
    }
357
358
0
    return err;
359
0
}
360
361
/*
362
 * Compute HS = hash( G | KPAK | ID | PVT )
363
 *
364
 * Use when making a (SSK,PVT) pair, signing and verifying.
365
 *
366
 * @param  [in]   key       ECCSI key.
367
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
368
 * @param  [in]   id        Identity to create hash from.
369
 * @param  [in]   idSz      Length of identity in bytes.
370
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
371
 * @param  [out]  hash      Buffer to hold hash data.
372
 * @param  [out]  hashSz    Length of hash data in bytes.
373
 * @return  0 on success.
374
 * @return  MEMORY_E when dynamic memory allocation fails.
375
 * @return  Other -ve value when an internal operation fails.
376
 */
377
static int eccsi_compute_hs(EccsiKey* key, enum wc_HashType hashType,
378
        const byte* id, word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz)
379
0
{
380
0
    int err;
381
0
    word32 dataSz = 0;
382
0
    int idx = wc_ecc_get_curve_idx(key->ecc.dp->id);
383
0
    ecc_point* kpak = &key->ecc.pubkey;
384
0
    int hash_inited = 0;
385
386
    /* HS = hash( G | KPAK | ID | PVT ) */
387
0
    err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID);
388
0
    if (err == 0) {
389
0
        hash_inited = 1;
390
        /* Base Point - G */
391
0
        dataSz = sizeof(key->data);
392
0
        err = eccsi_encode_base(key, key->data, &dataSz);
393
0
    }
394
0
    if (err == 0) {
395
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
396
0
    }
397
0
    if (err == 0) {
398
0
        err = eccsi_kpak_from_mont(key);
399
0
    }
400
0
    if (err == 0) {
401
0
        dataSz = sizeof(key->data);
402
        /* KPAK - public key */
403
0
        err = wc_ecc_export_point_der(idx, kpak, key->data, &dataSz);
404
0
    }
405
0
    if (err == 0) {
406
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
407
0
    }
408
0
    if (err == 0) {
409
        /* Id - Signer's ID */
410
0
        err = wc_HashUpdate(&key->hash, hashType, id, idSz);
411
0
    }
412
0
    if (err == 0) {
413
0
        dataSz = sizeof(key->data);
414
        /* PVT - Public Validation Token */
415
0
        err = wc_ecc_export_point_der(idx, pvt, key->data, &dataSz);
416
0
    }
417
0
    if (err == 0) {
418
        /* PVT - Public Validation Token */
419
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
420
0
    }
421
0
    if (err == 0) {
422
0
        err = wc_HashFinal(&key->hash, hashType, hash);
423
0
    }
424
425
0
    if (err == 0) {
426
0
        *hashSz = (byte)wc_HashGetDigestSize(hashType);
427
0
    }
428
429
0
    if (hash_inited) {
430
0
        (void)wc_HashFree(&key->hash, hashType);
431
0
    }
432
433
0
    return err;
434
0
}
435
436
#ifdef WOLFCRYPT_ECCSI_KMS
437
/**
438
 * Generate KMS Secret Auth Key (KSAK) and KMS Public Auth Key (KPAK).
439
 *
440
 * RFC 6507, Section 4.2
441
 *
442
 * Called when establishing a new KMS.\n
443
 * KSAK must be kept secret while KPAK is required by clients for signing
444
 * and verifying.\n
445
 * Export key using wc_ExportEccsiKey(), once generated, to reuse the key.\n
446
 * Export KPAK using wc_ExportEccsiPublicKey(), once generate to send to
447
 * clients.
448
 *
449
 * Creates a random private key and multiplies it by the base point to calculate
450
 * the public key.
451
 *
452
 * @param  [in]  key      ECCSI key.
453
 * @param  [in]  rng      Random number generator.
454
 * @return  0 on success.
455
 * @return  BAD_FUNC_ARG when key or rng is NULL.
456
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
457
 * @return  Other -ve value when an internal operation fails.
458
 */
459
int wc_MakeEccsiKey(EccsiKey* key, WC_RNG* rng)
460
0
{
461
0
    int err = 0;
462
463
0
    if ((key == NULL) || (rng == NULL)) {
464
0
        err = BAD_FUNC_ARG;
465
0
    }
466
467
0
    if (err == 0) {
468
0
        err = wc_ecc_make_key_ex(rng, key->ecc.dp->size, &key->ecc,
469
0
                key->ecc.dp->id);
470
#ifdef WOLFSSL_ASYNC_CRYPT
471
        /* ECCSI has no asynchronous API, so the caller cannot resume a pending
472
         * key generation - complete it here. The key->pubkey sites in
473
         * eccsi_make_pair() and eccsi_gen_sig() need no wait: each is preceded
474
         * by wc_ecc_free(&key->pubkey), which clears the marker that
475
         * _ecc_make_key_ex() gates its pending path on. */
476
        err = wc_AsyncWait(err, &key->ecc.asyncDev, WC_ASYNC_FLAG_NONE);
477
#endif
478
0
    }
479
480
0
    return err;
481
0
}
482
483
/*
484
 * Encode a point into a buffer.
485
 *
486
 * X and y ordinate of point concatenated. Each number is zero padded tosize.
487
 * Descriptor byte (0x04) is prepended when not raw.
488
 *
489
 * @param  [in]      point    ECC point to encode.
490
 * @param  [in]      size     Size of prime in bytes - maximum ordinate length.
491
 * @param  [out]     data     Buffer to hold encoded data.
492
 *                            NULL when needing length of encoded data.
493
 * @param  [in,out]  sz       In, the size of the buffer in bytes.
494
 *                            Out, the size of the encoded data in bytes.
495
 * @param  [in]      raw      On 0, prepend descriptor byte.
496
 *                            On 1, only include ordinates.
497
 * @return  0 on success.
498
 * @return  BAD_FUNC_ARG when key or sz is NULL.
499
 * @return  LENGTH_ONLY_E when data is NULL - sz will hold the size in bytes of
500
 *          the encoded data.
501
 * @return  BUFFER_E when size of buffer is too small.
502
 */
503
static int eccsi_encode_point(ecc_point* point, word32 size, byte* data,
504
        word32* sz, int raw)
505
0
{
506
0
    int err = 0;
507
508
0
    if (data == NULL) {
509
0
        *sz = size * 2 + !raw;
510
0
        err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
511
0
    }
512
0
    if ((err == 0) && (*sz < size * 2 + !raw)) {
513
0
        err = BUFFER_E;
514
0
    }
515
516
0
    if (err == 0) {
517
0
        if (!raw) {
518
0
            data[0] = 0x04;
519
0
            data++;
520
0
        }
521
522
        /* Write out the point's x ordinate into key size bytes. */
523
0
        err = mp_to_unsigned_bin_len(point->x, data, (int)size);
524
0
    }
525
0
    if (err == 0) {
526
0
        data += size;
527
        /* Write out the point's y ordinate into key size bytes. */
528
0
        err = mp_to_unsigned_bin_len(point->y, data, (int)size);
529
0
    }
530
0
    if (err == 0) {
531
0
        *sz = size * 2 + !raw;
532
0
    }
533
534
0
    return err;
535
0
}
536
537
/*
538
 * Decode the data into an ECC point.
539
 *
540
 * X and y ordinate of point concatenated. Each number is zero padded to
541
 * key size. Supports prepended descriptor byte (0x04).
542
 *
543
 * @param  [out]  point  ECC point to encode.
544
 * @param  [in]   size   Size of prime in bytes - maximum ordinate length.
545
 * @param  [in]   data   Encoded public key.
546
 * @param  [in]   sz     Size of the encoded public key in bytes.
547
 * @return  0 on success.
548
 * @return  BAD_FUNC_ARG when key or z is NULL.
549
 * @return  BUFFER_E when size of data is not equal to the expected size.
550
 * @return  ASN_PARSE_E when format byte is invalid.
551
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
552
 */
553
static int eccsi_decode_point(ecc_point* point, word32 size, const byte* data,
554
        word32 sz)
555
89
{
556
89
    int err = 0;
557
558
89
    if ((sz != size * 2) && (sz != size * 2 + 1)) {
559
0
        err = BUFFER_E;
560
0
    }
561
562
89
    if ((err == 0) && (sz & 1)) {
563
0
        if (data[0] != 0x04) {
564
0
            err = ASN_PARSE_E;
565
0
        }
566
0
        data++;
567
0
    }
568
569
89
    if (err == 0) {
570
        /* Read the public key point's x value from key size bytes. */
571
89
        err = mp_read_unsigned_bin(point->x, data, size);
572
89
    }
573
89
    if (err == 0) {
574
89
        data += size;
575
        /* Read the public key point's y value from key size bytes. */
576
89
        err = mp_read_unsigned_bin(point->y, data, size);
577
89
    }
578
89
    if (err == 0) {
579
89
        err = mp_set(point->z, 1);
580
89
    }
581
582
89
    return err;
583
89
}
584
585
/*
586
 * Encode the ECCSI key.
587
 *
588
 * Encodes the private key as big-endian bytes of fixed length.
589
 * Encodes the public key x and y ordinates as big-endian bytes of fixed length.
590
 *
591
 * @param  [in]      key   ECCSI key.
592
 * @param  [out]     data  Buffer to hold encoded ECCSI key.
593
 * @return  0 on success.
594
 * @return  MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK).
595
 */
596
static int eccsi_encode_key(EccsiKey* key, byte* data)
597
0
{
598
0
    int err;
599
0
    word32 sz = (word32)key->ecc.dp->size * 2;
600
601
    /* Write out the secret value into key size bytes. */
602
0
    err = mp_to_unsigned_bin_len(wc_ecc_key_get_priv(&key->ecc), data,
603
0
        key->ecc.dp->size);
604
0
    if (err == 0) {
605
0
        data += key->ecc.dp->size;
606
        /* Write the public key. */
607
0
        err = eccsi_encode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size,
608
0
                data, &sz, 1);
609
0
    }
610
611
0
    return err;
612
0
}
613
614
/**
615
 * Export the ECCSI key as encoded public/private ECC key.
616
 *
617
 * Use when saving the KMS key pair.
618
 *
619
 * Private key, x ordinate of public key and y ordinate of public key
620
 * concatenated. Each number is zero padded to key size.
621
 *
622
 * @param  [in]      key   ECCSI key.
623
 * @param  [out]     data  Buffer to hold encoded ECCSI key.
624
 *                         NULL when requesting required length.
625
 * @param  [in,out]  sz    On in, size of buffer in bytes.
626
 *                         On out, size of encoded ECCSI key in bytes.
627
 * @return  0 on success.
628
 * @return  BAD_FUNC_ARG when key or sz is NULL
629
 * @return  BAD_STATE_E when no key to export.
630
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
631
 * @return  BUFFER_E when the buffer passed in is too small.
632
 * @return  MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK).
633
 */
634
int wc_ExportEccsiKey(EccsiKey* key, byte* data, word32* sz)
635
0
{
636
0
    int err = 0;
637
638
0
    if ((key == NULL) || (sz == NULL)) {
639
0
        err = BAD_FUNC_ARG;
640
0
    }
641
642
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) {
643
0
        err = BAD_STATE_E;
644
0
    }
645
646
0
    if (err == 0) {
647
0
        if (data == NULL) {
648
0
            *sz = (word32)(key->ecc.dp->size * 3);
649
0
            err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
650
0
        }
651
0
        else if (*sz < (word32)key->ecc.dp->size * 3) {
652
0
            err = BUFFER_E;
653
0
        }
654
0
        else {
655
0
            *sz = (word32)(key->ecc.dp->size * 3);
656
0
        }
657
0
    }
658
0
    if (err == 0) {
659
0
        err = eccsi_kpak_from_mont(key);
660
0
    }
661
0
    if (err == 0) {
662
        /* Encode key */
663
0
        err = eccsi_encode_key(key, data);
664
0
    }
665
666
0
    return err;
667
0
}
668
669
/*
670
 * Import the ECCSI key as encoded public/private ECC key.
671
 *
672
 * Decodes the private key as big-endian bytes of fixed length.
673
 * Decodes the public key x and y ordinates as big-endian bytes of fixed length.
674
 *
675
 * @param  [in]  key   ECCSI key.
676
 * @param  [in]  data  Buffer holding encoded ECCSI key.
677
 * @return  0 on success.
678
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
679
 */
680
static int eccsi_decode_key(EccsiKey* key, const byte* data)
681
89
{
682
89
    int err;
683
684
    /* Read the secret value from key size bytes. */
685
89
    err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
686
89
        (word32)key->ecc.dp->size);
687
89
    if (err == 0) {
688
89
        err = ecc_blind_k_rng(&key->ecc, NULL);
689
89
    }
690
89
    if (err == 0) {
691
89
        data += key->ecc.dp->size;
692
        /* Read public key. */
693
89
        err = eccsi_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size,
694
89
                data, (word32)(key->ecc.dp->size * 2));
695
89
    }
696
697
89
    return err;
698
89
}
699
700
/**
701
 * Import the ECCSI key as encoded public/private ECC key.
702
 *
703
 * Use when restoring the KMS key pair.
704
 *
705
 * Private key, x ordinate of public key and y ordinate of public key
706
 * concatenated. Each number is zero padded to key size.
707
 *
708
 * @param  [in]  key   ECCSI key.
709
 * @param  [in]  data  Buffer holding encoded ECCSI key.
710
 * @param  [in]  sz    Size of encoded ECCSI key in bytes.
711
 * @return  0 on success.
712
 * @return  BAD_FUNC_ARG when key or data is NULL.
713
 * @return  BUFFER_E when size of data is not equal to the expected size.
714
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
715
 */
716
int wc_ImportEccsiKey(EccsiKey* key, const byte* data, word32 sz)
717
89
{
718
89
    int err = 0;
719
720
89
    if ((key == NULL) || (data == NULL)) {
721
0
        err = BAD_FUNC_ARG;
722
0
    }
723
89
    if ((err == 0) && (sz != (word32)key->ecc.dp->size * 3)) {
724
0
        err = BUFFER_E;
725
0
    }
726
727
89
    if (err == 0) {
728
89
        key->kpakMont = 0;
729
730
        /* Decode key */
731
89
        err = eccsi_decode_key(key, data);
732
89
    }
733
89
    if (err == 0) {
734
89
        key->ecc.type = ECC_PRIVATEKEY;
735
89
    }
736
737
89
    return err;
738
89
}
739
740
/**
741
 * Export the ECCSI private key.
742
 *
743
 * Use when saving the KMS key.
744
 *
745
 * Private key is zero padded to key size.
746
 *
747
 * @param  [in]      key   ECCSI key.
748
 * @param  [out]     data  Buffer to hold encoded ECCSI private key.
749
 *                         NULL when requesting required length.
750
 * @param  [in,out]  sz    On in, size of buffer in bytes.
751
 *                         On out, size of encoded ECCSI private key in bytes.
752
 * @return  0 on success.
753
 * @return  BAD_FUNC_ARG when key or sz is NULL
754
 * @return  BAD_STATE_E when no key to export.
755
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
756
 * @return  BUFFER_E when the buffer passed in is too small.
757
 * @return  MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK).
758
 */
759
int wc_ExportEccsiPrivateKey(EccsiKey* key, byte* data, word32* sz)
760
0
{
761
0
    int err = 0;
762
763
0
    if ((key == NULL) || (sz == NULL)) {
764
0
        err = BAD_FUNC_ARG;
765
0
    }
766
767
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) {
768
0
        err = BAD_STATE_E;
769
0
    }
770
771
0
    if (err == 0) {
772
0
        if (data == NULL) {
773
0
            *sz = (word32)key->ecc.dp->size;
774
0
            err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
775
0
        }
776
0
        else if (*sz < (word32)key->ecc.dp->size) {
777
0
            err = BUFFER_E;
778
0
        }
779
0
        else {
780
0
            *sz = (word32)key->ecc.dp->size;
781
0
        }
782
0
    }
783
0
    if (err == 0) {
784
0
        err = mp_to_unsigned_bin_len(wc_ecc_key_get_priv(&key->ecc), data,
785
0
            key->ecc.dp->size);
786
0
    }
787
788
0
    return err;
789
0
}
790
791
/**
792
 * Import the ECCSI private key.
793
 *
794
 * Use when restoring the KMS key pair.
795
 *
796
 * Private key is zero padded to key size.
797
 *
798
 * @param  [in]  key   ECCSI key.
799
 * @param  [in]  data  Buffer holding encoded ECCSI private key.
800
 * @param  [in]  sz    Size of encoded ECCSI private key in bytes.
801
 * @return  0 on success.
802
 * @return  BAD_FUNC_ARG when key or data is NULL.
803
 * @return  BUFFER_E when size of data is not equal to the expected size.
804
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
805
 */
806
int wc_ImportEccsiPrivateKey(EccsiKey* key, const byte* data, word32 sz)
807
0
{
808
0
    int err = 0;
809
810
0
    if ((key == NULL) || (data == NULL)) {
811
0
        err = BAD_FUNC_ARG;
812
0
    }
813
0
    if ((err == 0) && (sz != (word32)key->ecc.dp->size)) {
814
0
        err = BUFFER_E;
815
0
    }
816
817
0
    if (err == 0) {
818
0
        err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
819
0
            (word32)key->ecc.dp->size);
820
0
    }
821
0
    if (err == 0) {
822
0
        err = ecc_blind_k_rng(&key->ecc, NULL);
823
0
    }
824
825
0
    return err;
826
0
}
827
828
/**
829
 * Export the KMS Public Auth Key (KPAK) from the ECCSI object.
830
 *
831
 * KPAK is required by all clients in order to perform cryptographic operations.
832
 *
833
 * X and y ordinate of public key concatenated. Each number is zero padded to
834
 * key size.
835
 * Descriptor byte (0x04) is prepended when not raw.
836
 *
837
 * @param  [in]      key      ECCSI key.
838
 * @param  [out]     data     Buffer to hold the encoded public key.
839
 * @param  [in,out]  sz       On in, size of buffer in bytes.
840
 *                            On out, length of encoded public key in bytes.
841
 * @param  [in]      raw   On 0, prepend descriptor byte.
842
 *                         On 1, only include ordinates.
843
 * @return  0 on success.
844
 * @return  BAD_FUNC_ARG when key or sz is NULL.
845
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
846
 * @return  BUFFER_E when the buffer passed in is too small.
847
 */
848
int wc_ExportEccsiPublicKey(EccsiKey* key, byte* data, word32* sz, int raw)
849
0
{
850
0
    int err = 0;
851
852
0
    if ((key == NULL) || (sz == NULL)) {
853
0
        err = BAD_FUNC_ARG;
854
0
    }
855
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
856
0
            (key->ecc.type != ECC_PUBLICKEY)) {
857
0
        err = BAD_STATE_E;
858
0
    }
859
860
0
    if ((err == 0) && (data != NULL)) {
861
0
        err = eccsi_kpak_from_mont(key);
862
0
    }
863
0
    if (err == 0) {
864
        /* Write out public key. */
865
0
        err = eccsi_encode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size,
866
0
            data, sz, raw);
867
0
    }
868
869
0
    return err;
870
0
}
871
872
/*
873
 * Generates an (SSK, PVT) Pair - signing key pair.
874
 *
875
 * RFC 6507, Section 5.1.1
876
 *
877
 * @param  [in]   key       ECCSI key.
878
 * @param  [in]   rng       Random number generator.
879
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
880
 * @param  [in]   id        Identity to create hash from.
881
 * @param  [in]   idSz      Length of identity in bytes.
882
 * @param  [out]  ssk       Secret Signing Key as an MP integer.
883
 * @param  [out]  pvt       Public Validation Token (PVT) as an ECC point.
884
 * @return  0 on success.
885
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
886
 * @return  Other -ve value when an internal operation fails.
887
 */
888
static int eccsi_make_pair(EccsiKey* key, WC_RNG* rng,
889
        enum wc_HashType hashType, const byte* id, word32 idSz, mp_int* ssk,
890
        ecc_point* pvt)
891
0
{
892
0
    int err = 0;
893
0
    byte hashSz = 0;
894
0
    int genTryCnt = 0;
895
896
0
    do {
897
        /* Don't infinitely make pairs when random number generator fails. */
898
0
        if ((++genTryCnt) > ECCSI_MAX_GEN_COUNT) {
899
0
            err = RNG_FAILURE_E;
900
0
        }
901
902
0
        if (err == 0) {
903
0
            wc_ecc_free(&key->pubkey);
904
905
            /* Step 1 and 2: Generate ephemeral key - v, PVT = [v]G */
906
0
            err = wc_ecc_make_key_ex(rng, key->ecc.dp->size, &key->pubkey,
907
0
                    key->ecc.dp->id);
908
0
        }
909
0
        if (err == 0) {
910
0
            err = wc_ecc_copy_point(&key->pubkey.pubkey, pvt);
911
0
        }
912
913
        /* Step 3: Compute HS */
914
0
        if (err == 0) {
915
0
            hashSz = (byte)sizeof(key->data);
916
0
            err = eccsi_compute_hs(key, hashType, id, idSz, pvt, key->data,
917
0
                    &hashSz);
918
0
        }
919
920
        /* Step 4: Compute SSK = ( KSAK + HS * v ) modulo q */
921
0
        if (err == 0) {
922
0
            err = mp_read_unsigned_bin(ssk, key->data, hashSz);
923
0
        }
924
0
        if (err == 0) {
925
0
            err = mp_mulmod(ssk, wc_ecc_key_get_priv(&key->pubkey),
926
0
                &key->params.order, ssk);
927
0
        }
928
0
        if (err == 0) {
929
0
            err = mp_addmod(ssk, wc_ecc_key_get_priv(&key->ecc),
930
0
                &key->params.order, ssk);
931
0
        }
932
0
    }
933
0
    while ((err == 0) && (mp_iszero(ssk) ||
934
0
            (mp_cmp(ssk, wc_ecc_key_get_priv(&key->ecc)) == MP_EQ)));
935
    /* Step 5: ensure SSK and HS are non-zero (code lines above) */
936
937
    /* Step 6: Copy out SSK (done during calc) and PVT. Erase v */
938
0
    ecc_forcezero_k(&key->pubkey);
939
940
0
    return err;
941
0
}
942
943
/**
944
 * Generates an (SSK, PVT) Pair - signing key pair.
945
 *
946
 * RFC 6507, Section 5.1.1
947
 *
948
 * ID should include information to indicate a revocation date.\n
949
 * SSK must be zeroized after sending to client.\n
950
 * SSK is sent to signing client only.\n
951
 * PVT is sent to all client types.
952
 *
953
 * @param  [in]   key       ECCSI key.
954
 * @param  [in]   rng       Random number generator.
955
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
956
 * @param  [in]   id        Identity to create hash from.
957
 * @param  [in]   idSz      Length of identity in bytes.
958
 * @param  [out]  ssk       Secret Signing Key as an MP integer.
959
 * @param  [out]  pvt       Public Validation Token (PVT) as an ECC point.
960
 * @return  0 on success.
961
 * @return  BAD_FUNC_ARG when key, rng, id, ssk or pvt is NULL.
962
 * @return  BAD_STATE_E when curve not set (key not set).
963
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
964
 * @return  Other -ve value when an internal operation fails.
965
 */
966
int wc_MakeEccsiPair(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
967
        const byte* id, word32 idSz, mp_int* ssk, ecc_point* pvt)
968
0
{
969
0
    int err = 0;
970
971
0
    if ((key == NULL) || (rng == NULL) || (id == NULL) || (ssk == NULL) ||
972
0
            (pvt == NULL)) {
973
0
        err = BAD_FUNC_ARG;
974
0
    }
975
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) {
976
0
        err = BAD_STATE_E;
977
0
    }
978
979
0
    if (err == 0) {
980
0
        err = eccsi_load_order(key);
981
0
    }
982
0
    if (err == 0) {
983
0
        err = eccsi_make_pair(key, rng, hashType, id, idSz, ssk, pvt);
984
0
    }
985
986
0
    return err;
987
0
}
988
989
/**
990
 * Encode the SSK and PVT into a buffer.
991
 *
992
 * SSK and PVT required by client signing messages.
993
 *
994
 * @param  [in]      key   ECCSI key.
995
 * @param  [in]      ssk   Secret Signing Key as an MP integer.
996
 * @param  [in]      pvt   Public Validation Token (PVT) as an ECC point.
997
 * @param  [out]     data  Buffer to encode key pair into.
998
 * @param  [in,out]  sz    In, size of buffer in bytes.
999
 *                         Out, size of encoded pair data in bytes.
1000
 * @return  0 on success.
1001
 * @return  BAD_FUNC_ARG when key, ssk, pvt or sz is NULL.
1002
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1003
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
1004
 */
1005
int wc_EncodeEccsiPair(const EccsiKey* key, mp_int* ssk, ecc_point* pvt,
1006
        byte* data, word32* sz)
1007
0
{
1008
0
    int err = 0;
1009
1010
0
    if ((key == NULL) || (ssk == NULL) || (pvt == NULL) || (sz == NULL)) {
1011
0
        err = BAD_FUNC_ARG;
1012
0
    }
1013
1014
0
    if ((err == 0) && (data == NULL)) {
1015
0
        *sz = (word32)(key->ecc.dp->size * 3);
1016
0
        err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
1017
0
    }
1018
0
    if ((err == 0) && (*sz < (word32)(key->ecc.dp->size * 3))) {
1019
0
        err = BUFFER_E;
1020
0
    }
1021
1022
0
    if (err == 0) {
1023
0
        err = mp_to_unsigned_bin_len(ssk, data, key->ecc.dp->size);
1024
0
    }
1025
0
    if (err == 0) {
1026
0
        data += key->ecc.dp->size;
1027
        /* Write out the PVT's x ordinate into key size bytes. */
1028
0
        err = mp_to_unsigned_bin_len(pvt->x, data, key->ecc.dp->size);
1029
0
    }
1030
0
    if (err == 0) {
1031
0
        data += key->ecc.dp->size;
1032
        /* Write out the PVT's y ordinate into key size bytes. */
1033
0
        err = mp_to_unsigned_bin_len(pvt->y, data, key->ecc.dp->size);
1034
0
    }
1035
0
    if (err == 0) {
1036
0
        *sz = (word32)(key->ecc.dp->size * 3);
1037
0
    }
1038
1039
0
    return err;
1040
0
}
1041
1042
/**
1043
 * Encode the Secret Signing Key (SSK).
1044
 *
1045
 * Use when saving the key pair.
1046
 *
1047
 * SSK is zero padded to key size.
1048
 *
1049
 * @param  [in]      key   ECCSI key.
1050
 * @param  [in]      ssk   Secret Signing Key as an MP integer.
1051
 * @param  [out]     data  Buffer to hold encoded SSK.
1052
 *                         NULL when requesting required length.
1053
 * @param  [in,out]  sz    On in, size of buffer in bytes.
1054
 *                         On out, size of encoded ECCSI key in bytes.
1055
 * @return  0 on success.
1056
 * @return  BAD_FUNC_ARG when key, ssk or sz is NULL
1057
 * @return  BAD_STATE_E when no key to export.
1058
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
1059
 * @return  BUFFER_E when the buffer passed in is too small.
1060
 * @return  MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK).
1061
 */
1062
int wc_EncodeEccsiSsk(const EccsiKey* key, mp_int* ssk, byte* data, word32* sz)
1063
0
{
1064
0
    int err = 0;
1065
1066
0
    if ((key == NULL) || (ssk == NULL) || (sz == NULL)) {
1067
0
        err = BAD_FUNC_ARG;
1068
0
    }
1069
1070
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) {
1071
0
        err = BAD_STATE_E;
1072
0
    }
1073
1074
0
    if (err == 0) {
1075
0
        if (data == NULL) {
1076
0
            *sz = (word32)key->ecc.dp->size;
1077
0
            err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
1078
0
        }
1079
0
        else if (*sz < (word32)key->ecc.dp->size) {
1080
0
            err = BUFFER_E;
1081
0
        }
1082
0
        else {
1083
0
            *sz = (word32)key->ecc.dp->size;
1084
0
        }
1085
0
    }
1086
0
    if (err == 0) {
1087
0
        err = mp_to_unsigned_bin_len(ssk, data, key->ecc.dp->size);
1088
0
    }
1089
1090
0
    return err;
1091
0
}
1092
1093
/**
1094
 * Decode the Secret Signing Key (SSK).
1095
 *
1096
 * Use when restoring the key pair.
1097
 *
1098
 * SSK is zero padded to key size.
1099
 *
1100
 * @param  [in]   key   ECCSI key.
1101
 * @param  [in]   data  Buffer holding encoded ECCSI key.
1102
 * @param  [in]   sz    Size of encoded ECCSI key in bytes.
1103
 * @param  [out]  ssk   Secret Signing Key as an MP integer.
1104
 * @return  0 on success.
1105
 * @return  BAD_FUNC_ARG when key, data or ssk is NULL.
1106
 * @return  BUFFER_E when size of data is not equal to the expected size.
1107
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1108
 */
1109
int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, word32 sz,
1110
        mp_int* ssk)
1111
0
{
1112
0
    int err = 0;
1113
1114
0
    if ((key == NULL) || (data == NULL) || (ssk == NULL)) {
1115
0
        err = BAD_FUNC_ARG;
1116
0
    }
1117
0
    if ((err == 0) && (sz != (word32)key->ecc.dp->size)) {
1118
0
        err = BUFFER_E;
1119
0
    }
1120
1121
0
    if (err == 0) {
1122
0
        err = mp_read_unsigned_bin(ssk, data, (word32)key->ecc.dp->size);
1123
0
    }
1124
1125
0
    return err;
1126
0
}
1127
1128
/**
1129
 * Encode the PVT into a buffer.
1130
 *
1131
 * PVT required by client verifying messages.
1132
 *
1133
 * X and y ordinate of public key concatenated. Each number is zero padded to
1134
 * key size.
1135
 * Descriptor byte (0x04) is prepended when not raw.
1136
 *
1137
 * @param  [in]      key   ECCSI key.
1138
 * @param  [in]      pvt   Public Validation Token (PVT) as an ECC point.
1139
 * @param  [out]     data  Buffer to encode key pair into.
1140
 * @param  [in,out]  sz    In, size of buffer in bytes.
1141
 *                         Out, size of encoded pair data in bytes.
1142
 * @param  [in]      raw   On 0, prepend descriptor byte.
1143
 *                         On 1, only include ordinates.
1144
 * @return  0 on success.
1145
 * @return  BAD_FUNC_ARG when key, pvt or sz is NULL.
1146
 * @return  BAD_STATE_E when PVT has not been set.
1147
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1148
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
1149
 */
1150
int wc_EncodeEccsiPvt(const EccsiKey* key, ecc_point* pvt, byte* data,
1151
        word32* sz, int raw)
1152
0
{
1153
0
    int err = 0;
1154
1155
0
    if ((key == NULL) || (pvt == NULL) || (sz == NULL)) {
1156
0
        err = BAD_FUNC_ARG;
1157
0
    }
1158
1159
0
    if (err == 0) {
1160
0
        err = eccsi_encode_point(pvt, (word32)key->ecc.dp->size, data, sz, raw);
1161
0
    }
1162
1163
0
    return err;
1164
0
}
1165
1166
#endif /* WOLFCRYPT_ECCSI_KMS */
1167
1168
#ifdef WOLFCRYPT_ECCSI_CLIENT
1169
/**
1170
 * Decode the SSK and PVT data into separate variables.
1171
 *
1172
 * A signing client decodes the data so that it can validate the pair and sign.
1173
 *
1174
 * @param  [in]   key   ECCSI key.
1175
 * @param  [in]   data  Buffer holding key pair data.
1176
 * @param  [in]   sz    Size of data in bytes.
1177
 * @param  [out]  ssk   Secret Signing Key as an MP integer.
1178
 * @param  [out]  pvt   Public Validation Token (PVT) as an ECC point.
1179
 * @return  0 on success.
1180
 * @return  BAD_FUNC_ARG when key, data, ssk or pvt is NULL.
1181
 * @return  LENGTH_ONLY_E when data is NULL - sz is set.
1182
 * @return  BUFFER_E when size of data is not equal to the expected size.
1183
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1184
 */
1185
int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, word32 sz,
1186
        mp_int* ssk, ecc_point* pvt)
1187
0
{
1188
0
    int err = 0;
1189
1190
0
    if ((key == NULL) || (data == NULL) || (ssk == NULL) || (pvt == NULL)) {
1191
0
        err = BAD_FUNC_ARG;
1192
0
    }
1193
0
    if ((err == 0) && (sz != (word32)(key->ecc.dp->size * 3))) {
1194
0
        err = BUFFER_E;
1195
0
    }
1196
1197
0
    if (err == 0) {
1198
        /* Read the SSK value from key size bytes. */
1199
0
        err = mp_read_unsigned_bin(ssk, data, (word32)key->ecc.dp->size);
1200
0
    }
1201
0
    if (err == 0) {
1202
0
        data += key->ecc.dp->size;
1203
        /* Read the PVT's x value from key size bytes. */
1204
0
        err = mp_read_unsigned_bin(pvt->x, data, (word32)key->ecc.dp->size);
1205
0
    }
1206
0
    if (err == 0) {
1207
0
        data += key->ecc.dp->size;
1208
        /* Read the PVT's y value from key size bytes. */
1209
0
        err = mp_read_unsigned_bin(pvt->y, data, (word32)key->ecc.dp->size);
1210
0
    }
1211
0
    if (err == 0) {
1212
0
        err = mp_set(pvt->z, 1);
1213
0
    }
1214
1215
0
    return err;
1216
0
}
1217
1218
/**
1219
 * Decode the PVT data into an ECC point.
1220
 *
1221
 * A verifying client decodes the data so that it can verify a message.
1222
 *
1223
 * X and y ordinate of public key concatenated. Each number is zero padded to
1224
 * key size.
1225
 * Descriptor byte (0x04) is prepended when not raw.
1226
 *
1227
 * @param  [in]   key   ECCSI key.
1228
 * @param  [in]   data  Buffer holding PVT data.
1229
 * @param  [in]   sz    Size of data in bytes.
1230
 * @param  [out]  pvt   Public Validation Token (PVT) as an ECC point.
1231
 * @return  0 on success.
1232
 * @return  BAD_FUNC_ARG when key, data, ssk or pvt is NULL.
1233
 * @return  BUFFER_E when size of data is not equal to the expected size.
1234
 * @return  ASN_PARSE_E when format byte is invalid.
1235
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1236
 */
1237
int wc_DecodeEccsiPvt(const EccsiKey* key, const byte* data, word32 sz,
1238
        ecc_point* pvt)
1239
0
{
1240
0
    int err = 0;
1241
1242
0
    if ((key == NULL) || (data == NULL) || (pvt == NULL)) {
1243
0
        err = BAD_FUNC_ARG;
1244
0
    }
1245
1246
0
    if (err == 0) {
1247
0
        err = eccsi_decode_point(pvt, (word32)key->ecc.dp->size, data, sz);
1248
0
    }
1249
1250
0
    return err;
1251
0
}
1252
1253
/**
1254
 * Decode the PVT data, from a signature, into an ECC point.
1255
 *
1256
 * A verifying client decodes the data so that it can calculate the identity
1257
 * hash.
1258
 *
1259
 * X and y ordinate of public key concatenated. Each number is zero padded to
1260
 * key size.
1261
 * Descriptor byte (0x04) is prepended when not raw.
1262
 *
1263
 * @param  [in]   key   ECCSI key.
1264
 * @param  [in]   sig   Buffer holding signature data.
1265
 * @param  [in]   sz    Size of data in bytes.
1266
 * @param  [out]  pvt   Public Validation Token (PVT) as an ECC point.
1267
 * @return  0 on success.
1268
 * @return  BAD_FUNC_ARG when key, data, ssk or pvt is NULL.
1269
 * @return  BUFFER_E when size of data is not equal to the expected size.
1270
 * @return  ASN_PARSE_E when format byte is invalid.
1271
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1272
 */
1273
int wc_DecodeEccsiPvtFromSig(const EccsiKey* key, const byte* sig, word32 sz,
1274
        ecc_point* pvt)
1275
0
{
1276
0
    int err = 0;
1277
1278
0
    if ((key == NULL) || (sig == NULL) || (pvt == NULL)) {
1279
0
        err = BAD_FUNC_ARG;
1280
0
    }
1281
1282
0
    if (err == 0) {
1283
0
        word32 rSz = (word32)(key->ecc.dp->size * 2);
1284
0
        err = eccsi_decode_point(pvt, (word32)key->ecc.dp->size, sig + rSz,
1285
0
                sz - rSz);
1286
0
    }
1287
1288
0
    return err;
1289
0
}
1290
1291
/**
1292
 * Import the KMS Public Auth Key (KPAK) into the ECCSI object.
1293
 *
1294
 * Clients import the KPAK to perform cryptographic operations.
1295
 *
1296
 * X and y ordinate of public key concatenated. Each number is zero padded to
1297
 * key size.
1298
 * Descriptor byte (0x04) is prepended when not raw.
1299
 *
1300
 * @param  [in]  key      ECCSI key.
1301
 * @param  [in]  data     Encoded public key as an array of bytes.
1302
 * @param  [in]  sz       Length of encoded KPAK in bytes.
1303
 * @param  [in]  trusted  1 when public key is trusted.
1304
 *                        0 when validation is required to be performed.
1305
 * @return  0 on success.
1306
 * @return  BAD_FUNC_ARG when key or data is NULL.
1307
 * @return  BUFFER_E when size of data is not equal to the expected size.
1308
 * @return  ASN_PARSE_E when format byte is invalid.
1309
 * @return  ECC_OUT_OF_RANGE_E when point is invalid.
1310
 * @return  ECC_INF_E when point is at infinity and invalid.
1311
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1312
 */
1313
int wc_ImportEccsiPublicKey(EccsiKey* key, const byte* data, word32 sz,
1314
        int trusted)
1315
0
{
1316
0
    int err = 0;
1317
1318
0
    if ((key == NULL) || (data == NULL)) {
1319
0
        err = BAD_FUNC_ARG;
1320
0
    }
1321
1322
0
    if (err == 0) {
1323
0
        key->kpakMont = 0;
1324
1325
        /* Read the public key. */
1326
0
        err = eccsi_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size,
1327
0
                data, sz);
1328
0
    }
1329
0
    if (err == 0) {
1330
0
        key->ecc.type = ECC_PUBLICKEY;
1331
0
    }
1332
0
    if ((err == 0) && (!trusted)) {
1333
0
       err = wc_ecc_check_key(&key->ecc);
1334
0
    }
1335
1336
0
    return err;
1337
0
}
1338
1339
/*
1340
 * Scalar multiply the base point of the curve and add a point.
1341
 *
1342
 * @param  [in]   key   ECCSI key.
1343
 * @param  [in]   n     MP integer representing scalar to multiply by.
1344
 * @param  [in]   a     ECC point to add.
1345
 * @param  [out]  res   ECC point representation of the resulting point.
1346
 * @param  [in]   mp    Montgomery reduction multiplier.
1347
 * @param  [in]   map   0 indicates to leave in projective representation.
1348
 *                      1 indicates map projective point to affine.
1349
 * @return  0 on success.
1350
 * @return  MEMORY_E when dynamic memory allocation fails.
1351
 * @return  Other -ve value when an internal operation fails.
1352
 */
1353
static int eccsi_mulmod_base_add(EccsiKey* key, const mp_int* n,
1354
        ecc_point* a, ecc_point* res, mp_digit mp, int map)
1355
0
{
1356
0
    int err = 0;
1357
1358
#if defined(WOLFSSL_HAVE_SP_ECC) && !defined(WOLFSSL_SP_NO_256)
1359
    if ((key->ecc.idx != ECC_CUSTOM_IDX) &&
1360
            (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) {
1361
        err = sp_ecc_mulmod_base_add_256(n, a, 1, res, map, key->heap);
1362
    }
1363
    else
1364
#endif
1365
0
#ifndef WOLFSSL_SP_MATH
1366
0
    {
1367
0
        EccsiKeyParams* params = &key->params;
1368
0
        err = wc_ecc_mulmod(n, params->base, params->base, &params->a,
1369
0
                &params->prime, 0);
1370
0
        key->params.haveBase = 0;
1371
0
        if (err == 0) {
1372
0
            err = ecc_projective_add_point(params->base, a, res, &params->a,
1373
0
                    &params->prime, mp);
1374
0
        }
1375
0
        if ((err == 0) && map) {
1376
0
            err = ecc_map(res, &params->prime, mp);
1377
0
        }
1378
0
    }
1379
#else
1380
    {
1381
        err = NOT_COMPILED_IN;
1382
    }
1383
    (void)key;
1384
    (void)n;
1385
    (void)a;
1386
    (void)res;
1387
    (void)mp;
1388
    (void)map;
1389
#endif
1390
1391
0
    return err;
1392
0
}
1393
1394
/*
1395
 * Scalar multiply a point on the curve.
1396
 *
1397
 * @param  [in]   key    ECCSI key.
1398
 * @param  [in]   n      MP integer representing scalar to multiply by.
1399
 * @param  [in]   point  ECC point representation of a point on the curve.
1400
 * @param  [out]  res    ECC point representation of the resulting point.
1401
 * @param  [in]   map    0 indicates to leave in projective representation.
1402
 *                       1 indicates map projective point to affine.
1403
 * @return  0 on success.
1404
 * @return  MEMORY_E when dynamic memory allocation fails.
1405
 * @return  Other -ve value when an internal operation fails.
1406
 */
1407
static int eccsi_mulmod_point(EccsiKey* key, const mp_int* n, ecc_point* point,
1408
        ecc_point* res, int map)
1409
0
{
1410
0
    int err;
1411
1412
#if defined(WOLFSSL_HAVE_SP_ECC) && !defined(WOLFSSL_SP_NO_256)
1413
    if ((key->ecc.idx != ECC_CUSTOM_IDX) &&
1414
            (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) {
1415
        err = sp_ecc_mulmod_256(n, point, res, map, key->heap);
1416
    }
1417
    else
1418
#endif
1419
0
    {
1420
0
        EccsiKeyParams* params = &key->params;
1421
1422
0
        err = wc_ecc_mulmod(n, point, res, &params->a, &params->prime, map);
1423
0
    }
1424
1425
0
    return err;
1426
0
}
1427
1428
/*
1429
 * Scalar multiply a point on the curve and add a.
1430
 *
1431
 * @param  [in]   key    ECCSI key.
1432
 * @param  [in]   n      MP integer representing scalar to multiply by.
1433
 * @param  [in]   point  ECC point representation of a point on the curve.
1434
 * @param  [in]   a      ECC point to add.
1435
 * @param  [out]  res    ECC point representation of the resulting point.
1436
 * @param  [in]   mp     Montgomery reduction multiplier.
1437
 * @param  [in]   map    0 indicates to leave in projective representation.
1438
 *                       1 indicates map projective point to affine.
1439
 * @return  0 on success.
1440
 * @return  MEMORY_E when dynamic memory allocation fails.
1441
 * @return  Other -ve value when an internal operation fails.
1442
 */
1443
static int eccsi_mulmod_point_add(EccsiKey* key, const mp_int* n,
1444
        ecc_point* point, ecc_point* a, ecc_point* res, mp_digit mp, int map)
1445
0
{
1446
#if defined(WOLFSSL_HAVE_SP_ECC) && !defined(WOLFSSL_SP_NO_256)
1447
    int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
1448
1449
    if ((key->ecc.idx != ECC_CUSTOM_IDX) &&
1450
            (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) {
1451
        err = sp_ecc_mulmod_add_256(n, point, a, 0, res, map, key->heap);
1452
    }
1453
1454
    (void)mp;
1455
1456
    return err;
1457
#else
1458
0
    int err;
1459
0
    EccsiKeyParams* params = &key->params;
1460
1461
0
    err = wc_ecc_mulmod(n, point, res, &params->a, &params->prime, 0);
1462
0
    if (err == 0) {
1463
0
        err = ecc_projective_add_point(res, a, res, &key->params.a,
1464
0
                &params->prime, mp);
1465
0
    }
1466
0
    if ((err == 0) && map) {
1467
0
        err = ecc_map(res, &params->prime, mp);
1468
0
    }
1469
1470
0
    return err;
1471
0
#endif
1472
0
}
1473
1474
/**
1475
 * Validate an (SSV, PVT) Pair.
1476
 *
1477
 * RFC 6507, Section 5.1.2
1478
 *
1479
 * A signing client should validate the key pair before first use.
1480
 *
1481
 * @param  [in]   key       ECCSI key.
1482
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1483
 * @param  [in]   id        Identity to create hash from.
1484
 * @param  [in]   idSz      Length of identity in bytes.
1485
 * @param  [in]   ssk       Secret Signing Key as an MP integer.
1486
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
1487
 * @param  [out]  valid     1 when pair is valid and 0 otherwise.
1488
 * @return  0 on success.
1489
 * @return  BAD_FUNC_ARG when key, id, ssk, pvt or valid is NULL.
1490
 * @return  BAD_STATE_E when curve not set (key not set).
1491
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1492
 * @return  IS_POINT_E when point is not on the curve.
1493
 * @return  Other -ve value when an internal operation fails.
1494
 */
1495
int wc_ValidateEccsiPair(EccsiKey* key, enum wc_HashType hashType,
1496
        const byte* id, word32 idSz, const mp_int* ssk, ecc_point* pvt,
1497
        int* valid)
1498
0
{
1499
0
    int err = 0;
1500
0
    ecc_point* res = NULL;
1501
0
    mp_int* hs = NULL;
1502
0
    mp_digit mp = 0;
1503
0
    byte hashSz = 0;
1504
0
    EccsiKeyParams* params = NULL;
1505
1506
0
    if ((key == NULL) || (id == NULL) || (ssk == NULL) || (pvt == NULL) ||
1507
0
            (valid == NULL)) {
1508
0
        err = BAD_FUNC_ARG;
1509
0
    }
1510
1511
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
1512
0
            (key->ecc.type != ECC_PUBLICKEY)) {
1513
0
        err = BAD_STATE_E;
1514
0
    }
1515
1516
0
    if (err != 0)
1517
0
        return err;
1518
1519
0
    params = &key->params;
1520
0
    hs = &key->tmp;
1521
0
    res = &key->pubkey.pubkey;
1522
1523
0
    err = eccsi_load_base(key);
1524
1525
0
    if (err == 0) {
1526
0
       err = eccsi_load_ecc_params(key);
1527
0
    }
1528
0
    if (err == 0) {
1529
0
        err = mp_montgomery_setup(&params->prime, &mp);
1530
0
    }
1531
1532
    /* Step 1: Validate PVT is on curve */
1533
0
    if (err == 0) {
1534
0
        err = wc_ecc_is_point(pvt, &params->a, &params->b, &params->prime);
1535
0
        if (err == -1) {
1536
0
            err = IS_POINT_E;
1537
0
        }
1538
0
    }
1539
1540
    /* Step 2: Compute HS = hash( G | KPAK | ID | PVT ) */
1541
0
    if (err == 0) {
1542
0
        hashSz = (byte)sizeof(key->data);
1543
        /* Converts KPAK from mont. */
1544
0
        err = eccsi_compute_hs(key, hashType, id, idSz, pvt, key->data,
1545
0
                &hashSz);
1546
0
    }
1547
1548
    /* Step 3: Validate that KPAK = [SSK]G - [HS]PVT */
1549
0
    if (err == 0) {
1550
0
        err = mp_read_unsigned_bin(hs, key->data, hashSz);
1551
0
    }
1552
    /* [HS]PVT */
1553
0
    if (err == 0) {
1554
0
        err = eccsi_mulmod_point(key, hs, pvt, res, 0);
1555
0
    }
1556
    /* -[HS]PVT */
1557
0
    if (err == 0) {
1558
0
        err = mp_sub(&params->prime, res->y, res->y);
1559
0
    }
1560
    /* [SSK]G + -[HS]PVT */
1561
0
    if (err == 0) {
1562
0
        err = eccsi_mulmod_base_add(key, ssk, res, res, mp, 1);
1563
0
    }
1564
0
    if (valid != NULL) {
1565
0
        *valid = (err == 0);
1566
0
        if (err == 0) {
1567
0
            ecc_point* kpak = &key->ecc.pubkey;
1568
            /* Compare KPAK and [SSK]G + -[HS]PVT */
1569
0
            *valid = (wc_ecc_cmp_point(res, kpak) == MP_EQ);
1570
0
        }
1571
0
    }
1572
1573
0
    return err;
1574
0
}
1575
1576
/**
1577
 * Validate Public Validation Token (PVT) is on the curve.
1578
 *
1579
 * RFC 6507, Section 5.1.2, Step 1
1580
 *
1581
 * A verifying client should validate the PVT before first use.
1582
 *
1583
 * @param  [in]   key       ECCSI key.
1584
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
1585
 * @param  [out]  valid     1 when PVT is valid and 0 otherwise.
1586
 * @return  0 on success.
1587
 * @return  BAD_FUNC_ARG when key, pvt or valid is NULL.
1588
 * @return  BAD_STATE_E when curve not set (key not set).
1589
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1590
 * @return  Other -ve value when an internal operation fails.
1591
 */
1592
int wc_ValidateEccsiPvt(EccsiKey* key, const ecc_point* pvt, int* valid)
1593
0
{
1594
0
    int err = 0;
1595
1596
0
    if ((key == NULL)| (pvt == NULL) || (valid == NULL)) {
1597
0
        err = BAD_FUNC_ARG;
1598
0
    }
1599
1600
0
    if (err == 0) {
1601
0
        err = wc_ecc_set_curve(&key->pubkey, key->ecc.dp->size,
1602
0
                key->ecc.dp->id);
1603
0
    }
1604
0
    if (err == 0) {
1605
0
        err = wc_ecc_copy_point(pvt, &key->pubkey.pubkey);
1606
0
    }
1607
0
    if (err == 0) {
1608
0
        *valid = (wc_ecc_check_key(&key->pubkey) == 0);
1609
0
    }
1610
1611
0
    return err;
1612
0
}
1613
1614
/**
1615
 * Creates the Hash of the ID and PVT with the ECCSI key.
1616
 *
1617
 * The hash ID is required as input to the sign and verify operations.\n
1618
 * Signing clients may cache this value.
1619
 *
1620
 * RFC 6507, Section 5.2.1, Step 3
1621
 *
1622
 * Set the calculated hash internally for use.
1623
 *
1624
 * @param  [in]   key       ECCSI key.
1625
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1626
 * @param  [in]   id        Identity to create hash from.
1627
 * @param  [in]   idSz      Length of identity in bytes.
1628
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
1629
 * @param  [out]  hash      Buffer to hold hash result.
1630
 * @param  [out]  hashSz    Length of hash data in bytes.
1631
 * @return  0 on success.
1632
 * @return  BAD_FUNC_ARG when key, id, pvt, hash or hashSz is NULL.
1633
 * @return  BAD_FUNC_ARG when hash size doesn't match curve size.
1634
 * @return  BAD_STATE_E when public key not set.
1635
 * @return  MEMORY_E when dynamic memory allocation fails.
1636
 * @return  Other -ve value when an internal operation fails.
1637
 */
1638
int wc_HashEccsiId(EccsiKey* key, enum wc_HashType hashType, const byte* id,
1639
        word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz)
1640
0
{
1641
0
    int err = 0;
1642
0
    int dgstSz = -1;
1643
0
    int curveSz = -1;
1644
1645
0
    if ((key == NULL) || (id == NULL) || (pvt == NULL) || (hash == NULL) ||
1646
0
            (hashSz == NULL)) {
1647
0
        err = BAD_FUNC_ARG;
1648
0
    }
1649
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
1650
0
            (key->ecc.type != ECC_PUBLICKEY)) {
1651
0
        err = BAD_STATE_E;
1652
0
    }
1653
    /* Ensure digest output size matches curve size (RFC 6507 4.1). */
1654
0
    if (err == 0) {
1655
0
        dgstSz = wc_HashGetDigestSize(hashType);
1656
0
        if (dgstSz < 0) {
1657
0
            err = dgstSz;
1658
0
        }
1659
0
    }
1660
0
    if (err == 0) {
1661
0
        curveSz = wc_ecc_get_curve_size_from_id(key->ecc.dp->id);
1662
0
        if (curveSz < 0) {
1663
0
            err = curveSz;
1664
0
        }
1665
0
    }
1666
0
    if ((err == 0) && (dgstSz != curveSz)) {
1667
0
        err = BAD_FUNC_ARG;
1668
0
    }
1669
    /* Load the curve parameters for operations */
1670
0
    if (err == 0) {
1671
0
       err = eccsi_load_ecc_params(key);
1672
0
    }
1673
0
    if (err == 0) {
1674
0
        err = eccsi_compute_hs(key, hashType, id, idSz, pvt, hash, hashSz);
1675
0
    }
1676
0
    if (err == 0) {
1677
0
        XMEMCPY(key->idHash, hash, *hashSz);
1678
0
        key->idHashSz = *hashSz;
1679
0
    }
1680
1681
0
    return err;
1682
0
}
1683
1684
/**
1685
 * Set the identity hash for use with signing/verification.
1686
 *
1687
 * @param  [in]  key     ECCSI key.
1688
 * @param  [in]  hash    Buffer with hash of identity.
1689
 * @param  [in]  hashSz  Length of hash data in bytes.
1690
 * @return  0 on success.
1691
 * @return  BAD_FUNC_ARG when key or hash is NULL, or hashSz is greater than
1692
 *          WC_MAX_DIGEST_SIZE.
1693
 */
1694
int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz)
1695
0
{
1696
0
    int err = 0;
1697
1698
0
    if ((key == NULL) || (hash == NULL) || (hashSz > WC_MAX_DIGEST_SIZE)) {
1699
0
        err = BAD_FUNC_ARG;
1700
0
    }
1701
0
    if (err == 0) {
1702
0
        XMEMCPY(key->idHash, hash, hashSz);
1703
0
        key->idHashSz = hashSz;
1704
0
    }
1705
1706
0
    return err;
1707
0
}
1708
1709
/**
1710
 * Set an (SSV, PVT) Pair for signing.
1711
 *
1712
 * @param  [in]   key  ECCSI key.
1713
 * @param  [in]   ssk  Secret Signing Key as an MP integer.
1714
 * @param  [in]   pvt  Public Validation Token (PVT) as an ECC point.
1715
 * @return  0 on success.
1716
 * @return  BAD_FUNC_ARG when key, ssk or pvt is NULL.
1717
 * @return  MP math errors when copy fails
1718
 */
1719
int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, const ecc_point* pvt)
1720
0
{
1721
0
    int err = 0;
1722
1723
0
    if ((key == NULL) || (ssk == NULL) || (pvt == NULL)) {
1724
0
        err = BAD_FUNC_ARG;
1725
0
    }
1726
1727
0
    if (err == 0) {
1728
0
        err = mp_copy(ssk, &key->ssk);
1729
0
    }
1730
1731
0
    if (err == 0) {
1732
0
        err = wc_ecc_copy_point(pvt, key->pvt);
1733
0
    }
1734
1735
0
    return err;
1736
0
}
1737
1738
#ifdef ECCSI_ORDER_MORE_BITS_THAN_PRIME
1739
/*
1740
 * Fit the number to the maximum number of bytes.
1741
 *
1742
 * If the number is too big then subtract from order.
1743
 * RFC 6507, Section 5.2.1, Note at end.
1744
 * This should only happen when order is larger than prime in bits.
1745
 *
1746
 * @param  [in]   a      MP integer to fix.
1747
 * @param  [in]   order  MP integer representing order of curve.
1748
 * @param  [in]   m      Maximum number of bytes to encode into.
1749
 * @param  [out]  r      MP integer that is the result after fixing.
1750
 * @return  0 on success.
1751
 * @return  MEMORY_E when dynamic memory allocation fails.
1752
 */
1753
static int eccsi_fit_to_octets(const mp_int* a, mp_int* order, int m,
1754
        mp_int* r)
1755
{
1756
    int err;
1757
1758
    if (mp_count_bits(a) > m * 8) {
1759
        err = mp_sub(order, (mp_int*)a, r);
1760
    }
1761
    else
1762
    {
1763
        err = mp_copy(a, r);
1764
    }
1765
1766
    return err;
1767
}
1768
#else
1769
/*
1770
 * Fit the number to the maximum number of bytes.
1771
 *
1772
 * If the number is too big then subtract from order.
1773
 * RFC 6507, Section 5.2.1, Note at end.
1774
 * This should only happen when order is larger than prime in bits.
1775
 *
1776
 * @param  [in]   a      MP integer to fix.
1777
 * @param  [in]   order  MP integer representing order of curve.
1778
 * @param  [in]   m      Maximum number of bytes to encode into.
1779
 * @param  [out]  r      MP integer that is the result after fixing.
1780
 * @return  0 on success.
1781
 * @return  MEMORY_E when dynamic memory allocation fails.
1782
 */
1783
static int eccsi_fit_to_octets(const mp_int* a, const mp_int* order, int m,
1784
        mp_int* r)
1785
0
{
1786
0
    (void)order;
1787
0
    (void)m;
1788
1789
    /* Duplicate line to stop static analyzer complaining. */
1790
0
    return mp_copy(a, r);
1791
0
}
1792
#endif
1793
1794
/*
1795
 * Compute the HE = hash( HS | r | M ), hash value of signature.
1796
 *
1797
 * Partial result required for signing and verification.
1798
 *
1799
 * @param  [in]   key       ECCSI key.
1800
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1801
 * @param  [in]   r         MP integer that is the first signature element.
1802
 * @param  [in]   msg       Message of signature.
1803
 * @param  [in]   msgSz     Length of message in bytes.
1804
 * @param  [out]  he        Signature hash.
1805
 * @param  [out]  heSz      Length of signature hash in bytes
1806
 * @return  0 on success.
1807
 * @return  MEMORY_E when dynamic memory allocation fails.
1808
 * @return  Other -ve value when an internal operation fails.
1809
 */
1810
static int eccsi_compute_he(EccsiKey* key, enum wc_HashType hashType,
1811
        mp_int* r, const byte* msg, word32 msgSz, byte* he, word32* heSz)
1812
0
{
1813
0
    int err = 0;
1814
0
    word32 dataSz = (word32)key->ecc.dp->size;
1815
0
    int hash_inited = 0;
1816
1817
    /* HE = hash( HS | r | M ) */
1818
0
    err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID);
1819
0
    if (err == 0) {
1820
0
        hash_inited = 1;
1821
        /* HS */
1822
0
        err = wc_HashUpdate(&key->hash, hashType, key->idHash, key->idHashSz);
1823
0
    }
1824
0
    if (err == 0) {
1825
0
        err = mp_to_unsigned_bin_len(r, key->data, (int)dataSz);
1826
0
    }
1827
0
    if (err == 0) {
1828
        /* r */
1829
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
1830
0
    }
1831
0
    if (err == 0) {
1832
        /* M */
1833
0
        err = wc_HashUpdate(&key->hash, hashType, msg, msgSz);
1834
0
    }
1835
0
    if (err == 0) {
1836
0
        err = wc_HashFinal(&key->hash, hashType, he);
1837
0
    }
1838
0
    if (err == 0) {
1839
0
        *heSz = (word32)wc_HashGetDigestSize(hashType);
1840
0
    }
1841
1842
0
    if (hash_inited) {
1843
0
        (void)wc_HashFree(&key->hash, hashType);
1844
0
    }
1845
1846
0
    return err;
1847
0
}
1848
1849
/*
1850
 * Encode the signature = ( r | s | PVT )
1851
 *
1852
 * @param  [in]   key    ECCSI key.
1853
 * @param  [in]   r      MP integer that is the first signature element.
1854
 * @param  [in]   s      MP integer that is the second signature element.
1855
 * @param  [in]   pvt    ECC point representing Public Validation Token.
1856
 * @param  [out]  sig    Signature of message.
1857
 * @param  [out]  sigSz  Length of signature in bytes.
1858
 */
1859
static int eccsi_encode_sig(const EccsiKey* key, mp_int* r, mp_int* s,
1860
        byte* sig, word32* sigSz)
1861
0
{
1862
0
    int err;
1863
0
    word32 sz = (word32)key->ecc.dp->size;
1864
1865
0
    err = mp_to_unsigned_bin_len(r, sig, (int)sz);
1866
0
    if (err == 0) {
1867
0
        err = mp_to_unsigned_bin_len(s, sig + sz, (int)sz);
1868
0
    }
1869
0
    if (err == 0) {
1870
0
        *sigSz = (word32)(key->ecc.dp->size * 2 + 1);
1871
0
        err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(key->ecc.dp->id),
1872
0
                 key->pvt, sig + sz * 2, sigSz);
1873
0
    }
1874
0
    if (err == 0) {
1875
0
        *sigSz = sz * 4 + 1;
1876
0
    }
1877
1878
0
    return err;
1879
0
}
1880
1881
/*
1882
 * Sign the ECCSI hash (of ID with the key) to two mp_int objects: r and s.
1883
 *
1884
 * RFC 6507, Section 5.2.1, Steps 1 to 4
1885
 *
1886
 * @param  [in]   key       ECCSI key.
1887
 * @param  [in]   rng       Random number generator.
1888
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1889
 * @param  [in]   msg       Message to sign.
1890
 * @param  [in]   msgSz     Length of message in bytes.
1891
 * @param  [out]  r         First big number integer part of signature.
1892
 * @param  [out]  s         Second big number integer part of signature.
1893
 * @return  0 on success.
1894
 * @return  MEMORY_E when dynamic memory allocation fails.
1895
 * @return  Other -ve value when an internal operation fails.
1896
 */
1897
static int eccsi_gen_sig(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
1898
        const byte* msg, word32 msgSz, mp_int* r, mp_int* s)
1899
0
{
1900
0
    int err = 0;
1901
0
    int sz = key->ecc.dp->size;
1902
0
    word32 heSz = 0;
1903
0
    const mp_int* jx = NULL;
1904
0
    mp_int* he = &key->tmp;
1905
0
    int genTryCnt = 0;
1906
1907
0
    do {
1908
        /* Don't infinitely gen sigs when random number generator fails. */
1909
0
        if ((++genTryCnt) > ECCSI_MAX_GEN_COUNT) {
1910
0
            err = RNG_FAILURE_E;
1911
0
        }
1912
1913
0
        if (err == 0) {
1914
0
            wc_ecc_free(&key->pubkey);
1915
1916
            /* Step 1 and 2: Generate ephemeral key - j, J = [j]G, r = Jx */
1917
0
            err = wc_ecc_make_key_ex(rng, sz, &key->pubkey, key->ecc.dp->id);
1918
0
        }
1919
0
        if (err == 0) {
1920
0
            jx = key->pubkey.pubkey.x;
1921
0
            err = eccsi_fit_to_octets(jx, &key->params.order, sz, r);
1922
0
        }
1923
1924
        /* Step 3: Compute HE = hash( HS | r | M ) */
1925
0
        if (err == 0) {
1926
0
            err = eccsi_compute_he(key, hashType, r, msg, msgSz, key->data,
1927
0
                    &heSz);
1928
0
        }
1929
1930
        /* Step 4: Verify that HE + r * SSK is non-zero modulo q */
1931
0
        if (err == 0) {
1932
0
            err = mp_read_unsigned_bin(he, key->data, heSz);
1933
0
        }
1934
        /* s' = r * SSK */
1935
0
        if (err == 0) {
1936
0
            err = mp_mulmod(r, &key->ssk, &key->params.order, s);
1937
0
        }
1938
        /* s' = HE + r * SSK */
1939
0
        if (err == 0) {
1940
0
            err = mp_addmod(he, s, &key->params.order, s);
1941
0
        }
1942
0
    }
1943
0
    while ((err == 0) && (mp_iszero(s) || (mp_cmp(s, he) == MP_EQ)));
1944
1945
0
    return err;
1946
0
}
1947
1948
1949
/**
1950
 * Sign the ECCSI hash (of ID with the key).
1951
 *
1952
 * RFC 6507, Section 5.2.1
1953
 *
1954
 * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n
1955
 * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set
1956
 * the identity hash to use.
1957
 *
1958
 * @param  [in]   key       ECCSI key.
1959
 * @param  [in]   rng       Random number generator.
1960
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1961
 * @param  [in]   msg       Message to sign.
1962
 * @param  [in]   msgSz     Length of message in bytes.
1963
 * @param  [out]  sig       Signature of message.
1964
 * @param  [out]  sigSz     Length of signature in bytes.
1965
 * @return  0 on success.
1966
 * @return  BAD_FUNC_ARG when key, rng, msg or sigSz is NULL.
1967
 * @return  BAD_STATE_E when the curve or id hash has not been set (no key set).
1968
 * @return  LENGTH_ONLY_E when sig is NULL - sigSz is set.
1969
 * @return  MEMORY_E when dynamic memory allocation fails.
1970
 * @return  Other -ve value when an internal operation fails.
1971
 */
1972
int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
1973
        const byte* msg, word32 msgSz, byte* sig, word32* sigSz)
1974
0
{
1975
0
    int err = 0;
1976
0
    mp_int* r = NULL;
1977
0
    mp_int* s = NULL;
1978
0
    mp_int* j = NULL;
1979
0
    word32 sz = 0;
1980
1981
0
    if ((key == NULL) || (rng == NULL) || (msg == NULL) || (sigSz == NULL)) {
1982
0
        err = BAD_FUNC_ARG;
1983
0
    }
1984
0
    if ((err == 0) && (key->ecc.type != ECC_PUBLICKEY) &&
1985
0
            (key->ecc.type != ECC_PRIVATEKEY)) {
1986
0
        err = BAD_STATE_E;
1987
0
    }
1988
0
    if ((err == 0) && (sig != NULL) && (key->idHashSz == 0)) {
1989
0
        err = BAD_STATE_E;
1990
0
    }
1991
1992
0
    if (err == 0)  {
1993
0
        sz = (word32)key->ecc.dp->size;
1994
0
        if (sig == NULL) {
1995
0
            *sigSz = sz * 4 + 1;
1996
0
            err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
1997
0
        }
1998
0
    }
1999
0
    if ((err == 0) && (*sigSz < sz * 4 + 1)) {
2000
0
        err = BAD_FUNC_ARG;
2001
0
    }
2002
2003
0
    if (err == 0) {
2004
0
        r = key->pubkey.pubkey.y;
2005
0
        s = key->pubkey.pubkey.z;
2006
2007
0
        err = eccsi_load_order(key);
2008
0
    }
2009
2010
0
    if (err == 0) {
2011
        /* Steps 1 to 4. */
2012
0
        err = eccsi_gen_sig(key, rng, hashType, msg, msgSz, r, s);
2013
0
    }
2014
2015
    /* Step 5: s' = ( (( HE + r * SSK )^-1) * j ) modulo q, erase j */
2016
0
    if (err == 0) {
2017
0
        err = mp_invmod(s, &key->params.order, s);
2018
0
    }
2019
0
    if (err == 0) {
2020
0
        j = wc_ecc_key_get_priv(&key->pubkey);
2021
0
        err = mp_mulmod(s, j, &key->params.order, s);
2022
        /* Erase j on the failure path too. */
2023
0
        ecc_forcezero_k(&key->pubkey);
2024
0
    }
2025
0
    if (err == 0) {
2026
        /* Step 6: s = s' fitted */
2027
0
        err = eccsi_fit_to_octets(s, &key->params.order, (int)sz, s);
2028
0
    }
2029
2030
    /* Step 7: Output Signature = ( r | s | PVT ) */
2031
0
    if (err == 0) {
2032
0
        err = eccsi_encode_sig(key, r, s, sig, sigSz);
2033
0
    }
2034
2035
0
    return err;
2036
0
}
2037
2038
/*
2039
 * Decode the s part of the signature = ( r | s | PVT )
2040
 *
2041
 * @param  [in]   key    ECCSI key.
2042
 * @param  [in]   sig    Signature of message.
2043
 * @param  [in]   sigSz  Length of signature in bytes.
2044
 * @param  [out]  s      MP integer that is the second signature element.
2045
 * @return  0 on success.
2046
 * @return  MEMORY_E when dynamic memory allocation fails.
2047
 * @return  Other -ve value when an internal operation fails.
2048
 */
2049
static int eccsi_decode_sig_s(const EccsiKey* key, const byte* sig,
2050
        word32 sigSz, mp_int* s)
2051
0
{
2052
0
    int err = 0;
2053
0
    word32 sz = (word32)key->ecc.dp->size;
2054
2055
0
    if (sigSz != sz * 4 + 1) {
2056
0
        err = BAD_FUNC_ARG;
2057
0
    }
2058
2059
0
    if (err == 0) {
2060
0
        err = mp_read_unsigned_bin(s, sig + sz, sz);
2061
0
    }
2062
2063
0
    return err;
2064
0
}
2065
2066
/*
2067
 * Decode the r and pvt part of the signature = ( r | s | PVT )
2068
 *
2069
 * @param  [in]   key    ECCSI key.
2070
 * @param  [in]   sig    Signature of message.
2071
 * @param  [in]   sigSz  Length of signature in bytes.
2072
 * @param  [out]  r      MP integer that is the first signature element.
2073
 * @param  [out]  pvt    ECC point representing Public Validation Token.
2074
 * @return  0 on success.
2075
 * @return  MEMORY_E when dynamic memory allocation fails.
2076
 * @return  Other -ve value when an internal operation fails.
2077
 */
2078
static int eccsi_decode_sig_r_pvt(const EccsiKey* key, const byte* sig,
2079
        word32 sigSz, mp_int* r, ecc_point* pvt)
2080
0
{
2081
0
    int err = 0;
2082
0
    word32 sz = (word32)key->ecc.dp->size;
2083
2084
0
    if (sigSz != sz * 4 + 1) {
2085
0
        err = BAD_FUNC_ARG;
2086
0
    }
2087
2088
0
    if (err == 0) {
2089
0
        err = mp_read_unsigned_bin(r, sig, sz);
2090
0
    }
2091
0
    if (err == 0) {
2092
        /* must free previous public point otherwise wc_ecc_import_point_der
2093
         * could leak memory */
2094
0
        mp_clear(pvt->x);
2095
0
        mp_clear(pvt->y);
2096
0
        mp_clear(pvt->z);
2097
2098
0
        err = wc_ecc_import_point_der(sig + sz * 2, sz * 2 + 1,
2099
0
                wc_ecc_get_curve_idx(key->ecc.dp->id), pvt);
2100
0
    }
2101
2102
0
    return err;
2103
0
}
2104
2105
/*
2106
 * Calculate Y point as part of verification process.
2107
 *
2108
 * Y = [HS]PVT + KPAK
2109
 *
2110
 * @param  [in]   key      ECCSI key.
2111
 * @param  [in]   pvt      ECC point representing Public Validation Token.
2112
 * @param  [in]   mp       Montgomery reduction multiplier.
2113
 * @param  [out]  y        ECC point representing calculated value Y.
2114
 * @return  0 on success.
2115
 * @return  MEMORY_E when dynamic memory allocation fails.
2116
 * @return  Other value when an an internal operation fails.
2117
 */
2118
static int eccsi_calc_y(EccsiKey* key, ecc_point* pvt, mp_digit mp,
2119
        ecc_point* y)
2120
0
{
2121
0
    int err;
2122
0
    mp_int* hs = &key->tmp;
2123
2124
0
#ifndef WOLFSSL_HAVE_SP_ECC
2125
0
    err = eccsi_kpak_to_mont(key);
2126
    /* Need KPAK in montgomery form. */
2127
0
    if (err == 0) {
2128
0
        err = mp_read_unsigned_bin(hs, key->idHash, key->idHashSz);
2129
0
    }
2130
#else
2131
    err = mp_read_unsigned_bin(hs, key->idHash, key->idHashSz);
2132
#endif
2133
0
    if (err == 0)
2134
0
    {
2135
        /* [HS]PVT + KPAK */
2136
0
        ecc_point* kpak = &key->ecc.pubkey;
2137
0
        err = eccsi_mulmod_point_add(key, hs, pvt, kpak, y, mp, 1);
2138
0
    }
2139
2140
0
    return err;
2141
0
}
2142
2143
/*
2144
 * Calculate J point as part of verification process.
2145
 *
2146
 * J = [s]( [HE]G + [r]Y )
2147
 *
2148
 * @param  [in]   key    ECCSI key.
2149
 * @param  [in]   hem    MP int representation of HE = Hash (hs, r and message).
2150
 * @param  [in]   sig    Signature of message.
2151
 * @param  [in]   sigSz  Length of signature in bytes.
2152
 * @param  [in]   y      ECC point representing [r]Y.
2153
 * @param  [in]   mp     Montgomery reduction multiplier.
2154
 * @param  [out]  j      ECC point representing calculated value J.
2155
 * @return  0 on success.
2156
 * @return  MEMORY_E when dynamic memory allocation fails.
2157
 * @return  Other value when an an internal operation fails.
2158
 */
2159
static int eccsi_calc_j(EccsiKey* key, const mp_int* hem, const byte* sig,
2160
        word32 sigSz, ecc_point* y, mp_digit mp, ecc_point* j)
2161
0
{
2162
0
    int err;
2163
0
    mp_int* s = &key->tmp;
2164
2165
    /* [HE]G + [r]Y */
2166
0
    err = eccsi_mulmod_base_add(key, hem, y, j, mp, 1);
2167
0
    if (err == 0) {
2168
0
        err = eccsi_decode_sig_s(key, sig, sigSz, s);
2169
0
    }
2170
    /* Validate s is in [1, q-1]: reject zero or out-of-range second signature
2171
     * component.  With s=0, [s](...) yields the point at infinity whose
2172
     * affine x-coordinate is 0, making the final mp_cmp(0,0) accept any
2173
     * forged signature. */
2174
0
    if (err == 0) {
2175
0
        if (mp_iszero(s)) {
2176
0
            err = MP_ZERO_E;
2177
0
        }
2178
0
        else if (mp_cmp(s, &key->params.order) != MP_LT) {
2179
0
            err = ECC_OUT_OF_RANGE_E;
2180
0
        }
2181
0
    }
2182
    /* [s]( [HE]G + [r]Y ) */
2183
0
    if (err == 0) {
2184
0
        err = eccsi_mulmod_point(key, s, j, j, 1);
2185
0
    }
2186
2187
0
    return err;
2188
0
}
2189
2190
/**
2191
 * Verify the ECCSI hash (of ID with the key).
2192
 *
2193
 * RFC 6507, Section 5.2.2
2194
 *
2195
 * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n
2196
 * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set
2197
 * the identity hash to use.
2198
 *
2199
 * @param  [in]   key       ECCSI key.
2200
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
2201
 * @param  [in]   msg       Message to verify.
2202
 * @param  [in]   msgSz     Length of message in bytes.
2203
 * @param  [in]   sig       Signature of message.
2204
 * @param  [in]   sigSz     Length of signature in bytes.
2205
 * @param  [out]  verified  1 when the signature was verified and 0 otherwise.
2206
 * @return  0 on success.
2207
 * @return  BAD_FUNC_ARG when key, hash, msg, sig or ret is NULL.
2208
 * @return  BAD_STATE_E when the curve or id hash has not been set (no key set).
2209
 * @return  MEMORY_E when dynamic memory allocation fails.
2210
 * @return  Other value when an an internal operation fails.
2211
 */
2212
int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType,
2213
        const byte* msg, word32 msgSz, const byte* sig, word32 sigSz,
2214
        int* verified)
2215
0
{
2216
0
    int err = 0;
2217
0
    byte* he = NULL;
2218
0
    word32 heSz = 0;
2219
0
    mp_int* r = NULL;
2220
0
    mp_int* jx = NULL;
2221
0
    mp_int* hem = NULL;
2222
0
    ecc_point* pvt = NULL;
2223
0
    ecc_point* y = NULL;
2224
0
    ecc_point* j = NULL;
2225
0
    mp_digit mp = 0;
2226
0
    EccsiKeyParams* params = NULL;
2227
2228
0
    if ((key == NULL) || (msg == NULL) || (sig == NULL) || (verified == NULL)) {
2229
0
        err = BAD_FUNC_ARG;
2230
0
    }
2231
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
2232
0
            (key->ecc.type != ECC_PUBLICKEY)) {
2233
0
        err = BAD_STATE_E;
2234
0
    }
2235
0
    if ((err == 0) && (key->idHashSz == 0)) {
2236
0
        err = BAD_STATE_E;
2237
0
    }
2238
2239
0
    if (err != 0)
2240
0
        return err;
2241
2242
    /* Decode the signature into components. */
2243
0
    r = wc_ecc_key_get_priv(&key->pubkey);
2244
0
    pvt = &key->pubkey.pubkey;
2245
0
    err = eccsi_decode_sig_r_pvt(key, sig, sigSz, r, pvt);
2246
2247
    /* Load the curve parameters for operations */
2248
0
    if (err == 0) {
2249
0
        err = eccsi_load_base(key);
2250
0
    }
2251
0
    if (err == 0) {
2252
0
        err = eccsi_load_ecc_params(key);
2253
0
    }
2254
0
    if (err == 0) {
2255
0
        params = &key->params;
2256
0
        err = mp_montgomery_setup(&params->prime, &mp);
2257
0
    }
2258
2259
    /* Validate r is in [1, q-1]: reject zero or out-of-range first signature
2260
     * component before any scalar multiplication takes place.
2261
     * Without this check, r=0 causes J_x=0 and the final mp_cmp(0,0)==MP_EQ
2262
     * comparison accepts the forged signature unconditionally. */
2263
0
    if (err == 0) {
2264
0
        if (mp_iszero(r)) {
2265
0
            err = MP_ZERO_E;
2266
0
        }
2267
0
        else if (mp_cmp(r, &params->order) != MP_LT) {
2268
0
            err = ECC_OUT_OF_RANGE_E;
2269
0
        }
2270
0
    }
2271
2272
    /* Step 1: Validate PVT is on curve */
2273
0
    if (err == 0) {
2274
0
        err = wc_ecc_is_point(pvt, &params->a, &params->b, &params->prime);
2275
0
    }
2276
2277
    /* Step 2: Compute HS = hash( G | KPAK | ID | PVT )
2278
     * HS is key->idHash, key->idHashSz */
2279
2280
    /* Step 3: Compute HE = hash( HS | r | M ) */
2281
0
    if (err == 0) {
2282
0
        he = key->data;
2283
0
        err = eccsi_compute_he(key, hashType, r, msg, msgSz, he, &heSz);
2284
0
    }
2285
2286
    /* Step 4: Y = [HS]PVT + KPAK */
2287
0
    if (err == 0) {
2288
0
        y = pvt;
2289
0
        err = eccsi_calc_y(key, pvt, mp, y);
2290
0
    }
2291
2292
    /* Step 5: Compute J = [s]( [HE]G + [r]Y ) */
2293
    /* [r]Y */
2294
0
    if (err == 0) {
2295
0
        hem = &key->tmp;
2296
0
        err = mp_read_unsigned_bin(hem, he, heSz);
2297
0
    }
2298
0
    if (err == 0) {
2299
0
        err = eccsi_mulmod_point(key, r, y, y, 0);
2300
0
    }
2301
0
    if (err == 0) {
2302
0
        j = params->base;
2303
0
        err = eccsi_calc_j(key, hem, sig, sigSz, y, mp, j);
2304
0
        key->params.haveBase = 0;
2305
0
    }
2306
2307
    /* Defense-in-depth: reject J = point at infinity before the final
2308
     * comparison. Catches any future path that might reach this point
2309
     * with a neutral-element result (e.g. s = 0 mod q for a non-zero
2310
     * encoded s). */
2311
0
    if (err == 0) {
2312
0
        if (wc_ecc_point_is_at_infinity(j)) {
2313
0
            err = ECC_INF_E;
2314
0
        }
2315
0
    }
2316
2317
    /* Step 6: Jx fitting, compare with r */
2318
0
    if (err == 0) {
2319
0
        jx = &key->tmp;
2320
0
        err = eccsi_fit_to_octets(j->x, &params->order, key->ecc.dp->size, jx);
2321
0
    }
2322
2323
0
    if (verified != NULL) {
2324
0
        *verified = ((err == 0) && (mp_cmp(jx, r) == MP_EQ));
2325
0
    }
2326
2327
0
    return err;
2328
0
}
2329
#endif /* WOLFCRYPT_ECCSI_CLIENT */
2330
2331
#endif /* WOLFCRYPT_HAVE_ECCSI */
2332