Coverage Report

Created: 2026-04-05 07:22

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
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && !defined(WOLFSSL_SP_ASM)
40
    /* force off unneeded vector register save/restore. */
41
    #undef SAVE_VECTOR_REGISTERS
42
    #define SAVE_VECTOR_REGISTERS(fail_clause) SAVE_NO_VECTOR_REGISTERS(fail_clause)
43
    #undef RESTORE_VECTOR_REGISTERS
44
    #define RESTORE_VECTOR_REGISTERS() RESTORE_NO_VECTOR_REGISTERS()
45
#endif
46
47
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
48
    /* FIPS build has replaced ecc.h. */
49
    #define wc_ecc_key_get_priv(key) (&((key)->k))
50
    #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
51
#endif
52
53
/**
54
 * Initialize the components of the ECCSI key and use the specified curve.
55
 *
56
 * Must be called before performing any operations.
57
 * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed.
58
 *
59
 * @param  [in]  key    ECCSI key to initialize.
60
 * @param  [in]  heap   Heap hint.
61
 * @param  [in]  devId  Device identifier.
62
 *                      Use INVALID_DEVID when no device used.
63
 * @return  0 on success.
64
 * @return  BAD_FUNC_ARG when key is NULL.
65
 * @return  MEMORY_E when dynamic memory allocation fails.
66
 */
67
int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap,
68
        int devId)
69
135
{
70
135
    int err = 0;
71
135
    EccsiKeyParams* params = NULL;
72
73
135
    if (key == NULL) {
74
0
        err = BAD_FUNC_ARG;
75
0
    }
76
77
135
    if (err == 0) {
78
135
        XMEMSET(key, 0, sizeof(*key));
79
135
        key->heap = heap;
80
135
        params = &key->params;
81
82
135
        err = wc_ecc_init_ex(&key->ecc, heap, devId);
83
135
    }
84
135
    if (err == 0) {
85
135
        err = wc_ecc_init_ex(&key->pubkey, heap, devId);
86
135
    }
87
135
    if (err == 0) {
88
135
        key->pvt = wc_ecc_new_point_h(heap);
89
135
        if (key->pvt == NULL) {
90
4
            err = MEMORY_E;
91
4
        }
92
135
    }
93
135
    if (err == 0) {
94
131
        err = mp_init_multi(&params->order,
95
131
#ifdef WOLFCRYPT_ECCSI_CLIENT
96
131
                &params->a, &params->b, &params->prime, &key->tmp, &key->ssk
97
#else
98
                NULL, NULL, NULL, NULL, NULL
99
#endif
100
131
                );
101
131
    }
102
135
    if (err == 0) {
103
131
        err = wc_ecc_set_curve(&key->ecc, keySz, curveId);
104
131
    }
105
135
    if (err == 0) {
106
131
        err = wc_ecc_set_curve(&key->pubkey, keySz, curveId);
107
131
    }
108
109
135
    if (err != 0) {
110
4
        wc_FreeEccsiKey(key);
111
4
    }
112
113
135
    return err;
114
135
}
115
116
/**
117
 * Initialize the components of the ECCSI key.
118
 * Default curve used: NIST_P256 (ECC_SECP256R1)
119
 *
120
 * Must be called before performing any operations.
121
 * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed.
122
 *
123
 * @param  [in]  key    ECCSI key to initialize.
124
 * @param  [in]  heap   Heap hint.
125
 * @param  [in]  devId  Device identifier.
126
 *                      Use INVALID_DEVID when no device used.
127
 * @return  0 on success.
128
 * @return  BAD_FUNC_ARG when key is NULL.
129
 * @return  MEMORY_E when dynamic memory allocation fails.
130
 */
131
int wc_InitEccsiKey(EccsiKey* key, void* heap, int devId)
132
0
{
133
0
    return wc_InitEccsiKey_ex(key, 32, ECC_SECP256R1, heap, devId);
134
0
}
135
136
/**
137
 * Frees memory associated with components of the ECCIS key.
138
 *
139
 * Must be called when finished with the ECCIS key.
140
 *
141
 * @param  [in]  key  ECCIS key.
142
 */
143
void wc_FreeEccsiKey(EccsiKey* key)
144
135
{
145
135
    if (key != NULL) {
146
135
        EccsiKeyParams* params = &key->params;
147
148
135
        wc_ecc_del_point_h(params->base, key->heap);
149
135
#ifdef WOLFCRYPT_ECCSI_CLIENT
150
135
        mp_free(&key->ssk);
151
135
        mp_free(&key->tmp);
152
135
        mp_free(&params->prime);
153
135
        mp_free(&params->b);
154
135
        mp_free(&params->a);
155
135
#endif
156
135
        mp_free(&params->order);
157
135
        wc_ecc_del_point_h(key->pvt, key->heap);
158
135
        wc_ecc_free(&key->pubkey);
159
135
        wc_ecc_free(&key->ecc);
160
135
        XMEMSET(key, 0, sizeof(*key));
161
135
    }
162
135
}
163
164
/*
165
 * Order, as a hex string in the ECC object, loaded into mp_int in key.
166
 * Flags that the order is available so it isn't loaded multiple times.
167
 *
168
 * @param  [in]  key  ECCSI key.
169
 * @return  0 on success.
170
 * @return  MEMORY_E when dynamic memory allocation fails.
171
 */
172
static int eccsi_load_order(EccsiKey* key)
173
0
{
174
0
    int err = 0;
175
176
0
    if (!key->params.haveOrder) {
177
0
        err = mp_read_radix(&key->params.order, key->ecc.dp->order,
178
0
                MP_RADIX_HEX);
179
0
        if (err == 0) {
180
0
            key->params.haveOrder = 1;
181
0
        }
182
0
    }
183
184
0
    return err;
185
0
}
186
187
#ifdef WOLFCRYPT_ECCSI_CLIENT
188
/*
189
 * Parameters, as a hex strings in the ECC object, loaded into mp_ints in key.
190
 *
191
 * Parameters loaded: order, A, B, prime.
192
 * Flags that each parameter is available so they aren't loaded multiple times.
193
 *
194
 * @param  [in]  key  ECCSI key.
195
 * @return  0 on success.
196
 * @return  MEMORY_E when dynamic memory allocation fails.
197
 */
