1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Crypto Component */
17 /** */
18 /** Elliptic Curve Digital Signature Algorithm (ECDSA) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_ecdsa.h"
24
25
26 /**************************************************************************/
27 /* */
28 /* FUNCTION RELEASE */
29 /* */
30 /* _nx_crypto_ecdsa_sign PORTABLE C */
31 /* 6.1 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function computes a signature of the hash data using the */
39 /* private key. */
40 /* */
41 /* */
42 /* INPUT */
43 /* */
44 /* curve Curve used in the ECDSA */
45 /* hash Hash data to be signed */
46 /* hash_length Length of hash data */
47 /* private_key Pointer to EC private key */
48 /* signature Pointer to signature output */
49 /* scratch Pointer to scratch buffer. */
50 /* This scratch buffer can be */
51 /* reused after this function */
52 /* returns. */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* _nx_crypto_ec_key_pair_generation_extra */
61 /* Generate EC Key Pair */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Application Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
72 /* 09-30-2020 Timothy Stapko Modified comment(s), */
73 /* verified memmove use cases, */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_nx_crypto_ecdsa_sign(NX_CRYPTO_EC * curve,UCHAR * hash,UINT hash_length,UCHAR * private_key,UINT private_key_length,UCHAR * signature,ULONG signature_length,ULONG * actual_signature_length,HN_UBASE * scratch)77 NX_CRYPTO_KEEP UINT _nx_crypto_ecdsa_sign(NX_CRYPTO_EC *curve, UCHAR *hash, UINT hash_length,
78 UCHAR *private_key, UINT private_key_length,
79 UCHAR *signature, ULONG signature_length,
80 ULONG *actual_signature_length, HN_UBASE *scratch)
81 {
82 UINT status;
83 NX_CRYPTO_HUGE_NUMBER privkey;
84 NX_CRYPTO_HUGE_NUMBER z;
85 NX_CRYPTO_HUGE_NUMBER k;
86 NX_CRYPTO_HUGE_NUMBER ik;
87 NX_CRYPTO_HUGE_NUMBER temp;
88 NX_CRYPTO_EC_POINT pt;
89 UINT buffer_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size;
90 UINT i;
91 UINT curve_size;
92 UINT r_size;
93 UINT s_size;
94 UCHAR pad_zero_r;
95 UCHAR pad_zero_s;
96 UINT sequence_size;
97 UCHAR *signature_r;
98 UCHAR *signature_s;
99
100 /* Signature format follows ASN1 DER encoding as per RFC 4492, section 5.8:
101 * Size: 1 | 1 or 2 | 1 | 1 | 0 or 1 | N | 1 | 1 | 0 or 1 | M
102 * Data: SEQ | Size | INT | Size | 0x00 | r | INT | Size | 0x00 | s */
103
104 curve_size = curve -> nx_crypto_ec_bits >> 3;
105 if (curve -> nx_crypto_ec_bits & 7)
106 {
107 curve_size++;
108 }
109
110 /* Check the signature_length for worst case. */
111 if (signature_length < ((curve_size << 1) + 9))
112 {
113 return(NX_CRYPTO_SIZE_ERROR);
114 }
115
116 if (private_key_length > buffer_size)
117 {
118 return(NX_CRYPTO_SIZE_ERROR);
119 }
120
121 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&privkey, scratch, buffer_size);
122 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&z, scratch, buffer_size);
123 /* Initialize per-message secret k buffer with 64 bits more buffer size. */
124 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&k, scratch, buffer_size + 8);
125 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&ik, scratch, buffer_size);
126 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, buffer_size * 2);
127 NX_CRYPTO_EC_POINT_INITIALIZE(&pt, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size);
128
129 /* Copy the private key from the caller's buffer. */
130 status = _nx_crypto_huge_number_setup(&privkey, private_key, private_key_length);
131 if (status != NX_CRYPTO_SUCCESS)
132 {
133 return(status);
134 }
135
136 /* Truncate the hash data to the size of group order. */
137 if (hash_length > buffer_size)
138 {
139 hash_length = buffer_size;
140 }
141
142 status = _nx_crypto_huge_number_setup(&z, hash, hash_length);
143 if (status != NX_CRYPTO_SUCCESS)
144 {
145 return(status);
146 }
147
148 /* The bit length of the hash data used is not longer than the group order. */
149 if (curve -> nx_crypto_ec_bits < hash_length << 3)
150 {
151 _nx_crypto_huge_number_shift_right(&z, (hash_length << 3) - curve -> nx_crypto_ec_bits);
152 }
153
154 do
155 {
156 do
157 {
158 /* Generate Key Pair. */
159 _nx_crypto_ec_key_pair_generation_extra(curve, &curve -> nx_crypto_ec_g, &k, &pt,
160 scratch);
161
162 /* Calculate r = pt.x mod n */
163 _nx_crypto_huge_number_modulus(&pt.nx_crypto_ec_point_x, &curve -> nx_crypto_ec_n);
164
165 } while (_nx_crypto_huge_number_is_zero(&pt.nx_crypto_ec_point_x));
166
167 /* Calculate s = k^-1 * (z + r * private_key) */
168 _nx_crypto_huge_number_inverse_modulus(&k, &curve -> nx_crypto_ec_n, &ik, scratch);
169 _nx_crypto_huge_number_multiply(&pt.nx_crypto_ec_point_x, &privkey, &temp);
170 _nx_crypto_huge_number_add_unsigned(&temp, &z);
171 _nx_crypto_huge_number_modulus(&temp, &curve -> nx_crypto_ec_n);
172 NX_CRYPTO_HUGE_NUMBER_COPY(&k, &temp);
173 _nx_crypto_huge_number_multiply(&ik, &k, &temp);
174 _nx_crypto_huge_number_modulus(&temp, &curve -> nx_crypto_ec_n);
175
176 } while (_nx_crypto_huge_number_is_zero(&temp));
177
178 /* Output r and s as two INTEGER in ASN.1 encoding */
179 signature_r = signature + 3;
180 status = _nx_crypto_huge_number_extract(&pt.nx_crypto_ec_point_x, signature_r, (curve_size + 3), &r_size);
181 if (status != NX_CRYPTO_SUCCESS)
182 {
183 return(status);
184 }
185
186 signature_s = signature + (curve_size + 6);
187 status = _nx_crypto_huge_number_extract(&temp, signature_s, (curve_size + 3), &s_size);
188 if (status != NX_CRYPTO_SUCCESS)
189 {
190 return(status);
191 }
192
193 /* Trim prefix zeros. */
194 for (i = 0; i < r_size; i++)
195 {
196 if (signature_r[i])
197 {
198
199 /* Loop until none zero byte. */
200 break;
201 }
202 }
203 signature_r += i;
204 r_size -= i;
205
206 /* The most significant bit must be zero to indicate positive integer. */
207 /* Pad zero at the front if necessary. */
208 pad_zero_r = (signature_r[0] & 0x80) ? 1 : 0;
209
210 for (i = 0; i < s_size; i++)
211 {
212 if (signature_s[i])
213 {
214
215 /* Loop until none zero byte. */
216 break;
217 }
218 }
219 signature_s += i;
220 s_size -= i;
221
222 /* The most significant bit must be zero to indicate positive integer. */
223 /* Pad zero at the front if necessary. */
224 pad_zero_s = (signature_s[0] & 0x80) ? 1 : 0;
225
226 /* Size of sequence. */
227 sequence_size = r_size + pad_zero_r + s_size + pad_zero_s + 4;
228
229 signature[0] = 0x30; /* SEQUENCE */
230 if (sequence_size < 0x80)
231 {
232 signature[1] = (UCHAR)sequence_size;
233 signature += 2;
234 *actual_signature_length = sequence_size + 2;
235 }
236 else
237 {
238 signature[1] = 0x81;
239 signature[2] = (UCHAR)sequence_size;
240 signature += 3;
241 *actual_signature_length = sequence_size + 3;
242 }
243
244 /* Setup r. */
245 NX_CRYPTO_MEMMOVE(&signature[2 + pad_zero_r], signature_r, r_size); /* Use case of memmove is verified. */
246 signature[0] = 0x02; /* Integer */
247 signature[1] = (UCHAR)(r_size + pad_zero_r);
248 if (pad_zero_r)
249 {
250 signature[2] = 0;
251 }
252 signature += (2u + pad_zero_r + r_size);
253
254 /* Setup s. */
255 NX_CRYPTO_MEMMOVE(&signature[2 + pad_zero_s], signature_s, s_size); /* Use case of memmove is verified. */
256 signature[0] = 0x02; /* Integer */
257 signature[1] = (UCHAR)(s_size + pad_zero_s);
258 if (pad_zero_s)
259 {
260 signature[2] = 0;
261 }
262
263 return NX_CRYPTO_SUCCESS;
264 }
265
266 /**************************************************************************/
267 /* */
268 /* FUNCTION RELEASE */
269 /* */
270 /* _nx_crypto_ecdsa_verify PORTABLE C */
271 /* 6.1 */
272 /* AUTHOR */
273 /* */
274 /* Timothy Stapko, Microsoft Corporation */
275 /* */
276 /* DESCRIPTION */
277 /* */
278 /* This function verifies the signature of the hash data using the */
279 /* public key. */
280 /* */
281 /* INPUT */
282 /* */
283 /* curve Curve used in the ECDSA */
284 /* hash Hash data to be verified */
285 /* hash_length Length of hash data */
286 /* public_key Pointer to EC public key */
287 /* signature Signature to be verified */
288 /* scratch Pointer to scratch buffer. */
289 /* This scratch buffer can be */
290 /* reused after this function */
291 /* returns. */
292 /* */
293 /* OUTPUT */
294 /* */
295 /* status Completion status */
296 /* */
297 /* CALLS */
298 /* */
299 /* _nx_crypto_huge_number_setup Generate private key */
300 /* */
301 /* CALLED BY */
302 /* */
303 /* Application Code */
304 /* */
305 /* RELEASE HISTORY */
306 /* */
307 /* DATE NAME DESCRIPTION */
308 /* */
309 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
310 /* 09-30-2020 Timothy Stapko Modified comment(s), and */
311 /* fixed input validation, */
312 /* added public key validation,*/
313 /* resulting in version 6.1 */
314 /* */
315 /**************************************************************************/
_nx_crypto_ecdsa_verify(NX_CRYPTO_EC * curve,UCHAR * hash,UINT hash_length,UCHAR * public_key,UINT public_key_length,UCHAR * signature,UINT signature_length,HN_UBASE * scratch)316 NX_CRYPTO_KEEP UINT _nx_crypto_ecdsa_verify(NX_CRYPTO_EC *curve, UCHAR *hash, UINT hash_length,
317 UCHAR *public_key, UINT public_key_length,
318 UCHAR *signature, UINT signature_length, HN_UBASE *scratch)
319 {
320 UINT status;
321 NX_CRYPTO_HUGE_NUMBER r;
322 NX_CRYPTO_HUGE_NUMBER s;
323 NX_CRYPTO_HUGE_NUMBER z;
324 NX_CRYPTO_HUGE_NUMBER w;
325 NX_CRYPTO_HUGE_NUMBER u1;
326 NX_CRYPTO_HUGE_NUMBER u2;
327 NX_CRYPTO_EC_POINT pubkey;
328 NX_CRYPTO_EC_POINT pt;
329 NX_CRYPTO_EC_POINT pt2;
330 UINT buffer_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size;
331
332 /* Signature format follows ASN1 DER encoding as per RFC 4492, section 5.8:
333 * Size: 1 | 1 or 2 | 1 | 1 | 0 or 1 | N | 1 | 1 | 0 or 1 | M
334 * Data: SEQ | Size | INT | Size | 0x00 | r | INT | Size | 0x00 | s */
335
336
337 if (public_key_length > 1 + (buffer_size << 1))
338 {
339 return(NX_CRYPTO_SIZE_ERROR);
340 }
341
342 /* Buffer should contain the signature data sequence. */
343 if (signature[0] != 0x30)
344 {
345 return(NX_CRYPTO_AUTHENTICATION_FAILED);
346 }
347
348 /* Check the size in SEQUENCE. */
349 if (signature[1] & 0x80)
350 {
351 if (signature_length < (signature[2] + 3u))
352 {
353 return(NX_CRYPTO_SIZE_ERROR);
354 }
355 signature_length = signature[2];
356 signature += 3;
357 }
358 else
359 {
360 if (signature_length < (signature[1] + 2u))
361 {
362 return(NX_CRYPTO_SIZE_ERROR);
363 }
364 signature_length = signature[1];
365 signature += 2;
366 }
367
368 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&r, scratch, buffer_size);
369 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&s, scratch, buffer_size);
370 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&z, scratch, buffer_size);
371 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&w, scratch, buffer_size);
372 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&u1, scratch, buffer_size << 1);
373 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&u2, scratch, buffer_size << 1);
374 NX_CRYPTO_EC_POINT_INITIALIZE(&pubkey, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size);
375 NX_CRYPTO_EC_POINT_INITIALIZE(&pt, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size);
376 NX_CRYPTO_EC_POINT_INITIALIZE(&pt2, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size);
377
378 /* Copy the public key from the caller's buffer. */
379 status = _nx_crypto_ec_point_setup(&pubkey, public_key, public_key_length);
380 if (status != NX_CRYPTO_SUCCESS)
381 {
382 return(status);
383 }
384
385 #ifndef NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION
386 status = _nx_crypto_ec_validate_public_key(&pubkey, curve, NX_CRYPTO_FALSE, scratch);
387 if (status != NX_CRYPTO_SUCCESS)
388 {
389 return(status);
390 }
391 #endif /* NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION */
392
393 if (signature_length < (signature[1] + 2u))
394 {
395 return(NX_CRYPTO_SIZE_ERROR);
396 }
397
398 /* Read r value from input signature. */
399 status = _nx_crypto_huge_number_setup(&r, &signature[2], signature[1]);
400 if (status != NX_CRYPTO_SUCCESS)
401 {
402 return(status);
403 }
404 signature_length -= (signature[1] + 2u);
405 signature += signature[1] + 2;
406
407 if (signature_length < (signature[1] + 2u))
408 {
409 return(NX_CRYPTO_SIZE_ERROR);
410 }
411
412 /* Read s value from input signature. */
413 status = _nx_crypto_huge_number_setup(&s, &signature[2], signature[1]);
414 if (status != NX_CRYPTO_SUCCESS)
415 {
416 return(status);
417 }
418
419 /* r and s must be in the range [1..n-1] */
420 if(_nx_crypto_huge_number_is_zero(&r) || _nx_crypto_huge_number_is_zero(&s))
421 {
422 return(NX_CRYPTO_NOT_SUCCESSFUL);
423 }
424
425 if(NX_CRYPTO_HUGE_NUMBER_LESS != _nx_crypto_huge_number_compare_unsigned(&r, &curve -> nx_crypto_ec_n))
426 {
427 return(NX_CRYPTO_NOT_SUCCESSFUL);
428 }
429
430 if(NX_CRYPTO_HUGE_NUMBER_LESS != _nx_crypto_huge_number_compare_unsigned(&s, &curve -> nx_crypto_ec_n))
431 {
432 return(NX_CRYPTO_NOT_SUCCESSFUL);
433 }
434
435 /* Truncate the hash data to the size of group order. */
436 if (hash_length > buffer_size)
437 {
438 hash_length = buffer_size;
439 }
440
441 status = _nx_crypto_huge_number_setup(&z, hash, hash_length);
442 if (status != NX_CRYPTO_SUCCESS)
443 {
444 return(status);
445 }
446
447 if (curve -> nx_crypto_ec_bits < hash_length << 3)
448 {
449 _nx_crypto_huge_number_shift_right(&z, (hash_length << 3) - curve -> nx_crypto_ec_bits);
450 }
451
452 /* Calculate w = s^-1 mod n */
453 _nx_crypto_huge_number_inverse_modulus(&s, &curve -> nx_crypto_ec_n, &w, scratch);
454
455 /* Calculate u1 = zw mod n */
456 _nx_crypto_huge_number_multiply(&z, &w, &u1);
457 _nx_crypto_huge_number_modulus(&u1, &curve -> nx_crypto_ec_n);
458
459 /* Calculate u2 = rw mod n */
460 _nx_crypto_huge_number_multiply(&r, &w, &u2);
461 _nx_crypto_huge_number_modulus(&u2, &curve -> nx_crypto_ec_n);
462
463 /* Calculate (x1,y1) = u1*G + u2*public_key */
464 curve -> nx_crypto_ec_multiple(curve, &curve -> nx_crypto_ec_g, &u1, &pt, scratch);
465 curve -> nx_crypto_ec_multiple(curve, &pubkey, &u2, &pt2, scratch);
466
467 curve -> nx_crypto_ec_add(curve, &pt, &pt2, scratch);
468
469 _nx_crypto_huge_number_modulus(&pt.nx_crypto_ec_point_x, &curve -> nx_crypto_ec_n);
470
471 /* Check r == x1 mod n */
472 if (NX_CRYPTO_HUGE_NUMBER_EQUAL != _nx_crypto_huge_number_compare_unsigned(&pt.nx_crypto_ec_point_x, &r))
473 {
474 return NX_CRYPTO_NOT_SUCCESSFUL;
475 }
476 return NX_CRYPTO_SUCCESS;
477 }
478
479 /**************************************************************************/
480 /* */
481 /* FUNCTION RELEASE */
482 /* */
483 /* _nx_crypto_method_ecdsa_init PORTABLE C */
484 /* 6.3.0 */
485 /* AUTHOR */
486 /* */
487 /* Timothy Stapko, Microsoft Corporation */
488 /* */
489 /* DESCRIPTION */
490 /* */
491 /* This function is the common crypto method init callback for */
492 /* Microsoft supported ECDSA cryptographic algorithm. */
493 /* */
494 /* INPUT */
495 /* */
496 /* method Pointer to crypto method */
497 /* key Pointer to key */
498 /* key_size_in_bits Length of key size in bits */
499 /* handler Returned crypto handler */
500 /* crypto_metadata Metadata area */
501 /* crypto_metadata_size Size of the metadata area */
502 /* */
503 /* OUTPUT */
504 /* */
505 /* status Completion status */
506 /* */
507 /* CALLS */
508 /* */
509 /* None */
510 /* */
511 /* CALLED BY */
512 /* */
513 /* Application Code */
514 /* */
515 /* RELEASE HISTORY */
516 /* */
517 /* DATE NAME DESCRIPTION */
518 /* */
519 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
520 /* 09-30-2020 Timothy Stapko Modified comment(s), */
521 /* resulting in version 6.1 */
522 /* 10-31-2023 Yanwu Cai Modified comment(s), */
523 /* resulting in version 6.3.0 */
524 /* */
525 /**************************************************************************/
_nx_crypto_method_ecdsa_init(struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,VOID ** handle,VOID * crypto_metadata,ULONG crypto_metadata_size)526 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_init(struct NX_CRYPTO_METHOD_STRUCT *method,
527 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
528 VOID **handle,
529 VOID *crypto_metadata,
530 ULONG crypto_metadata_size)
531 {
532 NX_CRYPTO_ECDSA *ecdsa;
533
534 NX_CRYPTO_PARAMETER_NOT_USED(key);
535 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
536 NX_CRYPTO_PARAMETER_NOT_USED(handle);
537
538 NX_CRYPTO_STATE_CHECK
539
540 if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
541 {
542 return(NX_CRYPTO_PTR_ERROR);
543 }
544
545 /* Verify the metadata address is 4-byte aligned. */
546 if((((ULONG)crypto_metadata) & 0x3) != 0)
547 {
548 return(NX_CRYPTO_PTR_ERROR);
549 }
550
551 if(crypto_metadata_size < sizeof(NX_CRYPTO_ECDSA))
552 {
553 return(NX_CRYPTO_PTR_ERROR);
554 }
555
556 ecdsa = (NX_CRYPTO_ECDSA *)crypto_metadata;
557
558 /* Reset ECDSA metadata. */
559 ecdsa -> nx_crypto_ecdsa_curve = NX_CRYPTO_NULL;
560 ecdsa -> nx_crypto_ecdsa_hash_method = NX_CRYPTO_NULL;
561
562 return(NX_CRYPTO_SUCCESS);
563 }
564
565
566 /**************************************************************************/
567 /* */
568 /* FUNCTION RELEASE */
569 /* */
570 /* _nx_crypto_method_ecdsa_cleanup PORTABLE C */
571 /* 6.1 */
572 /* AUTHOR */
573 /* */
574 /* Timothy Stapko, Microsoft Corporation */
575 /* */
576 /* DESCRIPTION */
577 /* */
578 /* This function cleans up the crypto metadata. */
579 /* */
580 /* INPUT */
581 /* */
582 /* crypto_metadata Crypto metadata */
583 /* */
584 /* OUTPUT */
585 /* */
586 /* status Completion status */
587 /* */
588 /* CALLS */
589 /* */
590 /* NX_CRYPTO_MEMSET Set the memory */
591 /* */
592 /* CALLED BY */
593 /* */
594 /* Application Code */
595 /* */
596 /* RELEASE HISTORY */
597 /* */
598 /* DATE NAME DESCRIPTION */
599 /* */
600 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
601 /* 09-30-2020 Timothy Stapko Modified comment(s), */
602 /* resulting in version 6.1 */
603 /* */
604 /**************************************************************************/
_nx_crypto_method_ecdsa_cleanup(VOID * crypto_metadata)605 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_cleanup(VOID *crypto_metadata)
606 {
607
608 NX_CRYPTO_STATE_CHECK
609
610 #ifdef NX_SECURE_KEY_CLEAR
611 if (!crypto_metadata)
612 return (NX_CRYPTO_SUCCESS);
613
614 /* Clean up the crypto metadata. */
615 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_ECDSA));
616 #else
617 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
618 #endif/* NX_SECURE_KEY_CLEAR */
619
620 return(NX_CRYPTO_SUCCESS);
621 }
622
623
624 /**************************************************************************/
625 /* */
626 /* FUNCTION RELEASE */
627 /* */
628 /* _nx_crypto_method_ecdsa_operation PORTABLE C */
629 /* 6.3.0 */
630 /* AUTHOR */
631 /* */
632 /* Timothy Stapko, Microsoft Corporation */
633 /* */
634 /* DESCRIPTION */
635 /* */
636 /* This function performs an ECDSA operation. */
637 /* */
638 /* INPUT */
639 /* */
640 /* op ECDSA operation */
641 /* handle Crypto handle */
642 /* method Cryption Method Object */
643 /* key Encryption Key */
644 /* key_size_in_bits Key size in bits */
645 /* input Input data */
646 /* input_length_in_byte Input data size */
647 /* iv_ptr Initial vector */
648 /* output Output buffer */
649 /* output_length_in_byte Output buffer size */
650 /* crypto_metadata Metadata area */
651 /* crypto_metadata_size Metadata area size */
652 /* packet_ptr Pointer to packet */
653 /* nx_crypto_hw_process_callback Callback function pointer */
654 /* */
655 /* OUTPUT */
656 /* */
657 /* status Completion status */
658 /* */
659 /* CALLS */
660 /* */
661 /* _nx_crypto_ecdsa_sign Sign using ECDSA */
662 /* _nx_crypto_ecdsa_verify Verify ECDSA signature */
663 /* */
664 /* CALLED BY */
665 /* */
666 /* Application Code */
667 /* */
668 /* RELEASE HISTORY */
669 /* */
670 /* DATE NAME DESCRIPTION */
671 /* */
672 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
673 /* 09-30-2020 Timothy Stapko Modified comment(s), */
674 /* resulting in version 6.1 */
675 /* 10-31-2023 Yanwu Cai Modified comment(s), */
676 /* resulting in version 6.3.0 */
677 /* */
678 /**************************************************************************/
_nx_crypto_method_ecdsa_operation(UINT op,VOID * handle,struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,UCHAR * input,ULONG input_length_in_byte,UCHAR * iv_ptr,UCHAR * output,ULONG output_length_in_byte,VOID * crypto_metadata,ULONG crypto_metadata_size,VOID * packet_ptr,VOID (* nx_crypto_hw_process_callback)(VOID *,UINT))679 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_operation(UINT op,
680 VOID *handle,
681 struct NX_CRYPTO_METHOD_STRUCT *method,
682 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
683 UCHAR *input, ULONG input_length_in_byte,
684 UCHAR *iv_ptr,
685 UCHAR *output, ULONG output_length_in_byte,
686 VOID *crypto_metadata, ULONG crypto_metadata_size,
687 VOID *packet_ptr,
688 VOID (*nx_crypto_hw_process_callback)(VOID *, UINT))
689 {
690 NX_CRYPTO_ECDSA *ecdsa;
691 UINT status = NX_CRYPTO_SUCCESS;
692 NX_CRYPTO_EXTENDED_OUTPUT
693 *extended_output;
694 NX_CRYPTO_METHOD *hash_method;
695 VOID *hash_handler = NX_CRYPTO_NULL;
696 UCHAR *hash_output = NX_CRYPTO_NULL;
697
698 NX_CRYPTO_PARAMETER_NOT_USED(handle);
699 NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
700 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
701 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
702
703 NX_CRYPTO_STATE_CHECK
704
705 /* Verify the metadata address is 4-byte aligned. */
706 if((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
707 {
708 return(NX_CRYPTO_PTR_ERROR);
709 }
710
711 if(crypto_metadata_size < sizeof(NX_CRYPTO_ECDSA))
712 {
713 return(NX_CRYPTO_PTR_ERROR);
714 }
715
716 ecdsa = (NX_CRYPTO_ECDSA *)crypto_metadata;
717
718 if (op == NX_CRYPTO_EC_CURVE_SET)
719 {
720 status = ((NX_CRYPTO_METHOD *)input) -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET,
721 NX_CRYPTO_NULL,
722 (NX_CRYPTO_METHOD *)input,
723 NX_CRYPTO_NULL, 0,
724 NX_CRYPTO_NULL, 0,
725 NX_CRYPTO_NULL,
726 (UCHAR *)&ecdsa -> nx_crypto_ecdsa_curve,
727 sizeof(NX_CRYPTO_METHOD *),
728 NX_CRYPTO_NULL, 0,
729 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
730
731 if (status)
732 {
733 return(status);
734 }
735 }
736 else if (op == NX_CRYPTO_AUTHENTICATE)
737 {
738 if ((key == NX_CRYPTO_NULL) || (ecdsa -> nx_crypto_ecdsa_curve == NX_CRYPTO_NULL))
739 {
740 return(NX_CRYPTO_PTR_ERROR);
741 }
742
743 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
744
745 status = _nx_crypto_ecdsa_sign(ecdsa -> nx_crypto_ecdsa_curve,
746 input,
747 input_length_in_byte,
748 key,
749 key_size_in_bits >> 3,
750 extended_output -> nx_crypto_extended_output_data,
751 extended_output -> nx_crypto_extended_output_length_in_byte,
752 &extended_output -> nx_crypto_extended_output_actual_size,
753 ecdsa -> nx_crypto_ecdsa_scratch_buffer);
754 }
755 else if (op == NX_CRYPTO_VERIFY)
756 {
757 if (key == NX_CRYPTO_NULL)
758 {
759 return(NX_CRYPTO_PTR_ERROR);
760 }
761
762 status = _nx_crypto_ecdsa_verify(ecdsa->nx_crypto_ecdsa_curve,
763 input,
764 input_length_in_byte,
765 key,
766 key_size_in_bits >> 3,
767 output, output_length_in_byte,
768 ecdsa -> nx_crypto_ecdsa_scratch_buffer);
769 }
770 else if (op == NX_CRYPTO_EC_KEY_PAIR_GENERATE)
771 {
772 if (ecdsa->nx_crypto_ecdsa_curve == NX_CRYPTO_NULL)
773 {
774 return(NX_CRYPTO_PTR_ERROR);
775 }
776
777 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
778 status = _nx_crypto_ec_key_pair_stream_generate(ecdsa->nx_crypto_ecdsa_curve,
779 extended_output -> nx_crypto_extended_output_data,
780 extended_output -> nx_crypto_extended_output_length_in_byte,
781 &extended_output -> nx_crypto_extended_output_actual_size,
782 ecdsa -> nx_crypto_ecdsa_scratch_buffer);
783 }
784 else if (op == NX_CRYPTO_HASH_METHOD_SET)
785 {
786
787 /* Setup hash method used by ECDSA. */
788 hash_method = (NX_CRYPTO_METHOD *)input;
789
790 /* ECDSA scratch buffer shares with metadata of hash method.
791 * Check the size required by metadata of hash method. */
792 if ((hash_method -> nx_crypto_metadata_area_size +
793 (hash_method -> nx_crypto_ICV_size_in_bits >> 3)) >
794 sizeof(ecdsa -> nx_crypto_ecdsa_scratch_buffer))
795 {
796 status = NX_CRYPTO_SIZE_ERROR;
797 }
798 else
799 {
800 ecdsa -> nx_crypto_ecdsa_hash_method = hash_method;
801 }
802 }
803 else if ((op == NX_CRYPTO_SIGNATURE_GENERATE) || (op == NX_CRYPTO_SIGNATURE_VERIFY))
804 {
805 hash_method = ecdsa -> nx_crypto_ecdsa_hash_method;
806 if (hash_method == NX_CRYPTO_NULL)
807 {
808
809 /* Hash method is not set successfully. */
810 status = NX_CRYPTO_PTR_ERROR;
811 }
812 else
813 {
814
815 /* Put the hash at the end of scratch buffer. */
816 hash_output = (UCHAR *)(ecdsa -> nx_crypto_ecdsa_scratch_buffer) +
817 (sizeof(ecdsa -> nx_crypto_ecdsa_scratch_buffer) - (hash_method -> nx_crypto_ICV_size_in_bits >> 3));
818
819 /* First, calculate hash value of input message. */
820 if (hash_method -> nx_crypto_init)
821 {
822 status = hash_method -> nx_crypto_init(hash_method,
823 NX_CRYPTO_NULL,
824 0,
825 &hash_handler,
826 ecdsa -> nx_crypto_ecdsa_scratch_buffer,
827 hash_method -> nx_crypto_metadata_area_size);
828 }
829
830 if (status == NX_CRYPTO_SUCCESS)
831 {
832 status = hash_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE,
833 NX_CRYPTO_NULL,
834 hash_method,
835 NX_CRYPTO_NULL,
836 0,
837 input,
838 input_length_in_byte,
839 NX_CRYPTO_NULL,
840 hash_output,
841 (hash_method -> nx_crypto_ICV_size_in_bits >> 3),
842 ecdsa -> nx_crypto_ecdsa_scratch_buffer,
843 hash_method -> nx_crypto_metadata_area_size,
844 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
845
846 if (status != NX_CRYPTO_SUCCESS)
847 {
848 return(status);
849 }
850 }
851
852 if (hash_method -> nx_crypto_cleanup)
853 {
854 status = hash_method -> nx_crypto_cleanup(ecdsa -> nx_crypto_ecdsa_scratch_buffer);
855 }
856 }
857
858 if (status == NX_CRYPTO_SUCCESS)
859 {
860
861 /* Second, generate/verify signature. */
862 if ((key == NX_CRYPTO_NULL) || (ecdsa -> nx_crypto_ecdsa_curve == NX_CRYPTO_NULL))
863 {
864 status = NX_CRYPTO_PTR_ERROR;
865 }
866 else if (op == NX_CRYPTO_SIGNATURE_GENERATE)
867 {
868
869 /* Signature generation. */
870 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
871
872 status = _nx_crypto_ecdsa_sign(ecdsa -> nx_crypto_ecdsa_curve,
873 hash_output,
874 (hash_method -> nx_crypto_ICV_size_in_bits >> 3),
875 key,
876 key_size_in_bits >> 3,
877 extended_output -> nx_crypto_extended_output_data,
878 extended_output -> nx_crypto_extended_output_length_in_byte,
879 &extended_output -> nx_crypto_extended_output_actual_size,
880 ecdsa -> nx_crypto_ecdsa_scratch_buffer);
881 }
882 else
883 {
884
885 /* Signature verification. */
886 status = _nx_crypto_ecdsa_verify(ecdsa->nx_crypto_ecdsa_curve,
887 hash_output,
888 (hash_method -> nx_crypto_ICV_size_in_bits >> 3),
889 key,
890 key_size_in_bits >> 3,
891 output, output_length_in_byte,
892 ecdsa -> nx_crypto_ecdsa_scratch_buffer);
893 }
894 }
895 }
896 else
897 {
898 status = NX_CRYPTO_NOT_SUCCESSFUL;
899 }
900
901 return(status);
902 }
903