Coverage Report

Created: 2026-08-15 06:21

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