198
static int eccsi_load_ecc_params(EccsiKey* key)
199
0
{
200
0
    int err = 0;
201
0
    EccsiKeyParams* params = &key->params;
202
203
0
    err = eccsi_load_order(key);
204
0
    if ((err == 0) && (!params->haveA)) {
205
0
        err = mp_read_radix(&params->a, key->ecc.dp->Af, MP_RADIX_HEX);
206
0
        if (err == 0) {
207
0
            params->haveA = 1;
208
0
        }
209
0
    }
210
0
    if ((err == 0) && (!params->haveB)) {
211
0
        err = mp_read_radix(&params->b, key->ecc.dp->Bf, MP_RADIX_HEX);
212
0
        if (err == 0) {
213
0
            params->haveB = 1;
214
0
        }
215
0
    }
216
0
    if ((err == 0) && (!params->havePrime)) {
217
0
        err = mp_read_radix(&params->prime, key->ecc.dp->prime, MP_RADIX_HEX);
218
0
        if (err == 0) {
219
0
            params->havePrime = 1;
220
0
        }
221
0
    }
222
223
0
    return err;
224
0
}
225
#endif /* WOLFCRYPT_ECCSI_CLIENT */
226
227
/*
228
 * Get the base point, hex encoded in the ECC object, as an ecc_point.
229
 *
230
 * Flags that base is available so it isn't loaded multiple times.
231
232
 * @param  [in]   key   ECCSI key.
233
 * @param  [out]  base  Base point of curve.
234
 * @return  0 on success.
235
 * @return  MEMORY_E when dynamic memory allocation fails.
236
 */
237
static int eccsi_load_base(EccsiKey* key)
238
0
{
239
0
    int err = 0;
240
0
    EccsiKeyParams* params = &key->params;
241
242
0
    if (!params->haveBase) {
243
0
        if (params->base == NULL) {
244
0
            params->base = wc_ecc_new_point_h(key->heap);
245
0
            if (params->base == NULL) {
246
0
                err = MEMORY_E;
247
0
            }
248
0
        }
249
0
        if (err == 0) {
250
0
            err = mp_read_radix(params->base->x, key->ecc.dp->Gx, MP_RADIX_HEX);
251
0
        }
252
0
        if (err == 0) {
253
0
            err = mp_read_radix(params->base->y, key->ecc.dp->Gy, MP_RADIX_HEX);
254
0
        }
255
0
        if (err == 0) {
256
0
            err = mp_set(params->base->z, 1);
257
0
        }
258
0
        if (err == 0) {
259
0
            params->haveBase = 1;
260
0
        }
261
0
    }
262
263
0
    return err;
264
0
}
265
266
/*
267
 * Encode the base point of the curve.
268
 *
269
 * Base point is hex encoded in the ECC object or cached as an ECC point from
270
 * previous load calls.
271
 *
272
 * @param  [in]   key     ECCSI key.
273
 * @param  [out]  data    Buffer to encode base point into.
274
 * @param  [out]  dataSz  Length of base point in bytes.
275
 * @return  0 on success.
276
 * @return  MEMORY_E when dynamic memory allocation fails.
277
 * @return  Other -ve value when an internal operation fails.
278
 */
279
static int eccsi_encode_base(EccsiKey* key, byte* data, word32* dataSz)
280
0
{
281
0
    int err;
282
0
    int idx = wc_ecc_get_curve_idx(key->ecc.dp->id);
283
284
0
    err = eccsi_load_base(key);
285
0
    if (err == 0) {
286
0
        err = wc_ecc_export_point_der(idx, key->params.base, data, dataSz);
287
0
    }
288
289
0
    return err;
290
0
}
291
292
#ifndef WOLFSSL_HAVE_SP_ECC
293
/*
294
 * Convert the KPAK to montgomery form.
295
 *
296
 * The KPAK is needed in Montgomery form for verification.
297
 *
298
 * @param  [in]  key      ECCSI key.
299
 * @return  0 on success.
300
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
301
 * @return  Other -ve value when an internal operation fails.
302
 */
303
static int eccsi_kpak_to_mont(EccsiKey* key)
304
0
{
305
0
    int err = 0;
306
0
    ecc_point* kpak = &key->ecc.pubkey;
307
0
    mp_int* mu = &key->tmp;
308
0
    mp_int* prime = &key->params.prime;
309
310
0
    if (!key->kpakMont) {
311
0
        err = mp_montgomery_calc_normalization(mu, prime);
312
0
        if (err == 0) {
313
0
            err = mp_mulmod(kpak->x, mu, prime, kpak->x);
314
0
        }
315
0
        if (err == 0) {
316
0
            err = mp_mulmod(kpak->y, mu, prime, kpak->y);
317
0
        }
318
0
        if (err == 0) {
319
0
            err = mp_mulmod(kpak->z, mu, prime, kpak->z);
320
0
        }
321
0
        if (err == 0) {
322
0
            key->kpakMont = 1;
323
0
        }
324
0
    }
325
326
0
    return err;
327
0
}
328
#endif
329
330
/*
331
 * Convert the KPAK from montgomery form.
332
 *
333
 * The KPAK is needed in Montgomery form for verification.
334
 *
335
 * @param  [in]  key      ECCSI key.
336
 * @return  0 on success.
337
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
338
 * @return  Other -ve value when an internal operation fails.
339
 */
340
static int eccsi_kpak_from_mont(EccsiKey* key)
341
0
{
342
0
    int err = 0;
343
0
    ecc_point* kpak = &key->ecc.pubkey;
344
0
    mp_digit mp;
345
0
    mp_int* prime = &key->params.prime;
346
347
0
    if (key->kpakMont) {
348
0
        err = mp_montgomery_setup(prime, &mp);
349
0
        if (err == 0) {
350
0
            err = mp_montgomery_reduce(kpak->x, prime, mp);
351
0
        }
352
0
        if (err == 0) {
353
0
            err = mp_montgomery_reduce(kpak->y, prime, mp);
354
0
        }
355
0
        if (err == 0) {
356
0
            err = mp_montgomery_reduce(kpak->z, prime, mp);
357
0
        }
358
0
        if (err == 0) {
359
0
            key->kpakMont = 0;
360
0
        }
361
0
    }
362
363
0
    return err;
364
0
}
365
366
/*
367
 * Compute HS = hash( G | KPAK | ID | PVT )
368
 *
369
 * Use when making a (SSK,PVT) pair, signing and verifying.
370
 *
371
 * @param  [in]   key       ECCSI key.
372
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
373
 * @param  [in]   id        Identity to create hash from.
374
 * @param  [in]   idSz      Length of identity in bytes.
375
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
376
 * @param  [out]  hash      Buffer to hold hash data.
377
 * @param  [out]  hashSz    Length of hash data in bytes.
378
 * @return  0 on success.
379
 * @return  MEMORY_E when dynamic memory allocation fails.
380
 * @return  Other -ve value when an internal operation fails.
381
 */
