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