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