382
static int eccsi_compute_hs(EccsiKey* key, enum wc_HashType hashType,
383
        const byte* id, word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz)
384
0
{
385
0
    int err;
386
0
    word32 dataSz = 0;
387
0
    int idx = wc_ecc_get_curve_idx(key->ecc.dp->id);
388
0
    ecc_point* kpak = &key->ecc.pubkey;
389
0
    int hash_inited = 0;
390
391
    /* HS = hash( G | KPAK | ID | PVT ) */
392
0
    err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID);
393
0
    if (err == 0) {
394
0
        hash_inited = 1;
395
        /* Base Point - G */
396
0
        dataSz = sizeof(key->data);
397
0
        err = eccsi_encode_base(key, key->data, &dataSz);
398
0
    }
399
0
    if (err == 0) {
400
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
401
0
    }
402
0
    if (err == 0) {
403
0
        err = eccsi_kpak_from_mont(key);
404
0
    }
405
0
    if (err == 0) {
406
0
        dataSz = sizeof(key->data);
407
        /* KPAK - public key */
408
0
        err = wc_ecc_export_point_der(idx, kpak, key->data, &dataSz);
409
0
    }
410
0
    if (err == 0) {
411
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
412
0
    }
413
0
    if (err == 0) {
414
        /* Id - Signer's ID */
415
0
        err = wc_HashUpdate(&key->hash, hashType, id, idSz);
416
0
    }
417
0
    if (err == 0) {
418
0
        dataSz = sizeof(key->data);
419
        /* PVT - Public Validation Token */
420
0
        err = wc_ecc_export_point_der(idx, pvt, key->data, &dataSz);
421
0
    }
422
0
    if (err == 0) {
423
        /* PVT - Public Validation Token */
424
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
425
0
    }
426
0
    if (err == 0) {
427
0
        err = wc_HashFinal(&key->hash, hashType, hash);
428
0
    }
429
430
0
    if (err == 0) {
431
0
        *hashSz = (byte)wc_HashGetDigestSize(hashType);
432
0
    }
433
434
0
    if (hash_inited) {
435
0
        (void)wc_HashFree(&key->hash, hashType);
436
0
    }
437
438
0
    return err;
439
0
}
440
441
#ifdef WOLFCRYPT_ECCSI_KMS
442
/**
443
 * Generate KMS Secret Auth Key (KSAK) and KMS Public Auth Key (KPAK).
444
 *
445
 * RFC 6507, Section 4.2
446
 *
447
 * Called when establishing a new KMS.\n
448
 * KSAK must be kept secret while KPAK is required by clients for signing
449
 * and verifying.\n
450
 * Export key using wc_ExportEccsiKey(), once generated, to reuse the key.\n
451
 * Export KPAK using wc_ExportEccsiPublicKey(), once generate to send to
452
 * clients.
453
 *
454
 * Creates a random private key and multiplies it by the base point to calculate
455
 * the public key.
456
 *
457
 * @param  [in]  key      ECCSI key.
458
 * @param  [in]  rng      Random number generator.
459
 * @return  0 on success.
460
 * @return  BAD_FUNC_ARG when key or rng is NULL.
461
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
462
 * @return  Other -ve value when an internal operation fails.
463
 */
464
int wc_MakeEccsiKey(EccsiKey* key, WC_RNG* rng)
465
0
{
466
0
    int err = 0;
467
468
0
    if ((key == NULL) || (rng == NULL)) {
469
0
        err = BAD_FUNC_ARG;
470
0
    }
471
472
0
    if (err == 0) {
473
0
        err = wc_ecc_make_key_ex(rng, key->ecc.dp->size, &key->ecc,
474
0
                key->ecc.dp->id);
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
131
{
553
131
    int err = 0;
554
555
131
    if ((sz != size * 2) && (sz != size * 2 + 1)) {
556
0
        err = BUFFER_E;
557
0
    }
558
559
131
    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
131
    if (err == 0) {
567
        /* Read the public key point's x value from key size bytes. */
568
131
        err = mp_read_unsigned_bin(point->x, data, size);
569
131
    }
570
131
    if (err == 0) {
571
131
        data += size;
572
        /* Read the public key point's y value from key size bytes. */
573
131
        err = mp_read_unsigned_bin(point->y, data, size);
574
131
    }
575
131
    if (err == 0) {
576
131
        err = mp_set(point->z, 1);
577
131
    }
578
579
131
    return err;
580
131
}
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
131
{
679
131
    int err;
680
681
    /* Read the secret value from key size bytes. */
682
131
    err = mp_read_unsigned_bin(wc_ecc_key_get_priv(&key->ecc), data,
683
131
        (word32)key->ecc.dp->size);
684
131
    if (err == 0) {
685
131
        data += key->ecc.dp->size;
686
        /* Read public key. */
687
131
        err = eccsi_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size,
688
131
                data, (word32)(key->ecc.dp->size * 2));
689
131
    }
690
691
131
    return err;
692
131
}
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
131
{
712
131
    int err = 0;
713
714
131
    if ((key == NULL) || (data == NULL)) {
715
0
        err = BAD_FUNC_ARG;
716
0
    }
717
131
    if ((err == 0) && (sz != (word32)key->ecc.dp->size * 3)) {
718
0
        err = BUFFER_E;
719
0
    }
720
721
131
    if (err == 0) {
722
131
        key->kpakMont = 0;
723
724
        /* Decode key */
725
131
        err = eccsi_decode_key(key, data);
726
131
    }
727
131
    if (err == 0) {
728
131
        key->ecc.type = ECC_PRIVATEKEY;
729
131
    }
730
731
131
    return err;
732
131
}
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
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
1511
1512
0
    params = &key->params;
1513
0
    hs = &key->tmp;
1514
0
    res = &key->pubkey.pubkey;
1515
1516
0
    err = eccsi_load_base(key);
1517
1518
0
    if (err == 0) {
1519
0
       err = eccsi_load_ecc_params(key);
1520
0
    }
1521
0
    if (err == 0) {
1522
0
        err = mp_montgomery_setup(&params->prime, &mp);
1523
0
    }
1524
1525
    /* Step 1: Validate PVT is on curve */
1526
0
    if (err == 0) {
1527
0
        err = wc_ecc_is_point(pvt, &params->a, &params->b, &params->prime);
1528
0
        if (err == -1) {
1529
0
            err = IS_POINT_E;
1530
0
        }
1531
0
    }
1532
1533
    /* Step 2: Compute HS = hash( G | KPAK | ID | PVT ) */
1534
0
    if (err == 0) {
1535
0
        hashSz = (byte)sizeof(key->data);
1536
        /* Converts KPAK from mont. */
1537
0
        err = eccsi_compute_hs(key, hashType, id, idSz, pvt, key->data,
1538
0
                &hashSz);
1539
0
    }
1540
1541
    /* Step 3: Validate that KPAK = [SSK]G - [HS]PVT */
1542
0
    if (err == 0) {
1543
0
        err = mp_read_unsigned_bin(hs, key->data, hashSz);
1544
0
    }
1545
    /* [HS]PVT */
1546
0
    if (err == 0) {
1547
0
        err = eccsi_mulmod_point(key, hs, pvt, res, 0);
1548
0
    }
1549
    /* -[HS]PVT */
1550
0
    if (err == 0) {
1551
0
        err = mp_sub(&params->prime, res->y, res->y);
1552
0
    }
1553
    /* [SSK]G + -[HS]PVT */
1554
0
    if (err == 0) {
1555
0
        err = eccsi_mulmod_base_add(key, ssk, res, res, mp, 1);
1556
0
    }
1557
0
    if (valid != NULL) {
1558
0
        *valid = (err == 0);
1559
0
        if (err == 0) {
1560
0
            ecc_point* kpak = &key->ecc.pubkey;
1561
            /* Compare KPAK and [SSK]G + -[HS]PVT */
1562
0
            *valid = (wc_ecc_cmp_point(res, kpak) == MP_EQ);
1563
0
        }
1564
0
    }
1565
1566
0
    RESTORE_VECTOR_REGISTERS();
1567
1568
0
    return err;
1569
0
}
1570
1571
/**
1572
 * Validate Public Validation Token (PVT) is on the curve.
1573
 *
1574
 * RFC 6507, Section 5.1.2, Step 1
1575
 *
1576
 * A verifying client should validate the PVT before first use.
1577
 *
1578
 * @param  [in]   key       ECCSI key.
1579
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
1580
 * @param  [out]  valid     1 when PVT is valid and 0 otherwise.
1581
 * @return  0 on success.
1582
 * @return  BAD_FUNC_ARG when key, pvt or valid is NULL.
1583
 * @return  BAD_STATE_E when curve not set (key not set).
1584
 * @return  MP_MEM or MEMORY_E when dynamic memory allocation fails.
1585
 * @return  Other -ve value when an internal operation fails.
1586
 */
