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