Coverage Report

Created: 2025-07-23 06:59

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