1587
int wc_ValidateEccsiPvt(EccsiKey* key, const ecc_point* pvt, int* valid)
1588
0
{
1589
0
    int err = 0;
1590
1591
0
    if ((key == NULL)| (pvt == NULL) || (valid == NULL)) {
1592
0
        err = BAD_FUNC_ARG;
1593
0
    }
1594
1595
0
    if (err == 0) {
1596
0
        err = wc_ecc_set_curve(&key->pubkey, key->ecc.dp->size,
1597
0
                key->ecc.dp->id);
1598
0
    }
1599
0
    if (err == 0) {
1600
0
        err = wc_ecc_copy_point(pvt, &key->pubkey.pubkey);
1601
0
    }
1602
0
    if (err == 0) {
1603
0
        *valid = (wc_ecc_check_key(&key->pubkey) == 0);
1604
0
    }
1605
1606
0
    return err;
1607
0
}
1608
1609
/**
1610
 * Creates the Hash of the ID and PVT with the ECCSI key.
1611
 *
1612
 * The hash ID is required as input to the sign and verify operations.\n
1613
 * Signing clients may cache this value.
1614
 *
1615
 * RFC 6507, Section 5.2.1, Step 3
1616
 *
1617
 * Set the calculated hash internally for use.
1618
 *
1619
 * @param  [in]   key       ECCSI key.
1620
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1621
 * @param  [in]   id        Identity to create hash from.
1622
 * @param  [in]   idSz      Length of identity in bytes.
1623
 * @param  [in]   pvt       Public Validation Token (PVT) as an ECC point.
1624
 * @param  [out]  hash      Buffer to hold hash result.
1625
 * @param  [out]  hashSz    Length of hash data in bytes.
1626
 * @return  0 on success.
1627
 * @return  BAD_FUNC_ARG when key, id, pvt, hash or hashSz is NULL.
1628
 * @return  BAD_FUNC_ARG when hash size doesn't match curve size.
1629
 * @return  BAD_STATE_E when public key not set.
1630
 * @return  MEMORY_E when dynamic memory allocation fails.
1631
 * @return  Other -ve value when an internal operation fails.
1632
 */
1633
int wc_HashEccsiId(EccsiKey* key, enum wc_HashType hashType, const byte* id,
1634
        word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz)
1635
0
{
1636
0
    int err = 0;
1637
0
    int dgstSz = -1;
1638
0
    int curveSz = -1;
1639
1640
0
    if ((key == NULL) || (id == NULL) || (pvt == NULL) || (hash == NULL) ||
1641
0
            (hashSz == NULL)) {
1642
0
        err = BAD_FUNC_ARG;
1643
0
    }
1644
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
1645
0
            (key->ecc.type != ECC_PUBLICKEY)) {
1646
0
        err = BAD_STATE_E;
1647
0
    }
1648
    /* Ensure digest output size matches curve size (RFC 6507 4.1). */
1649
0
    if (err == 0) {
1650
0
        dgstSz = wc_HashGetDigestSize(hashType);
1651
0
        if (dgstSz < 0) {
1652
0
            err = dgstSz;
1653
0
        }
1654
0
    }
1655
0
    if (err == 0) {
1656
0
        curveSz = wc_ecc_get_curve_size_from_id(key->ecc.dp->id);
1657
0
        if (curveSz < 0) {
1658
0
            err = curveSz;
1659
0
        }
1660
0
    }
1661
0
    if ((err == 0) && (dgstSz != curveSz)) {
1662
0
        err = BAD_FUNC_ARG;
1663
0
    }
1664
    /* Load the curve parameters for operations */
1665
0
    if (err == 0) {
1666
0
       err = eccsi_load_ecc_params(key);
1667
0
    }
1668
0
    if (err == 0) {
1669
0
        err = eccsi_compute_hs(key, hashType, id, idSz, pvt, hash, hashSz);
1670
0
    }
1671
0
    if (err == 0) {
1672
0
        XMEMCPY(key->idHash, hash, *hashSz);
1673
0
        key->idHashSz = *hashSz;
1674
0
    }
1675
1676
0
    return err;
