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 Diffie-Hellman (ECDH) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_CRYPTO_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_crypto_ecdh.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nx_crypto_ecdh_key_pair_import PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Timothy Stapko, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function sets up a Elliptic-curve Diffie-Hellman context by */
44 /* importing a local key pair. */
45 /* */
46 /* INPUT */
47 /* */
48 /* ecdh_ptr ECDH context */
49 /* curve Elliptic Curve */
50 /* local_private_key_ptr Pointer to local private key */
51 /* local_private_key_len Local private key length */
52 /* local_public_key_ptr Pointer to local public key */
53 /* local_public_key_len Remote public key length */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* status Completion status */
58 /* */
59 /* CALLS */
60 /* */
61 /* None */
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 /* resulting in version 6.1 */
74 /* */
75 /**************************************************************************/
_nx_crypto_ecdh_key_pair_import(NX_CRYPTO_ECDH * ecdh_ptr,NX_CRYPTO_EC * curve,UCHAR * local_private_key_ptr,ULONG local_private_key_len,UCHAR * local_public_key_ptr,ULONG local_public_key_len)76 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_key_pair_import(NX_CRYPTO_ECDH *ecdh_ptr,
77 NX_CRYPTO_EC *curve,
78 UCHAR *local_private_key_ptr,
79 ULONG local_private_key_len,
80 UCHAR *local_public_key_ptr,
81 ULONG local_public_key_len)
82 {
83 UINT public_key_len;
84 NX_CRYPTO_HUGE_NUMBER private_key;
85
86 NX_CRYPTO_PARAMETER_NOT_USED(local_public_key_ptr);
87
88 if (local_private_key_len > sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer))
89 {
90 return(NX_CRYPTO_SIZE_ERROR);
91 }
92
93 public_key_len = 1 + (((curve -> nx_crypto_ec_bits + 7) >> 3) << 1);
94 if (local_public_key_len > public_key_len)
95 {
96 return(NX_CRYPTO_SIZE_ERROR);
97 }
98
99 /* Assign the desired key size based on the chosen elliptic curve. */
100 ecdh_ptr -> nx_crypto_ecdh_key_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size;
101
102 /* Clear the private key buffer. */
103 NX_CRYPTO_MEMSET(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, 0,
104 sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer));
105
106 /* Setup the private key. */
107 private_key.nx_crypto_huge_number_data = ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
108 private_key.nx_crypto_huge_buffer_size = sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer);
109 _nx_crypto_huge_number_setup(&private_key, local_private_key_ptr, local_private_key_len);
110
111 return(NX_CRYPTO_SUCCESS);
112 }
113
114 /**************************************************************************/
115 /* */
116 /* FUNCTION RELEASE */
117 /* */
118 /* _nx_crypto_ecdh_private_key_export PORTABLE C */
119 /* 6.1 */
120 /* AUTHOR */
121 /* */
122 /* Timothy Stapko, Microsoft Corporation */
123 /* */
124 /* DESCRIPTION */
125 /* */
126 /* This function exports the local private key in Elliptic-curve */
127 /* Diffie-Hellman context. */
128 /* */
129 /* INPUT */
130 /* */
131 /* ecdh_ptr ECDH context */
132 /* local_private_key_ptr Pointer to local private key */
133 /* local_private_key_len Local private key length */
134 /* actual_local_private_key_len Pointer to private key length */
135 /* */
136 /* OUTPUT */
137 /* */
138 /* status Completion status */
139 /* */
140 /* CALLS */
141 /* */
142 /* None */
143 /* */
144 /* CALLED BY */
145 /* */
146 /* Application Code */
147 /* */
148 /* RELEASE HISTORY */
149 /* */
150 /* DATE NAME DESCRIPTION */
151 /* */
152 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
153 /* 09-30-2020 Timothy Stapko Modified comment(s), */
154 /* resulting in version 6.1 */
155 /* */
156 /**************************************************************************/
_nx_crypto_ecdh_private_key_export(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * local_private_key_ptr,ULONG local_private_key_len,ULONG * actual_local_private_key_len)157 UINT _nx_crypto_ecdh_private_key_export(NX_CRYPTO_ECDH *ecdh_ptr,
158 UCHAR *local_private_key_ptr,
159 ULONG local_private_key_len,
160 ULONG *actual_local_private_key_len)
161 {
162 UINT status;
163 UINT key_size;
164 UINT clen;
165 NX_CRYPTO_EC *curve;
166 NX_CRYPTO_HUGE_NUMBER private_key;
167
168 /* Make sure the key size was assigned before we do anything else. Generally, this means
169 _nx_crypto_ecdh_setup was not called to set up the NX_CRYPTO_ECDH structure prior to this call. */
170 if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size)
171 {
172 return(NX_CRYPTO_SIZE_ERROR);
173 }
174
175 curve = ecdh_ptr -> nx_crypto_ecdh_curve;
176
177 /* Figure out the sizes of our keys and buffers. */
178 key_size = ecdh_ptr -> nx_crypto_ecdh_key_size;
179
180 /* Check to make sure the buffer is large enough to hold the private key. */
181 clen = (curve -> nx_crypto_ec_bits + 7) >> 3;
182 if (local_private_key_len < clen)
183 {
184 return(NX_CRYPTO_SIZE_ERROR);
185 }
186
187 /* Private key buffer - note that no scratch is required for the private key, but we set it in case
188 it is needed in the future. */
189 private_key.nx_crypto_huge_number_data = (HN_UBASE *)ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
190 private_key.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT;
191 private_key.nx_crypto_huge_buffer_size = key_size;
192 private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
193
194 /* Copy the private key into the return buffer. */
195 status = _nx_crypto_huge_number_extract_fixed_size(&private_key,
196 local_private_key_ptr, clen);
197 *actual_local_private_key_len = clen;
198
199 return(status);
200 }
201
202 /**************************************************************************/
203 /* */
204 /* FUNCTION RELEASE */
205 /* */
206 /* _nx_crypto_ecdh_setup PORTABLE C */
207 /* 6.1 */
208 /* AUTHOR */
209 /* */
210 /* Timothy Stapko, Microsoft Corporation */
211 /* */
212 /* DESCRIPTION */
213 /* */
214 /* This function sets up a Elliptic-curve Diffie-Hellman context by */
215 /* generating a local key pair. */
216 /* */
217 /* INPUT */
218 /* */
219 /* ecdh_ptr ECDH context */
220 /* share_secret_key_ptr Shared secret buffer pointer */
221 /* share_secret_key_len_ptr Length of shared secret */
222 /* local_public_key_ptr Pointer to local public key */
223 /* local_public_key_len Remote public key length */
224 /* scratch_buf_ptr Pointer to scratch buffer, */
225 /* which cannot be smaller */
226 /* than 6 times of the key */
227 /* size (in bytes). This */
228 /* scratch buffer can be */
229 /* reused after this function */
230 /* returns. */
231 /* */
232 /* OUTPUT */
233 /* */
234 /* status Completion status */
235 /* */
236 /* CALLS */
237 /* */
238 /* _nx_crypto_ec_key_pair_generation_extra */
239 /* Generate EC Key Pair */
240 /* */
241 /* CALLED BY */
242 /* */
243 /* Application Code */
244 /* */
245 /* RELEASE HISTORY */
246 /* */
247 /* DATE NAME DESCRIPTION */
248 /* */
249 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
250 /* 09-30-2020 Timothy Stapko Modified comment(s), */
251 /* resulting in version 6.1 */
252 /* */
253 /**************************************************************************/
_nx_crypto_ecdh_setup(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * local_public_key_ptr,ULONG local_public_key_len,ULONG * actual_local_public_key_len,NX_CRYPTO_EC * curve,HN_UBASE * scratch_buf_ptr)254 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_setup(NX_CRYPTO_ECDH *ecdh_ptr,
255 UCHAR *local_public_key_ptr,
256 ULONG local_public_key_len,
257 ULONG *actual_local_public_key_len,
258 NX_CRYPTO_EC *curve,
259 HN_UBASE *scratch_buf_ptr)
260 {
261 UINT public_key_len;
262 /* Actual huge numbers used in calculations */
263 NX_CRYPTO_HUGE_NUMBER private_key;
264 NX_CRYPTO_EC_POINT public_key;
265
266 public_key_len = 1 + (((curve -> nx_crypto_ec_bits + 7) >> 3) << 1);
267 if (local_public_key_len < public_key_len)
268 {
269 return(NX_CRYPTO_SIZE_ERROR);
270 }
271
272 ecdh_ptr -> nx_crypto_ecdh_curve = curve;
273
274 /* Assign the desired key size based on the chosen elliptic curve. */
275 ecdh_ptr -> nx_crypto_ecdh_key_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size;
276
277 /* Public key buffer (and scratch). */
278 NX_CRYPTO_EC_POINT_INITIALIZE(&public_key, NX_CRYPTO_EC_POINT_AFFINE, scratch_buf_ptr,
279 ecdh_ptr -> nx_crypto_ecdh_key_size);
280
281 /* Private key buffer - note that no scratch is required for the private key. */
282 private_key.nx_crypto_huge_number_data = ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
283 private_key.nx_crypto_huge_number_size = ecdh_ptr -> nx_crypto_ecdh_key_size >> HN_SIZE_SHIFT;
284 private_key.nx_crypto_huge_buffer_size = sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer);
285 private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
286
287 /* Clear the private key buffer. */
288 NX_CRYPTO_MEMSET(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, 0,
289 sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer));
290
291 /* Generate Key Pair. */
292 _nx_crypto_ec_key_pair_generation_extra(curve, &curve -> nx_crypto_ec_g, &private_key,
293 &public_key, scratch_buf_ptr);
294
295 /* Copy the public key into the return buffer. */
296 _nx_crypto_ec_point_extract_uncompressed(curve, &public_key, local_public_key_ptr,
297 local_public_key_len, &public_key_len);
298
299 if (public_key_len == 0)
300 {
301 return(NX_CRYPTO_SIZE_ERROR);
302 }
303 *actual_local_public_key_len = public_key_len;
304
305 return(NX_CRYPTO_SUCCESS);
306 }
307
308
309 /**************************************************************************/
310 /* */
311 /* FUNCTION RELEASE */
312 /* */
313 /* _nx_crypto_ecdh_compute_secret PORTABLE C */
314 /* 6.1 */
315 /* AUTHOR */
316 /* */
317 /* Timothy Stapko, Microsoft Corporation */
318 /* */
319 /* DESCRIPTION */
320 /* */
321 /* This function computes the Elliptic-curve Diffie-Hellman shared */
322 /* secret using an existing Elliptic-curve Diffie-Hellman context */
323 /* and a public key received from a remote entity. */
324 /* */
325 /* INPUT */
326 /* */
327 /* ecdh_ptr ECDH context */
328 /* share_secret_key_ptr Shared secret buffer pointer */
329 /* share_secret_key_len_ptr Length of shared secret */
330 /* remote_public_key Pointer to remote public key */
331 /* remote_public_key_len Remote public key length */
332 /* scratch_buf_ptr Pointer to scratch buffer, */
333 /* which cannot be smaller */
334 /* than 8 times of the key */
335 /* size (in bytes). This */
336 /* scratch buffer can be */
337 /* reused after this function */
338 /* returns. */
339 /* */
340 /* OUTPUT */
341 /* */
342 /* status Completion status */
343 /* */
344 /* CALLS */
345 /* */
346 /* _nx_crypto_huge_number_extract Extract huge number */
347 /* _nx_crypto_huge_number_setup Setup huge number */
348 /* */
349 /* CALLED BY */
350 /* */
351 /* Application Code */
352 /* */
353 /* RELEASE HISTORY */
354 /* */
355 /* DATE NAME DESCRIPTION */
356 /* */
357 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
358 /* 09-30-2020 Timothy Stapko Modified comment(s), and */
359 /* added public key validation,*/
360 /* resulting in version 6.1 */
361 /* */
362 /**************************************************************************/
_nx_crypto_ecdh_compute_secret(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * share_secret_key_ptr,ULONG share_secret_key_len_ptr,ULONG * actual_share_secret_key_len,UCHAR * remote_public_key,ULONG remote_public_key_len,HN_UBASE * scratch_buf_ptr)363 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_compute_secret(NX_CRYPTO_ECDH *ecdh_ptr,
364 UCHAR *share_secret_key_ptr,
365 ULONG share_secret_key_len_ptr,
366 ULONG *actual_share_secret_key_len,
367 UCHAR *remote_public_key,
368 ULONG remote_public_key_len,
369 HN_UBASE *scratch_buf_ptr)
370 {
371 UINT status;
372 UINT key_size;
373 UINT clen;
374 NX_CRYPTO_EC *curve;
375 /* Actual huge numbers used in calculations */
376 NX_CRYPTO_HUGE_NUMBER private_key;
377 NX_CRYPTO_EC_POINT public_key, shared_secret;
378
379 /* Make sure the key size was assigned before we do anything else. Generally, this means
380 _nx_crypto_ecdh_setup was not called to set up the NX_CRYPTO_ECDH structure prior to this call. */
381 if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size)
382 {
383 return(NX_CRYPTO_SIZE_ERROR);
384 }
385
386 curve = ecdh_ptr -> nx_crypto_ecdh_curve;
387
388 /* Figure out the sizes of our keys and buffers. We need 4X the key size for our buffer space. */
389 key_size = ecdh_ptr -> nx_crypto_ecdh_key_size;
390
391 /* Make sure the remote public key is small enough to fit into the huge number buffer. */
392 if (remote_public_key_len > 1 + 2 * key_size)
393 {
394 return(NX_CRYPTO_SIZE_ERROR);
395 }
396
397 /* Check to make sure the buffer is large enough to hold the shared secret key. */
398 clen = (curve -> nx_crypto_ec_bits + 7) >> 3;
399 if (share_secret_key_len_ptr < clen)
400 {
401 return(NX_CRYPTO_SIZE_ERROR);
402 }
403
404 NX_CRYPTO_EC_POINT_INITIALIZE(&public_key, NX_CRYPTO_EC_POINT_AFFINE, scratch_buf_ptr, key_size);
405 NX_CRYPTO_EC_POINT_INITIALIZE(&shared_secret, NX_CRYPTO_EC_POINT_AFFINE, scratch_buf_ptr, key_size);
406
407
408 /* Copy the remote public key from the caller's buffer. */
409 status = _nx_crypto_ec_point_setup(&public_key, remote_public_key, remote_public_key_len);
410 if (status != NX_CRYPTO_SUCCESS)
411 {
412 return(status);
413 }
414
415 #ifndef NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION
416 status = _nx_crypto_ec_validate_public_key(&public_key, curve, NX_CRYPTO_TRUE, scratch_buf_ptr);
417 if (status != NX_CRYPTO_SUCCESS)
418 {
419 return(status);
420 }
421 #endif /* NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION */
422
423 /* Private key buffer - note that no scratch is required for the private key, but we set it in case
424 it is needed in the future. */
425 private_key.nx_crypto_huge_number_data = (HN_UBASE *)ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
426 private_key.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT;
427 private_key.nx_crypto_huge_buffer_size = key_size;
428 private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
429
430 /* Finally, generate shared secret from the remote public key, our generated private key, and the curve.
431 The actual calculation is "shared_secret = private_key * public_key". */
432 curve -> nx_crypto_ec_multiple(curve, &public_key, &private_key, &shared_secret, scratch_buf_ptr);
433
434 /* The public key size is simply the key size for this group. */
435
436 /* Copy the shared secret into the return buffer. */
437 status = _nx_crypto_huge_number_extract_fixed_size(&shared_secret.nx_crypto_ec_point_x,
438 share_secret_key_ptr, clen);
439 *actual_share_secret_key_len = clen;
440
441 return(status);
442 }
443
444
445 /**************************************************************************/
446 /* */
447 /* FUNCTION RELEASE */
448 /* */
449 /* _nx_crypto_method_ecdh_init PORTABLE C */
450 /* 6.3.0 */
451 /* AUTHOR */
452 /* */
453 /* Timothy Stapko, Microsoft Corporation */
454 /* */
455 /* DESCRIPTION */
456 /* */
457 /* This function is the common crypto method init callback for */
458 /* Microsoft supported ECDH cryptographic algorithm. */
459 /* */
460 /* INPUT */
461 /* */
462 /* method Pointer to crypto method */
463 /* key Pointer to key */
464 /* key_size_in_bits Length of key size in bits */
465 /* handler Returned crypto handler */
466 /* crypto_metadata Metadata area */
467 /* crypto_metadata_size Size of the metadata area */
468 /* */
469 /* OUTPUT */
470 /* */
471 /* status Completion status */
472 /* */
473 /* CALLS */
474 /* */
475 /* None */
476 /* */
477 /* CALLED BY */
478 /* */
479 /* Application Code */
480 /* */
481 /* RELEASE HISTORY */
482 /* */
483 /* DATE NAME DESCRIPTION */
484 /* */
485 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
486 /* 09-30-2020 Timothy Stapko Modified comment(s), */
487 /* resulting in version 6.1 */
488 /* 10-31-2023 Yanwu Cai Modified comment(s), */
489 /* resulting in version 6.3.0 */
490 /* */
491 /**************************************************************************/
_nx_crypto_method_ecdh_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)492 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_init(struct NX_CRYPTO_METHOD_STRUCT *method,
493 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
494 VOID **handle,
495 VOID *crypto_metadata,
496 ULONG crypto_metadata_size)
497 {
498
499 NX_CRYPTO_STATE_CHECK
500
501 NX_CRYPTO_PARAMETER_NOT_USED(key);
502 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
503 NX_CRYPTO_PARAMETER_NOT_USED(handle);
504
505 if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
506 {
507 return(NX_CRYPTO_PTR_ERROR);
508 }
509
510 /* Verify the metadata address is 4-byte aligned. */
511 if((((ULONG)crypto_metadata) & 0x3) != 0)
512 {
513 return(NX_CRYPTO_PTR_ERROR);
514 }
515
516 if(crypto_metadata_size < sizeof(NX_CRYPTO_ECDH))
517 {
518 return(NX_CRYPTO_PTR_ERROR);
519 }
520
521 return(NX_CRYPTO_SUCCESS);
522 }
523
524
525 /**************************************************************************/
526 /* */
527 /* FUNCTION RELEASE */
528 /* */
529 /* _nx_crypto_method_ecdh_cleanup PORTABLE C */
530 /* 6.1 */
531 /* AUTHOR */
532 /* */
533 /* Timothy Stapko, Microsoft Corporation */
534 /* */
535 /* DESCRIPTION */
536 /* */
537 /* This function cleans up the crypto metadata. */
538 /* */
539 /* INPUT */
540 /* */
541 /* crypto_metadata Crypto metadata */
542 /* */
543 /* OUTPUT */
544 /* */
545 /* status Completion status */
546 /* */
547 /* CALLS */
548 /* */
549 /* NX_CRYPTO_MEMSET Set the memory */
550 /* */
551 /* CALLED BY */
552 /* */
553 /* Application Code */
554 /* */
555 /* RELEASE HISTORY */
556 /* */
557 /* DATE NAME DESCRIPTION */
558 /* */
559 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
560 /* 09-30-2020 Timothy Stapko Modified comment(s), */
561 /* resulting in version 6.1 */
562 /* */
563 /**************************************************************************/
_nx_crypto_method_ecdh_cleanup(VOID * crypto_metadata)564 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_cleanup(VOID *crypto_metadata)
565 {
566
567 NX_CRYPTO_STATE_CHECK
568
569 #ifdef NX_SECURE_KEY_CLEAR
570 if (!crypto_metadata)
571 return (NX_CRYPTO_SUCCESS);
572
573 /* Clean up the crypto metadata. */
574 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_ECDH));
575 #else
576 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
577 #endif/* NX_SECURE_KEY_CLEAR */
578
579 return(NX_CRYPTO_SUCCESS);
580 }
581
582
583 /**************************************************************************/
584 /* */
585 /* FUNCTION RELEASE */
586 /* */
587 /* _nx_crypto_method_ecdh_operation PORTABLE C */
588 /* 6.3.0 */
589 /* AUTHOR */
590 /* */
591 /* Timothy Stapko, Microsoft Corporation */
592 /* */
593 /* DESCRIPTION */
594 /* */
595 /* This function performs an ECDH operation. */
596 /* */
597 /* INPUT */
598 /* */
599 /* op ECDH operation */
600 /* handle Crypto handle */
601 /* method Cryption Method Object */
602 /* key Encryption Key */
603 /* key_size_in_bits Key size in bits */
604 /* input Input data */
605 /* input_length_in_byte Input data size */
606 /* iv_ptr Initial vector */
607 /* output Output buffer */
608 /* output_length_in_byte Output buffer size */
609 /* crypto_metadata Metadata area */
610 /* crypto_metadata_size Metadata area size */
611 /* packet_ptr Pointer to packet */
612 /* nx_crypto_hw_process_callback Callback function pointer */
613 /* */
614 /* OUTPUT */
615 /* */
616 /* status Completion status */
617 /* */
618 /* CALLS */
619 /* */
620 /* _nx_crypto_ecdh_setup Setup local key pair */
621 /* _nx_crypto_ecdh_compute_secret Compute shared secret */
622 /* */
623 /* CALLED BY */
624 /* */
625 /* Application Code */
626 /* */
627 /* RELEASE HISTORY */
628 /* */
629 /* DATE NAME DESCRIPTION */
630 /* */
631 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
632 /* 09-30-2020 Timothy Stapko Modified comment(s), */
633 /* resulting in version 6.1 */
634 /* 10-31-2023 Yanwu Cai Modified comment(s), */
635 /* resulting in version 6.3.0 */
636 /* */
637 /**************************************************************************/
_nx_crypto_method_ecdh_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))638 NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_operation(UINT op,
639 VOID *handle,
640 struct NX_CRYPTO_METHOD_STRUCT *method,
641 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
642 UCHAR *input, ULONG input_length_in_byte,
643 UCHAR *iv_ptr,
644 UCHAR *output, ULONG output_length_in_byte,
645 VOID *crypto_metadata, ULONG crypto_metadata_size,
646 VOID *packet_ptr,
647 VOID (*nx_crypto_hw_process_callback)(VOID *, UINT))
648 {
649 NX_CRYPTO_ECDH *ecdh;
650 UINT status = NX_CRYPTO_SUCCESS;
651 NX_CRYPTO_EXTENDED_OUTPUT
652 *extended_output;
653
654 NX_CRYPTO_PARAMETER_NOT_USED(handle);
655 NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
656 NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte);
657 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
658 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
659
660 NX_CRYPTO_STATE_CHECK
661
662 /* Verify the metadata address is 4-byte aligned. */
663 if((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
664 {
665 return(NX_CRYPTO_PTR_ERROR);
666 }
667
668 if(crypto_metadata_size < sizeof(NX_CRYPTO_ECDH))
669 {
670 return(NX_CRYPTO_PTR_ERROR);
671 }
672
673 ecdh = (NX_CRYPTO_ECDH *)crypto_metadata;
674
675 if (op == NX_CRYPTO_EC_CURVE_SET)
676 {
677 /* Set curve to be used in the ECDH. */
678 status = ((NX_CRYPTO_METHOD *)input) -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET,
679 NX_CRYPTO_NULL,
680 (NX_CRYPTO_METHOD *)input,
681 NX_CRYPTO_NULL, 0,
682 NX_CRYPTO_NULL, 0,
683 NX_CRYPTO_NULL,
684 (UCHAR *)&ecdh -> nx_crypto_ecdh_curve,
685 sizeof(NX_CRYPTO_EC *),
686 NX_CRYPTO_NULL, 0,
687 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
688
689 }
690 else if (op == NX_CRYPTO_EC_KEY_PAIR_GENERATE)
691 {
692 if (ecdh -> nx_crypto_ecdh_curve == NX_CRYPTO_NULL)
693 {
694 return(NX_CRYPTO_PTR_ERROR);
695 }
696
697 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
698 status = _nx_crypto_ec_key_pair_stream_generate(ecdh -> nx_crypto_ecdh_curve,
699 extended_output -> nx_crypto_extended_output_data,
700 extended_output -> nx_crypto_extended_output_length_in_byte,
701 &extended_output -> nx_crypto_extended_output_actual_size,
702 ecdh -> nx_crypto_ecdh_scratch_buffer);
703 }
704 else if (op == NX_CRYPTO_DH_SETUP)
705 {
706 /* Setup local key pair. */
707 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
708 #ifdef NX_CRYPTO_ENABLE_CURVE25519_448
709 if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 ||
710 ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448)
711 {
712 status = _nx_crypto_ecdh_setup_x25519_448(ecdh,
713 extended_output -> nx_crypto_extended_output_data,
714 extended_output -> nx_crypto_extended_output_length_in_byte,
715 &extended_output -> nx_crypto_extended_output_actual_size,
716 ecdh -> nx_crypto_ecdh_curve,
717 ecdh -> nx_crypto_ecdh_scratch_buffer);
718 }
719 else
720 #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */
721 {
722 status = _nx_crypto_ecdh_setup(ecdh,
723 extended_output -> nx_crypto_extended_output_data,
724 extended_output -> nx_crypto_extended_output_length_in_byte,
725 &extended_output -> nx_crypto_extended_output_actual_size,
726 ecdh -> nx_crypto_ecdh_curve,
727 ecdh -> nx_crypto_ecdh_scratch_buffer);
728 }
729 }
730 else if (op == NX_CRYPTO_DH_KEY_PAIR_IMPORT)
731 {
732 if (key == NX_CRYPTO_NULL)
733 {
734 return(NX_CRYPTO_PTR_ERROR);
735 }
736
737 #ifdef NX_CRYPTO_ENABLE_CURVE25519_448
738 if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 ||
739 ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448)
740 {
741
742 /* Import local key pair. */
743 status = _nx_crypto_ecdh_key_pair_import_x25519_448(ecdh, ecdh -> nx_crypto_ecdh_curve,
744 key, (key_size_in_bits >> 3),
745 input, input_length_in_byte);
746 }
747 else
748 #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */
749 {
750
751 /* Import local key pair. */
752 status = _nx_crypto_ecdh_key_pair_import(ecdh, ecdh -> nx_crypto_ecdh_curve,
753 key, (key_size_in_bits >> 3),
754 input, input_length_in_byte);
755 }
756 }
757 else if (op == NX_CRYPTO_DH_PRIVATE_KEY_EXPORT)
758 {
759 /* Export local private key. */
760 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
761
762 #ifdef NX_CRYPTO_ENABLE_CURVE25519_448
763 if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 ||
764 ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448)
765 {
766 status = _nx_crypto_ecdh_private_key_export_x25519_448(ecdh,
767 extended_output -> nx_crypto_extended_output_data,
768 extended_output -> nx_crypto_extended_output_length_in_byte,
769 &extended_output -> nx_crypto_extended_output_actual_size);
770 }
771 else
772 #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */
773 {
774
775 status = _nx_crypto_ecdh_private_key_export(ecdh,
776 extended_output -> nx_crypto_extended_output_data,
777 extended_output -> nx_crypto_extended_output_length_in_byte,
778 &extended_output -> nx_crypto_extended_output_actual_size);
779 }
780 }
781 else if (op == NX_CRYPTO_DH_CALCULATE)
782 {
783 /* Compute shared secret. */
784 extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
785
786 #ifdef NX_CRYPTO_ENABLE_CURVE25519_448
787 if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 ||
788 ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448)
789 {
790
791 status = _nx_crypto_ecdh_compute_secret_x25519_448(ecdh,
792 extended_output -> nx_crypto_extended_output_data,
793 extended_output -> nx_crypto_extended_output_length_in_byte,
794 &extended_output -> nx_crypto_extended_output_actual_size,
795 input,
796 input_length_in_byte,
797 ecdh -> nx_crypto_ecdh_scratch_buffer);
798 }
799 else
800 #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */
801 {
802
803 status = _nx_crypto_ecdh_compute_secret(ecdh,
804 extended_output -> nx_crypto_extended_output_data,
805 extended_output -> nx_crypto_extended_output_length_in_byte,
806 &extended_output -> nx_crypto_extended_output_actual_size,
807 input,
808 input_length_in_byte,
809 ecdh -> nx_crypto_ecdh_scratch_buffer);
810 }
811 }
812 else
813 {
814 status = NX_CRYPTO_NOT_SUCCESSFUL;
815 }
816
817 return(status);
818 }
819
820 #ifdef NX_CRYPTO_ENABLE_CURVE25519_448
821
822 /**************************************************************************/
823 /* */
824 /* FUNCTION RELEASE */
825 /* */
826 /* _nx_crypto_ecdh_key_pair_import_x25519_448 PORTABLE C */
827 /* 6.1.11 */
828 /* AUTHOR */
829 /* */
830 /* Yuxin Zhou, Microsoft Corporation */
831 /* */
832 /* DESCRIPTION */
833 /* */
834 /* This function sets up a Elliptic-curve Diffie-Hellman context by */
835 /* importing a local key pair. */
836 /* */
837 /* INPUT */
838 /* */
839 /* ecdh_ptr ECDH context */
840 /* curve Elliptic Curve */
841 /* local_private_key_ptr Pointer to local private key */
842 /* local_private_key_len Local private key length */
843 /* local_public_key_ptr Pointer to local public key */
844 /* local_public_key_len Remote public key length */
845 /* */
846 /* OUTPUT */
847 /* */
848 /* status Completion status */
849 /* */
850 /* CALLS */
851 /* */
852 /* None */
853 /* */
854 /* CALLED BY */
855 /* */
856 /* _nx_crypto_method_ecdh_operation Perform ECDH operation */
857 /* */
858 /* RELEASE HISTORY */
859 /* */
860 /* DATE NAME DESCRIPTION */
861 /* */
862 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
863 /* */
864 /**************************************************************************/
_nx_crypto_ecdh_key_pair_import_x25519_448(NX_CRYPTO_ECDH * ecdh_ptr,NX_CRYPTO_EC * curve,UCHAR * local_private_key_ptr,ULONG local_private_key_len,UCHAR * local_public_key_ptr,ULONG local_public_key_len)865 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_key_pair_import_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr,
866 NX_CRYPTO_EC *curve,
867 UCHAR *local_private_key_ptr,
868 ULONG local_private_key_len,
869 UCHAR *local_public_key_ptr,
870 ULONG local_public_key_len)
871 {
872 UINT key_len;
873
874
875 NX_CRYPTO_PARAMETER_NOT_USED(local_public_key_ptr);
876
877 key_len = (curve -> nx_crypto_ec_bits + 7) >> 3;
878
879 if (local_private_key_len != key_len)
880 {
881 return(NX_CRYPTO_SIZE_ERROR);
882 }
883
884 if (local_public_key_len > key_len)
885 {
886 return(NX_CRYPTO_SIZE_ERROR);
887 }
888
889 /* Assign the desired key size based on the chosen elliptic curve. */
890 ecdh_ptr -> nx_crypto_ecdh_key_size = key_len;
891
892 /* Copy the private key buffer. */
893 NX_CRYPTO_MEMCPY(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, local_private_key_ptr, local_private_key_len); /* Use case of memcpy is verified. */
894
895 return(NX_CRYPTO_SUCCESS);
896 }
897
898 /**************************************************************************/
899 /* */
900 /* FUNCTION RELEASE */
901 /* */
902 /* _nx_crypto_ecdh_private_key_export_x25519_448 PORTABLE C */
903 /* 6.1.11 */
904 /* AUTHOR */
905 /* */
906 /* Yuxin Zhou, Microsoft Corporation */
907 /* */
908 /* DESCRIPTION */
909 /* */
910 /* This function exports the local private key in Elliptic-curve */
911 /* Diffie-Hellman context. */
912 /* */
913 /* INPUT */
914 /* */
915 /* ecdh_ptr ECDH context */
916 /* local_private_key_ptr Pointer to local private key */
917 /* local_private_key_len Local private key length */
918 /* actual_local_private_key_len Pointer to private key length */
919 /* */
920 /* OUTPUT */
921 /* */
922 /* status Completion status */
923 /* */
924 /* CALLS */
925 /* */
926 /* NX_CRYPTO_MEMCPY Copy the key */
927 /* */
928 /* CALLED BY */
929 /* */
930 /* _nx_crypto_method_ecdh_operation Perform ECDH operation */
931 /* */
932 /* RELEASE HISTORY */
933 /* */
934 /* DATE NAME DESCRIPTION */
935 /* */
936 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
937 /* */
938 /**************************************************************************/
_nx_crypto_ecdh_private_key_export_x25519_448(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * local_private_key_ptr,ULONG local_private_key_len,ULONG * actual_local_private_key_len)939 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_private_key_export_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr,
940 UCHAR *local_private_key_ptr,
941 ULONG local_private_key_len,
942 ULONG *actual_local_private_key_len)
943 {
944 UINT clen;
945 NX_CRYPTO_EC *curve;
946
947 /* Make sure the key size was assigned before we do anything else. */
948 if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size)
949 {
950 return(NX_CRYPTO_SIZE_ERROR);
951 }
952
953 curve = ecdh_ptr -> nx_crypto_ecdh_curve;
954
955 /* Check to make sure the buffer is large enough to hold the private key. */
956 clen = (curve -> nx_crypto_ec_bits + 7) >> 3;
957 if (local_private_key_len < clen)
958 {
959 return(NX_CRYPTO_SIZE_ERROR);
960 }
961
962 /* Copy the private key buffer. */
963 NX_CRYPTO_MEMCPY(local_private_key_ptr, ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, clen); /* Use case of memcpy is verified. */
964
965 *actual_local_private_key_len = clen;
966
967 return(NX_CRYPTO_SUCCESS);
968 }
969
970 /**************************************************************************/
971 /* */
972 /* FUNCTION RELEASE */
973 /* */
974 /* _nx_crypto_ecdh_setup_x25519_448 PORTABLE C */
975 /* 6.1.12 */
976 /* AUTHOR */
977 /* */
978 /* Yuxin Zhou, Microsoft Corporation */
979 /* */
980 /* DESCRIPTION */
981 /* */
982 /* This function sets up a Elliptic-curve Diffie-Hellman context by */
983 /* generating a local key pair. */
984 /* */
985 /* INPUT */
986 /* */
987 /* ecdh_ptr ECDH context */
988 /* share_secret_key_ptr Shared secret buffer pointer */
989 /* share_secret_key_len_ptr Length of shared secret */
990 /* local_public_key_ptr Pointer to local public key */
991 /* local_public_key_len Remote public key length */
992 /* scratch_buf_ptr Pointer to scratch buffer, */
993 /* which cannot be smaller */
994 /* than 6 times of the key */
995 /* size (in bytes). This */
996 /* scratch buffer can be */
997 /* reused after this function */
998 /* returns. */
999 /* */
1000 /* OUTPUT */
1001 /* */
1002 /* status Completion status */
1003 /* */
1004 /* CALLS */
1005 /* */
1006 /* _nx_crypto_ec_key_pair_generation_x25519 */
1007 /* Generate EC Key Pair */
1008 /* _nx_crypto_ec_extract_fixed_size_le Extract huge number */
1009 /* */
1010 /* CALLED BY */
1011 /* */
1012 /* _nx_crypto_method_ecdh_operation Perform ECDH operation */
1013 /* */
1014 /* RELEASE HISTORY */
1015 /* */
1016 /* DATE NAME DESCRIPTION */
1017 /* */
1018 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
1019 /* 07-29-2022 Yuxin Zhou Modified comment(s), */
1020 /* added x448 curve, */
1021 /* resulting in version 6.1.12 */
1022 /* */
1023 /**************************************************************************/
_nx_crypto_ecdh_setup_x25519_448(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * local_public_key_ptr,ULONG local_public_key_len,ULONG * actual_local_public_key_len,NX_CRYPTO_EC * curve,HN_UBASE * scratch_buf_ptr)1024 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_setup_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr,
1025 UCHAR *local_public_key_ptr,
1026 ULONG local_public_key_len,
1027 ULONG *actual_local_public_key_len,
1028 NX_CRYPTO_EC *curve,
1029 HN_UBASE *scratch_buf_ptr)
1030 {
1031 UINT key_len;
1032 UINT status;
1033 NX_CRYPTO_HUGE_NUMBER private_key;
1034 NX_CRYPTO_EC_POINT public_key;
1035
1036 key_len = (curve -> nx_crypto_ec_bits + 7) >> 3;
1037 if (local_public_key_len < key_len)
1038 {
1039 return(NX_CRYPTO_SIZE_ERROR);
1040 }
1041
1042 ecdh_ptr -> nx_crypto_ecdh_curve = curve;
1043
1044 /* Assign the desired key size based on the chosen elliptic curve. */
1045 ecdh_ptr -> nx_crypto_ecdh_key_size = key_len;
1046
1047 /* Public key buffer (and scratch). */
1048 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&public_key.nx_crypto_ec_point_x, scratch_buf_ptr, key_len);
1049
1050 /* Private key buffer - note that no scratch is required for the private key. */
1051 private_key.nx_crypto_huge_number_data = ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
1052 private_key.nx_crypto_huge_number_size = ecdh_ptr -> nx_crypto_ecdh_key_size >> HN_SIZE_SHIFT;
1053 private_key.nx_crypto_huge_buffer_size = sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer);
1054 private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
1055
1056 /* Clear the private key buffer. */
1057 NX_CRYPTO_MEMSET(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, 0,
1058 sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer));
1059
1060 /* Generate Key Pair. */
1061 status = _nx_crypto_ec_key_pair_generation_x25519_448(curve, &curve -> nx_crypto_ec_g, &private_key,
1062 &public_key, scratch_buf_ptr);
1063 if (status)
1064 {
1065 return(status);
1066 }
1067
1068 /* Copy the public key into the return buffer. */
1069 status = _nx_crypto_ec_extract_fixed_size_le(&public_key.nx_crypto_ec_point_x,
1070 local_public_key_ptr, key_len);
1071 if (status)
1072 {
1073 return(status);
1074 }
1075
1076 *actual_local_public_key_len = key_len;
1077
1078 return(NX_CRYPTO_SUCCESS);
1079 }
1080
1081
1082 /**************************************************************************/
1083 /* */
1084 /* FUNCTION RELEASE */
1085 /* */
1086 /* _nx_crypto_ecdh_compute_secret_x25519_448 PORTABLE C */
1087 /* 6.1.11 */
1088 /* AUTHOR */
1089 /* */
1090 /* Yuxin Zhou, Microsoft Corporation */
1091 /* */
1092 /* DESCRIPTION */
1093 /* */
1094 /* This function computes the Elliptic-curve Diffie-Hellman shared */
1095 /* secret using an existing Elliptic-curve Diffie-Hellman context */
1096 /* and a public key received from a remote entity. */
1097 /* */
1098 /* INPUT */
1099 /* */
1100 /* ecdh_ptr ECDH context */
1101 /* share_secret_key_ptr Shared secret buffer pointer */
1102 /* share_secret_key_len_ptr Length of shared secret */
1103 /* remote_public_key Pointer to remote public key */
1104 /* remote_public_key_len Remote public key length */
1105 /* scratch_buf_ptr Pointer to scratch buffer, */
1106 /* */
1107 /* OUTPUT */
1108 /* */
1109 /* status Completion status */
1110 /* */
1111 /* CALLS */
1112 /* */
1113 /* _nx_crypto_ec_extract_fixed_size_le Extract huge number */
1114 /* [nx_crypto_ec_multiple] Perform multiplication for EC */
1115 /* _nx_crypto_huge_number_is_zero Check for all-zero value */
1116 /* */
1117 /* CALLED BY */
1118 /* */
1119 /* _nx_crypto_method_ecdh_operation Perform ECDH operation */
1120 /* */
1121 /* RELEASE HISTORY */
1122 /* */
1123 /* DATE NAME DESCRIPTION */
1124 /* */
1125 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
1126 /* */
1127 /**************************************************************************/
_nx_crypto_ecdh_compute_secret_x25519_448(NX_CRYPTO_ECDH * ecdh_ptr,UCHAR * share_secret_key_ptr,ULONG share_secret_key_len_ptr,ULONG * actual_share_secret_key_len,UCHAR * remote_public_key,ULONG remote_public_key_len,HN_UBASE * scratch_buf_ptr)1128 NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_compute_secret_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr,
1129 UCHAR *share_secret_key_ptr,
1130 ULONG share_secret_key_len_ptr,
1131 ULONG *actual_share_secret_key_len,
1132 UCHAR *remote_public_key,
1133 ULONG remote_public_key_len,
1134 HN_UBASE *scratch_buf_ptr)
1135 {
1136 UINT status;
1137 UINT key_size;
1138 UINT clen;
1139 NX_CRYPTO_EC *curve;
1140 /* Actual huge numbers used in calculations */
1141 NX_CRYPTO_HUGE_NUMBER private_key;
1142 NX_CRYPTO_EC_POINT public_key, shared_secret;
1143
1144 /* Make sure the key size was assigned before we do anything else. */
1145 if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size)
1146 {
1147 return(NX_CRYPTO_SIZE_ERROR);
1148 }
1149
1150 curve = ecdh_ptr -> nx_crypto_ecdh_curve;
1151
1152 /* Figure out the sizes of our keys and buffers. */
1153 key_size = ecdh_ptr -> nx_crypto_ecdh_key_size;
1154
1155 /* Make sure the remote public key size is correct. */
1156 if (remote_public_key_len != key_size)
1157 {
1158 return(NX_CRYPTO_SIZE_ERROR);
1159 }
1160
1161 /* Check to make sure the buffer is large enough to hold the shared secret key. */
1162 clen = (curve -> nx_crypto_ec_bits + 7) >> 3;
1163 if (share_secret_key_len_ptr < clen)
1164 {
1165 return(NX_CRYPTO_SIZE_ERROR);
1166 }
1167
1168 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&public_key.nx_crypto_ec_point_x, scratch_buf_ptr, key_size);
1169 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&shared_secret.nx_crypto_ec_point_x, scratch_buf_ptr, key_size);
1170
1171 /* Copy the remote public key from the caller's buffer. */
1172 NX_CRYPTO_MEMCPY(public_key.nx_crypto_ec_point_x.nx_crypto_huge_number_data, remote_public_key, remote_public_key_len); /* Use case of memcpy is verified. */
1173 public_key.nx_crypto_ec_point_x.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT;
1174
1175 /* Private key buffer */
1176 private_key.nx_crypto_huge_number_data = (HN_UBASE*)ecdh_ptr -> nx_crypto_ecdh_private_key_buffer;
1177 private_key.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT;
1178 private_key.nx_crypto_huge_buffer_size = key_size;
1179 private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE;
1180
1181 /* Finally, generate shared secret from the remote public key, our generated private key, and the curve.
1182 The actual calculation is "shared_secret = private_key * public_key". */
1183 curve -> nx_crypto_ec_multiple(curve, &public_key, &private_key, &shared_secret, scratch_buf_ptr);
1184
1185 /* Check for the all-zero value results. */
1186 if (_nx_crypto_huge_number_is_zero(&shared_secret.nx_crypto_ec_point_x))
1187 {
1188 return(NX_CRYPTO_NOT_SUCCESSFUL);
1189 }
1190
1191 /* Copy the shared secret into the return buffer. */
1192 status = _nx_crypto_ec_extract_fixed_size_le(&shared_secret.nx_crypto_ec_point_x,
1193 share_secret_key_ptr, clen);
1194
1195 /* The public key size is simply the key size for this group. */
1196 *actual_share_secret_key_len = clen;
1197
1198 return(status);
1199 }
1200
1201 #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */
1202