1677
0
}
1678
1679
/**
1680
 * Set the identity hash for use with signing/verification.
1681
 *
1682
 * @param  [in]  key     ECCSI key.
1683
 * @param  [in]  hash    Buffer with hash of identity.
1684
 * @param  [in]  hashSz  Length of hash data in bytes.
1685
 * @return  0 on success.
1686
 * @return  BAD_FUNC_ARG when key or hash is NULL, or hashSz is greater than
1687
 *          WC_MAX_DIGEST_SIZE.
1688
 */
1689
int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz)
1690
0
{
1691
0
    int err = 0;
1692
1693
0
    if ((key == NULL) || (hash == NULL) || (hashSz > WC_MAX_DIGEST_SIZE)) {
1694
0
        err = BAD_FUNC_ARG;
1695
0
    }
1696
0
    if (err == 0) {
1697
0
        XMEMCPY(key->idHash, hash, hashSz);
1698
0
        key->idHashSz = hashSz;
1699
0
    }
1700
1701
0
    return err;
1702
0
}
1703
1704
/**
1705
 * Set an (SSV, PVT) Pair for signing.
1706
 *
1707
 * @param  [in]   key  ECCSI key.
1708
 * @param  [in]   ssk  Secret Signing Key as an MP integer.
1709
 * @param  [in]   pvt  Public Validation Token (PVT) as an ECC point.
1710
 * @return  0 on success.
1711
 * @return  BAD_FUNC_ARG when key, ssk or pvt is NULL.
1712
 * @return  MP math errors when copy fails
1713
 */
1714
int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, const ecc_point* pvt)
1715
0
{
1716
0
    int err = 0;
1717
1718
0
    if ((key == NULL) || (ssk == NULL) || (pvt == NULL)) {
1719
0
        err = BAD_FUNC_ARG;
1720
0
    }
1721
1722
0
    if (err == 0) {
1723
0
        err = mp_copy(ssk, &key->ssk);
1724
0
    }
1725
1726
0
    if (err == 0) {
1727
0
        err = wc_ecc_copy_point(pvt, key->pvt);
1728
0
    }
1729
1730
0
    return err;
1731
0
}
1732
1733
#ifdef ECCSI_ORDER_MORE_BITS_THAN_PRIME
1734
/*
1735
 * Fit the number to the maximum number of bytes.
1736
 *
1737
 * If the number is too big then subtract from order.
1738
 * RFC 6507, Section 5.2.1, Note at end.
1739
 * This should only happen when order is larger than prime in bits.
1740
 *
1741
 * @param  [in]   a      MP integer to fix.
1742
 * @param  [in]   order  MP integer representing order of curve.
1743
 * @param  [in]   m      Maximum number of bytes to encode into.
1744
 * @param  [out]  r      MP integer that is the result after fixing.
1745
 * @return  0 on success.
1746
 * @return  MEMORY_E when dynamic memory allocation fails.
1747
 */
1748
static int eccsi_fit_to_octets(const mp_int* a, mp_int* order, int m,
1749
        mp_int* r)
1750
{
1751
    int err;
1752
1753
    if (mp_count_bits(a) > m * 8) {
1754
        err = mp_sub(order, (mp_int*)a, r);
1755
    }
1756
    else
1757
    {
1758
        err = mp_copy(a, r);
1759
    }
1760
1761
    return err;
1762
}
1763
#else
1764
/*
1765
 * Fit the number to the maximum number of bytes.
1766
 *
1767
 * If the number is too big then subtract from order.
1768
 * RFC 6507, Section 5.2.1, Note at end.
1769
 * This should only happen when order is larger than prime in bits.
1770
 *
1771
 * @param  [in]   a      MP integer to fix.
1772
 * @param  [in]   order  MP integer representing order of curve.
1773
 * @param  [in]   m      Maximum number of bytes to encode into.
1774
 * @param  [out]  r      MP integer that is the result after fixing.
1775
 * @return  0 on success.
1776
 * @return  MEMORY_E when dynamic memory allocation fails.
1777
 */
1778
static int eccsi_fit_to_octets(const mp_int* a, const mp_int* order, int m,
1779
        mp_int* r)
1780
0
{
1781
0
    (void)order;
1782
0
    (void)m;
1783
1784
    /* Duplicate line to stop static analyzer complaining. */
1785
0
    return mp_copy(a, r);
1786
0
}
1787
#endif
1788
1789
/*
1790
 * Compute the HE = hash( HS | r | M ), hash value of signature.
1791
 *
1792
 * Partial result required for signing and verification.
1793
 *
1794
 * @param  [in]   key       ECCSI key.
1795
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1796
 * @param  [in]   r         MP integer that is the first signature element.
1797
 * @param  [in]   msg       Message of signature.
1798
 * @param  [in]   msgSz     Length of message in bytes.
1799
 * @param  [out]  he        Signature hash.
1800
 * @param  [out]  heSz      Length of signature hash in bytes
1801
 * @return  0 on success.
1802
 * @return  MEMORY_E when dynamic memory allocation fails.
1803
 * @return  Other -ve value when an internal operation fails.
1804
 */
1805
static int eccsi_compute_he(EccsiKey* key, enum wc_HashType hashType,
1806
        mp_int* r, const byte* msg, word32 msgSz, byte* he, word32* heSz)
1807
0
{
1808
0
    int err = 0;
1809
0
    word32 dataSz = (word32)key->ecc.dp->size;
1810
0
    int hash_inited = 0;
1811
1812
    /* HE = hash( HS | r | M ) */
1813
0
    err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID);
1814
0
    if (err == 0) {
1815
0
        hash_inited = 1;
1816
        /* HS */
1817
0
        err = wc_HashUpdate(&key->hash, hashType, key->idHash, key->idHashSz);
1818
0
    }
1819
0
    if (err == 0) {
1820
0
        err = mp_to_unsigned_bin_len(r, key->data, (int)dataSz);
1821
0
    }
1822
0
    if (err == 0) {
1823
        /* r */
1824
0
        err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz);
1825
0
    }
1826
0
    if (err == 0) {
1827
        /* M */
1828
0
        err = wc_HashUpdate(&key->hash, hashType, msg, msgSz);
1829
0
    }
1830
0
    if (err == 0) {
1831
0
        err = wc_HashFinal(&key->hash, hashType, he);
1832
0
    }
1833
0
    if (err == 0) {
1834
0
        *heSz = (word32)wc_HashGetDigestSize(hashType);
1835
0
    }
1836
1837
0
    if (hash_inited) {
1838
0
        (void)wc_HashFree(&key->hash, hashType);
1839
0
    }
1840
1841
0
    return err;
1842
0
}
1843
1844
/*
1845
 * Encode the signature = ( r | s | PVT )
1846
 *
1847
 * @param  [in]   key    ECCSI key.
1848
 * @param  [in]   r      MP integer that is the first signature element.
1849
 * @param  [in]   s      MP integer that is the second signature element.
1850
 * @param  [in]   pvt    ECC point representing Public Validation Token.
1851
 * @param  [out]  sig    Signature of message.
1852
 * @param  [out]  sigSz  Length of signature in bytes.
1853
 */
1854
static int eccsi_encode_sig(const EccsiKey* key, mp_int* r, mp_int* s,
1855
        byte* sig, word32* sigSz)
1856
0
{
1857
0
    int err;
1858
0
    word32 sz = (word32)key->ecc.dp->size;
1859
1860
0
    err = mp_to_unsigned_bin_len(r, sig, (int)sz);
1861
0
    if (err == 0) {
1862
0
        err = mp_to_unsigned_bin_len(s, sig + sz, (int)sz);
1863
0
    }
1864
0
    if (err == 0) {
1865
0
        *sigSz = (word32)(key->ecc.dp->size * 2 + 1);
1866
0
        err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(key->ecc.dp->id),
1867
0
                 key->pvt, sig + sz * 2, sigSz);
1868
0
    }
1869
0
    if (err == 0) {
1870
0
        *sigSz = sz * 4 + 1;
1871
0
    }
1872
1873
0
    return err;
1874
0
}
1875
1876
/*
1877
 * Sign the ECCSI hash (of ID with the key) to two mp_int objects: r and s.
1878
 *
1879
 * RFC 6507, Section 5.2.1, Steps 1 to 4
1880
 *
1881
 * @param  [in]   key       ECCSI key.
1882
 * @param  [in]   rng       Random number generator.
1883
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1884
 * @param  [in]   msg       Message to sign.
1885
 * @param  [in]   msgSz     Length of message in bytes.
1886
 * @param  [out]  r         First big number integer part of signature.
1887
 * @param  [out]  s         Second big number integer part of signature.
1888
 * @return  0 on success.
1889
 * @return  MEMORY_E when dynamic memory allocation fails.
1890
 * @return  Other -ve value when an internal operation fails.
1891
 */
1892
static int eccsi_gen_sig(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
1893
        const byte* msg, word32 msgSz, mp_int* r, mp_int* s)
1894
0
{
1895
0
    int err = 0;
1896
0
    int sz = key->ecc.dp->size;
1897
0
    word32 heSz = 0;
1898
0
    const mp_int* jx = NULL;
1899
0
    mp_int* he = &key->tmp;
1900
0
    int genTryCnt = 0;
1901
1902
0
    do {
1903
        /* Don't infinitely gen sigs when random number generator fails. */
1904
0
        if ((++genTryCnt) > ECCSI_MAX_GEN_COUNT) {
1905
0
            err = RNG_FAILURE_E;
1906
0
        }
1907
1908
0
        if (err == 0) {
1909
0
            wc_ecc_free(&key->pubkey);
1910
1911
            /* Step 1 and 2: Generate ephemeral key - j, J = [j]G, r = Jx */
1912
0
            err = wc_ecc_make_key_ex(rng, sz, &key->pubkey, key->ecc.dp->id);
1913
0
        }
1914
0
        if (err == 0) {
1915
0
            jx = key->pubkey.pubkey.x;
1916
0
            err = eccsi_fit_to_octets(jx, &key->params.order, sz, r);
1917
0
        }
1918
1919
        /* Step 3: Compute HE = hash( HS | r | M ) */
1920
0
        if (err == 0) {
1921
0
            err = eccsi_compute_he(key, hashType, r, msg, msgSz, key->data,
1922
0
                    &heSz);
1923
0
        }
1924
1925
        /* Step 4: Verify that HE + r * SSK is non-zero modulo q */
1926
0
        if (err == 0) {
1927
0
            err = mp_read_unsigned_bin(he, key->data, heSz);
1928
0
        }
1929
        /* s' = r * SSK */
1930
0
        if (err == 0) {
1931
0
            err = mp_mulmod(r, &key->ssk, &key->params.order, s);
1932
0
        }
1933
        /* s' = HE + r * SSK */
1934
0
        if (err == 0) {
1935
0
            err = mp_addmod(he, s, &key->params.order, s);
1936
0
        }
1937
0
    }
1938
0
    while ((err == 0) && (mp_iszero(s) || (mp_cmp(s, he) == MP_EQ)));
1939
1940
0
    return err;
1941
0
}
1942
1943
1944
/**
1945
 * Sign the ECCSI hash (of ID with the key).
1946
 *
1947
 * RFC 6507, Section 5.2.1
1948
 *
1949
 * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n
1950
 * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set
1951
 * the identity hash to use.
1952
 *
1953
 * @param  [in]   key       ECCSI key.
1954
 * @param  [in]   rng       Random number generator.
1955
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
1956
 * @param  [in]   msg       Message to sign.
1957
 * @param  [in]   msgSz     Length of message in bytes.
1958
 * @param  [out]  sig       Signature of message.
1959
 * @param  [out]  sigSz     Length of signature in bytes.
1960
 * @return  0 on success.
1961
 * @return  BAD_FUNC_ARG when key, rng, msg or sigSz is NULL.
1962
 * @return  BAD_STATE_E when the curve or id hash has not been set (no key set).
1963
 * @return  LENGTH_ONLY_E when sig is NULL - sigSz is set.
1964
 * @return  MEMORY_E when dynamic memory allocation fails.
1965
 * @return  Other -ve value when an internal operation fails.
1966
 */
1967
int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
1968
        const byte* msg, word32 msgSz, byte* sig, word32* sigSz)
1969
0
{
1970
0
    int err = 0;
1971
0
    mp_int* r = NULL;
1972
0
    mp_int* s = NULL;
1973
0
    mp_int* j = NULL;
1974
0
    word32 sz = 0;
1975
1976
0
    if ((key == NULL) || (rng == NULL) || (msg == NULL) || (sigSz == NULL)) {
1977
0
        err = BAD_FUNC_ARG;
1978
0
    }
1979
0
    if ((err == 0) && (key->ecc.type != ECC_PUBLICKEY) &&
1980
0
            (key->ecc.type != ECC_PRIVATEKEY)) {
1981
0
        err = BAD_STATE_E;
1982
0
    }
1983
0
    if ((err == 0) && (sig != NULL) && (key->idHashSz == 0)) {
1984
0
        err = BAD_STATE_E;
1985
0
    }
1986
1987
0
    if (err == 0)  {
1988
0
        sz = (word32)key->ecc.dp->size;
1989
0
        if (sig == NULL) {
1990
0
            *sigSz = sz * 4 + 1;
1991
0
            err = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
1992
0
        }
1993
0
    }
1994
0
    if ((err == 0) && (*sigSz < sz * 4 + 1)) {
1995
0
        err = BAD_FUNC_ARG;
1996
0
    }
1997
1998
0
    if (err == 0) {
1999
0
        r = key->pubkey.pubkey.y;
2000
0
        s = key->pubkey.pubkey.z;
2001
2002
0
        err = eccsi_load_order(key);
2003
0
    }
2004
2005
0
    if (err == 0) {
2006
        /* Steps 1 to 4. */
2007
0
        err = eccsi_gen_sig(key, rng, hashType, msg, msgSz, r, s);
2008
0
    }
2009
2010
    /* Step 5: s' = ( (( HE + r * SSK )^-1) * j ) modulo q, erase j */
2011
0
    if (err == 0) {
2012
0
        err = mp_invmod(s, &key->params.order, s);
2013
0
    }
2014
0
    if (err == 0) {
2015
0
        j = wc_ecc_key_get_priv(&key->pubkey);
2016
0
        err = mp_mulmod(s, j, &key->params.order, s);
2017
0
    }
2018
0
    if (err == 0) {
2019
0
        mp_forcezero(j);
2020
2021
        /* Step 6: s = s' fitted */
2022
0
        err = eccsi_fit_to_octets(s, &key->params.order, (int)sz, s);
2023
0
    }
2024
2025
    /* Step 7: Output Signature = ( r | s | PVT ) */
2026
0
    if (err == 0) {
2027
0
        err = eccsi_encode_sig(key, r, s, sig, sigSz);
2028
0
    }
2029
2030
0
    return err;
2031
0
}
2032
2033
/*
2034
 * Decode the s part of the signature = ( r | s | PVT )
2035
 *
2036
 * @param  [in]   key    ECCSI key.
2037
 * @param  [in]   sig    Signature of message.
2038
 * @param  [in]   sigSz  Length of signature in bytes.
2039
 * @param  [out]  s      MP integer that is the second signature element.
2040
 * @return  0 on success.
2041
 * @return  MEMORY_E when dynamic memory allocation fails.
2042
 * @return  Other -ve value when an internal operation fails.
2043
 */
2044
static int eccsi_decode_sig_s(const EccsiKey* key, const byte* sig,
2045
        word32 sigSz, mp_int* s)
2046
0
{
2047
0
    int err = 0;
2048
0
    word32 sz = (word32)key->ecc.dp->size;
2049
2050
0
    if (sigSz != sz * 4 + 1) {
2051
0
        err = BAD_FUNC_ARG;
2052
0
    }
2053
2054
0
    if (err == 0) {
2055
0
        err = mp_read_unsigned_bin(s, sig + sz, sz);
2056
0
    }
2057
2058
0
    return err;
2059
0
}
2060
2061
/*
2062
 * Decode the r and pvt part of the signature = ( r | s | PVT )
2063
 *
2064
 * @param  [in]   key    ECCSI key.
2065
 * @param  [in]   sig    Signature of message.
2066
 * @param  [in]   sigSz  Length of signature in bytes.
2067
 * @param  [out]  r      MP integer that is the first signature element.
2068
 * @param  [out]  pvt    ECC point representing Public Validation Token.
2069
 * @return  0 on success.
2070
 * @return  MEMORY_E when dynamic memory allocation fails.
2071
 * @return  Other -ve value when an internal operation fails.
2072
 */
2073
static int eccsi_decode_sig_r_pvt(const EccsiKey* key, const byte* sig,
2074
        word32 sigSz, mp_int* r, ecc_point* pvt)
2075
0
{
2076
0
    int err = 0;
2077
0
    word32 sz = (word32)key->ecc.dp->size;
2078
2079
0
    if (sigSz != sz * 4 + 1) {
2080
0
        err = BAD_FUNC_ARG;
2081
0
    }
2082
2083
0
    if (err == 0) {
2084
0
        err = mp_read_unsigned_bin(r, sig, sz);
2085
0
    }
2086
0
    if (err == 0) {
2087
        /* must free previous public point otherwise wc_ecc_import_point_der
2088
         * could leak memory */
2089
0
        mp_clear(pvt->x);
2090
0
        mp_clear(pvt->y);
2091
0
        mp_clear(pvt->z);
2092
2093
0
        err = wc_ecc_import_point_der(sig + sz * 2, sz * 2 + 1,
2094
0
                wc_ecc_get_curve_idx(key->ecc.dp->id), pvt);
2095
0
    }
2096
2097
0
    return err;
2098
0
}
2099
2100
/*
2101
 * Calculate Y point as part of verification process.
2102
 *
2103
 * Y = [HS]PVT + KPAK
2104
 *
2105
 * @param  [in]   key      ECCSI key.
2106
 * @param  [in]   pvt      ECC point representing Public Validation Token.
2107
 * @param  [in]   mp       Montgomery reduction multiplier.
2108
 * @param  [out]  y        ECC point representing calculated value Y.
2109
 * @return  0 on success.
2110
 * @return  MEMORY_E when dynamic memory allocation fails.
2111
 * @return  Other value when an an internal operation fails.
2112
 */
2113
static int eccsi_calc_y(EccsiKey* key, ecc_point* pvt, mp_digit mp,
2114
        ecc_point* y)
2115
0
{
2116
0
    int err;
2117
0
    mp_int* hs = &key->ssk;
2118
2119
0
    err = mp_read_unsigned_bin(hs, key->idHash, key->idHashSz);
2120
0
#ifndef WOLFSSL_HAVE_SP_ECC
2121
    /* Need KPAK in montgomery form. */
2122
0
    if (err == 0) {
2123
0
        err = eccsi_kpak_to_mont(key);
2124
0
    }
2125
0
#endif
2126
    /* [HS]PVT + KPAK */
2127
0
    if (err == 0) {
2128
0
        ecc_point* kpak = &key->ecc.pubkey;
2129
0
        err = eccsi_mulmod_point_add(key, hs, pvt, kpak, y, mp, 1);
2130
0
    }
2131
2132
0
    return err;
2133
0
}
2134
2135
/*
2136
 * Calculate J point as part of verification process.
2137
 *
2138
 * J = [s]( [HE]G + [r]Y )
2139
 *
2140
 * @param  [in]   key    ECCSI key.
2141
 * @param  [in]   hem    MP int representation of HE = Hash (hs, r and message).
2142
 * @param  [in]   sig    Signature of message.
2143
 * @param  [in]   sigSz  Length of signature in bytes.
2144
 * @param  [in]   y      ECC point representing [r]Y.
2145
 * @param  [in]   mp     Montgomery reduction multiplier.
2146
 * @param  [out]  j      ECC point representing calculated value J.
2147
 * @return  0 on success.
2148
 * @return  MEMORY_E when dynamic memory allocation fails.
2149
 * @return  Other value when an an internal operation fails.
2150
 */
2151
static int eccsi_calc_j(EccsiKey* key, const mp_int* hem, const byte* sig,
2152
        word32 sigSz, ecc_point* y, mp_digit mp, ecc_point* j)
2153
0
{
2154
0
    int err;
2155
0
    mp_int* s = &key->tmp;
2156
2157
    /* [HE]G + [r]Y */
2158
0
    err = eccsi_mulmod_base_add(key, hem, y, j, mp, 1);
2159
0
    if (err == 0) {
2160
0
        err = eccsi_decode_sig_s(key, sig, sigSz, s);
2161
0
    }
2162
    /* [s]( [HE]G + [r]Y ) */
2163
0
    if (err == 0) {
2164
0
        err = eccsi_mulmod_point(key, s, j, j, 1);
2165
0
    }
2166
2167
0
    return err;
2168
0
}
2169
2170
/**
2171
 * Verify the ECCSI hash (of ID with the key).
2172
 *
2173
 * RFC 6507, Section 5.2.2
2174
 *
2175
 * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n
2176
 * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set
2177
 * the identity hash to use.
2178
 *
2179
 * @param  [in]   key       ECCSI key.
2180
 * @param  [in]   hashType  Type of hash algorithm. e.g. WC_SHA256
2181
 * @param  [in]   msg       Message to verify.
2182
 * @param  [in]   msgSz     Length of message in bytes.
2183
 * @param  [in]   sig       Signature of message.
2184
 * @param  [in]   sigSz     Length of signature in bytes.
2185
 * @param  [out]  verified  1 when the signature was verified and 0 otherwise.
2186
 * @return  0 on success.
2187
 * @return  BAD_FUNC_ARG when key, hash, msg, sig or ret is NULL.
2188
 * @return  BAD_STATE_E when the curve or id hash has not been set (no key set).
2189
 * @return  MEMORY_E when dynamic memory allocation fails.
2190
 * @return  Other value when an an internal operation fails.
2191
 */
2192
int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType,
2193
        const byte* msg, word32 msgSz, const byte* sig, word32 sigSz,
2194
        int* verified)
2195
0
{
2196
0
    int err = 0;
2197
0
    byte* he = NULL;
2198
0
    word32 heSz = 0;
2199
0
    mp_int* r = NULL;
2200
0
    mp_int* jx = NULL;
2201
0
    mp_int* hem = NULL;
2202
0
    ecc_point* pvt = NULL;
2203
0
    ecc_point* y = NULL;
2204
0
    ecc_point* j = NULL;
2205
0
    mp_digit mp = 0;
2206
0
    EccsiKeyParams* params = NULL;
2207
2208
0
    if ((key == NULL) || (msg == NULL) || (sig == NULL) || (verified == NULL)) {
2209
0
        err = BAD_FUNC_ARG;
2210
0
    }
2211
0
    if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) &&
2212
0
            (key->ecc.type != ECC_PUBLICKEY)) {
2213
0
        err = BAD_STATE_E;
2214
0
    }
2215
0
    if ((err == 0) && (key->idHashSz == 0)) {
2216
0
        err = BAD_STATE_E;
2217
0
    }
2218
2219
0
    if (err != 0)
2220
0
        return err;
2221
2222
0
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
2223
2224
    /* Decode the signature into components. */
2225
0
    r = wc_ecc_key_get_priv(&key->pubkey);
2226
0
    pvt = &key->pubkey.pubkey;
2227
0
    err = eccsi_decode_sig_r_pvt(key, sig, sigSz, r, pvt);
2228
2229
    /* Load the curve parameters for operations */
2230
0
    if (err == 0) {
2231
0
        err = eccsi_load_base(key);
2232
0
    }
2233
0
    if (err == 0) {
2234
0
        err = eccsi_load_ecc_params(key);
2235
0
    }
2236
0
    if (err == 0) {
2237
0
        params = &key->params;
2238
0
        err = mp_montgomery_setup(&params->prime, &mp);
2239
0
    }
2240
2241
    /* Step 1: Validate PVT is on curve */
2242
0
    if (err == 0) {
2243
0
        err = wc_ecc_is_point(pvt, &params->a, &params->b, &params->prime);
2244
0
    }
2245
2246
    /* Step 2: Compute HS = hash( G | KPAK | ID | PVT )
2247
     * HS is key->idHash, key->idHashSz */
2248
2249
    /* Step 3: Compute HE = hash( HS | r | M ) */
2250
0
    if (err == 0) {
2251
0
        he = key->data;
2252
0
        err = eccsi_compute_he(key, hashType, r, msg, msgSz, he, &heSz);
2253
0
    }
2254
2255
    /* Step 4: Y = [HS]PVT + KPAK */
2256
0
    if (err == 0) {
2257
0
        y = pvt;
2258
0
        err = eccsi_calc_y(key, pvt, mp, y);
2259
0
    }
2260
2261
    /* Step 5: Compute J = [s]( [HE]G + [r]Y ) */
2262
    /* [r]Y */
2263
0
    if (err == 0) {
2264
0
        hem = &key->tmp;
2265
0
        err = mp_read_unsigned_bin(hem, he, heSz);
2266
0
    }
2267
0
    if (err == 0) {
2268
0
        err = eccsi_mulmod_point(key, r, y, y, 0);
2269
0
    }
2270
0
    if (err == 0) {
2271
0
        j = params->base;
2272
0
        err = eccsi_calc_j(key, hem, sig, sigSz, y, mp, j);
2273
0
        key->params.haveBase = 0;
2274
0
    }
2275
2276
    /* Step 6: Jx fitting, compare with r */
2277
0
    if (err == 0) {
2278
0
        jx = &key->tmp;
2279
0
        err = eccsi_fit_to_octets(j->x, &params->order, key->ecc.dp->size, jx);
2280
0
    }
2281
2282
0
    if (verified != NULL) {
2283
0
        *verified = ((err == 0) && (mp_cmp(jx, r) == MP_EQ));
2284
0
    }
2285
2286
0
    RESTORE_VECTOR_REGISTERS();
2287
2288
0
    return err;
2289
0
}
2290
#endif /* WOLFCRYPT_ECCSI_CLIENT */
2291
2292
#endif /* WOLFCRYPT_HAVE_ECCSI */
2293