1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Crypto Component */
16 /** */
17 /** HMAC Mode */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #include "nx_crypto_hmac.h"
23
24 /**************************************************************************/
25 /* */
26 /* FUNCTION RELEASE */
27 /* */
28 /* _nx_crypto_hmac PORTABLE C */
29 /* 6.1 */
30 /* */
31 /* AUTHOR */
32 /* */
33 /* Timothy Stapko, Microsoft Corporation */
34 /* */
35 /* DESCRIPTION */
36 /* */
37 /* This function calculates the HMAC. */
38 /* */
39 /* INPUT */
40 /* */
41 /* hmac_metadata pointer to HMAC metadata */
42 /* input_ptr input byte stream */
43 /* input_length input byte stream length */
44 /* key_ptr key stream */
45 /* key_length key stream length */
46 /* digest_ptr generated crypto digest */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* status Completion status */
51 /* */
52 /* CALLS */
53 /* */
54 /* _nx_crypto_hmac_initialize Perform HMAC initialization */
55 /* _nx_crypto_hmac_update Perform HMAC update */
56 /* _nx_crypto_hmac_digest_calculate Calculate HMAC digest */
57 /* */
58 /* CALLED BY */
59 /* */
60 /* Application Code */
61 /* _nx_crypto_method_hmac_md5_operation Handle HMAC-MD5 operation */
62 /* _nx_crypto_method_hmac_sha1_operation Handle HMAC-SHA1 operation */
63 /* _nx_crypto_method_hmac_sha256_operation Handle HMAC-SHA256 operation*/
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
70 /* 09-30-2020 Timothy Stapko Modified comment(s), */
71 /* resulting in version 6.1 */
72 /* */
73 /**************************************************************************/
_nx_crypto_hmac(NX_CRYPTO_HMAC * hmac_metadata,UCHAR * input_ptr,UINT input_length,UCHAR * key_ptr,UINT key_length,UCHAR * digest_ptr,UINT digest_length)74 NX_CRYPTO_KEEP UINT _nx_crypto_hmac(NX_CRYPTO_HMAC *hmac_metadata,
75 UCHAR *input_ptr, UINT input_length,
76 UCHAR *key_ptr, UINT key_length,
77 UCHAR *digest_ptr, UINT digest_length)
78 {
79
80 /* Initialize, update and calculate. */
81 _nx_crypto_hmac_initialize(hmac_metadata, key_ptr, key_length);
82 _nx_crypto_hmac_update(hmac_metadata, input_ptr, input_length);
83 _nx_crypto_hmac_digest_calculate(hmac_metadata, digest_ptr, digest_length);
84
85 /* Return success. */
86 return(NX_CRYPTO_SUCCESS);
87 }
88
89
90 /**************************************************************************/
91 /* */
92 /* FUNCTION RELEASE */
93 /* */
94 /* _nx_crypto_hmac_initialize PORTABLE C */
95 /* 6.1 */
96 /* */
97 /* AUTHOR */
98 /* */
99 /* Timothy Stapko, Microsoft Corporation */
100 /* */
101 /* DESCRIPTION */
102 /* */
103 /* This function performs HMAC initialization. */
104 /* */
105 /* INPUT */
106 /* */
107 /* hmac_metadata pointer to HMAC metadata */
108 /* key_ptr key stream */
109 /* key_length key stream length */
110 /* */
111 /* OUTPUT */
112 /* */
113 /* status Completion status */
114 /* */
115 /* CALLS */
116 /* */
117 /* [crypto_digest_calculate] Calculate crypto digest */
118 /* [crypto_initialize] Perform crypto initialization */
119 /* [crypto_update] Perform crypto update */
120 /* */
121 /* CALLED BY */
122 /* */
123 /* Application Code */
124 /* _nx_crypto_hmac Calculate the HMAC */
125 /* _nx_crypto_method_hmac_md5_operation Handle HMAC-MD5 operation */
126 /* _nx_crypto_method_hmac_sha1_operation Handle HMAC-SHA1 operation */
127 /* _nx_crypto_method_hmac_sha256_operation Handle HMAC-SHA256 operation*/
128 /* _nx_crypto_method_hmac_sha512_operation Handle HMAC-SHA512 operation*/
129 /* */
130 /* RELEASE HISTORY */
131 /* */
132 /* DATE NAME DESCRIPTION */
133 /* */
134 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
135 /* 09-30-2020 Timothy Stapko Modified comment(s), */
136 /* verified memcpy use cases, */
137 /* resulting in version 6.1 */
138 /* */
139 /**************************************************************************/
_nx_crypto_hmac_initialize(NX_CRYPTO_HMAC * hmac_metadata,UCHAR * key_ptr,UINT key_length)140 NX_CRYPTO_KEEP UINT _nx_crypto_hmac_initialize(NX_CRYPTO_HMAC *hmac_metadata, UCHAR *key_ptr, UINT key_length)
141 {
142 UCHAR temp_key[128];
143 UINT i;
144
145 /* If key is longer than block size, reset it to key=CRYPTO(key). */
146 if (key_length > hmac_metadata -> block_size)
147 {
148
149 hmac_metadata -> crypto_initialize(hmac_metadata -> context, hmac_metadata -> algorithm);
150
151 hmac_metadata -> crypto_update(hmac_metadata -> context, key_ptr, key_length);
152
153 hmac_metadata -> crypto_digest_calculate(hmac_metadata -> context, temp_key, hmac_metadata -> algorithm);
154
155 key_ptr = temp_key;
156
157 key_length = hmac_metadata -> output_length;
158 }
159
160 hmac_metadata -> crypto_initialize(hmac_metadata -> context, hmac_metadata -> algorithm);
161
162 /* The HMAC_CRYPTO transform looks like:
163
164 CRYPTO(K XOR opad, CRYPTO(K XOR ipad, text))
165
166 where K is an n byte key,
167 ipad is the byte 0x36 repeated block_size times,
168 opad is the byte 0x5c repeated block_size times,
169 and text is the data being protected. */
170
171 NX_CRYPTO_MEMSET(hmac_metadata -> k_ipad, 0, hmac_metadata -> block_size);
172
173 NX_CRYPTO_MEMSET(hmac_metadata -> k_opad, 0, hmac_metadata -> block_size);
174
175 NX_CRYPTO_MEMCPY(hmac_metadata -> k_ipad, key_ptr, key_length); /* Use case of memcpy is verified. */
176
177 NX_CRYPTO_MEMCPY(hmac_metadata -> k_opad, key_ptr, key_length); /* Use case of memcpy is verified. */
178
179
180 /* XOR key with ipad and opad values. */
181 for (i = 0; i < hmac_metadata -> block_size; i++)
182 {
183 hmac_metadata -> k_ipad[i] ^= 0x36;
184 hmac_metadata -> k_opad[i] ^= 0x5c;
185 }
186
187 /* Kick off the inner hash with our padded key. */
188 hmac_metadata -> crypto_update(hmac_metadata -> context, hmac_metadata -> k_ipad, hmac_metadata -> block_size);
189
190 #ifdef NX_SECURE_KEY_CLEAR
191 NX_CRYPTO_MEMSET(temp_key, 0, sizeof(temp_key));
192 #endif /* NX_SECURE_KEY_CLEAR */
193
194 /* Return success. */
195 return(NX_CRYPTO_SUCCESS);
196 }
197
198
199 /**************************************************************************/
200 /* */
201 /* FUNCTION RELEASE */
202 /* */
203 /* _nx_crypto_hmac_update PORTABLE C */
204 /* 6.1 */
205 /* */
206 /* AUTHOR */
207 /* */
208 /* Timothy Stapko, Microsoft Corporation */
209 /* */
210 /* DESCRIPTION */
211 /* */
212 /* This function performs HMAC update. */
213 /* */
214 /* INPUT */
215 /* */
216 /* hmac_metadata pointer to HMAC metadata */
217 /* input_ptr input byte stream */
218 /* input_length input byte stream length */
219 /* */
220 /* OUTPUT */
221 /* */
222 /* status Completion status */
223 /* */
224 /* CALLS */
225 /* */
226 /* [crypto_update] Perform crypto update */
227 /* */
228 /* CALLED BY */
229 /* */
230 /* Application Code */
231 /* _nx_crypto_hmac Calculate the HMAC */
232 /* */
233 /* RELEASE HISTORY */
234 /* */
235 /* DATE NAME DESCRIPTION */
236 /* */
237 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
238 /* 09-30-2020 Timothy Stapko Modified comment(s), */
239 /* resulting in version 6.1 */
240 /* */
241 /**************************************************************************/
_nx_crypto_hmac_update(NX_CRYPTO_HMAC * hmac_metadata,UCHAR * input_ptr,UINT input_length)242 NX_CRYPTO_KEEP UINT _nx_crypto_hmac_update(NX_CRYPTO_HMAC *hmac_metadata, UCHAR *input_ptr, UINT input_length)
243 {
244
245 /* Update inner CRYPTO. */
246 hmac_metadata -> crypto_update(hmac_metadata -> context, input_ptr, input_length);
247
248 /* Return success. */
249 return(NX_CRYPTO_SUCCESS);
250 }
251
252
253 /**************************************************************************/
254 /* */
255 /* FUNCTION RELEASE */
256 /* */
257 /* _nx_crypto_hmac_digest_calculate PORTABLE C */
258 /* 6.1 */
259 /* */
260 /* AUTHOR */
261 /* */
262 /* Timothy Stapko, Microsoft Corporation */
263 /* */
264 /* DESCRIPTION */
265 /* */
266 /* This function performs HMAC digest calculation. */
267 /* */
268 /* INPUT */
269 /* */
270 /* hmac_metadata pointer to HMAC metadata */
271 /* digest_ptr generated crypto digest */
272 /* */
273 /* OUTPUT */
274 /* */
275 /* status Completion status */
276 /* */
277 /* CALLS */
278 /* */
279 /* [crypto_digest_calculate] Calculate crypto digest */
280 /* [crypto_initialize] Perform crypto initialization */
281 /* [crypto_update] Perform crypto update */
282 /* */
283 /* CALLED BY */
284 /* */
285 /* Application Code */
286 /* _nx_crypto_hmac Calculate the HMAC */
287 /* */
288 /* RELEASE HISTORY */
289 /* */
290 /* DATE NAME DESCRIPTION */
291 /* */
292 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
293 /* 09-30-2020 Timothy Stapko Modified comment(s), */
294 /* verified memcpy use cases, */
295 /* resulting in version 6.1 */
296 /* */
297 /**************************************************************************/
_nx_crypto_hmac_digest_calculate(NX_CRYPTO_HMAC * hmac_metadata,UCHAR * digest_ptr,UINT digest_length)298 NX_CRYPTO_KEEP UINT _nx_crypto_hmac_digest_calculate(NX_CRYPTO_HMAC *hmac_metadata, UCHAR *digest_ptr, UINT digest_length)
299 {
300 UCHAR icv_ptr[64];
301
302 /* Perform outer CRYPTO. */
303
304 hmac_metadata -> crypto_digest_calculate(hmac_metadata -> context, icv_ptr, hmac_metadata -> algorithm);
305
306 hmac_metadata -> crypto_initialize(hmac_metadata -> context, hmac_metadata -> algorithm);
307
308 hmac_metadata -> crypto_update(hmac_metadata -> context, hmac_metadata -> k_opad, hmac_metadata -> block_size);
309
310 hmac_metadata -> crypto_update(hmac_metadata -> context, icv_ptr, hmac_metadata -> output_length);
311
312 hmac_metadata -> crypto_digest_calculate(hmac_metadata -> context, icv_ptr, hmac_metadata -> algorithm);
313
314 NX_CRYPTO_MEMCPY(digest_ptr, icv_ptr, (digest_length > hmac_metadata -> output_length ? hmac_metadata -> output_length : digest_length)); /* Use case of memcpy is verified. */
315
316 #ifdef NX_SECURE_KEY_CLEAR
317 NX_CRYPTO_MEMSET(icv_ptr, 0, sizeof(icv_ptr));
318 #endif /* NX_SECURE_KEY_CLEAR */
319
320 /* Return success. */
321 return(NX_CRYPTO_SUCCESS);
322 }
323
324
325 /**************************************************************************/
326 /* */
327 /* FUNCTION RELEASE */
328 /* */
329 /* _nx_crypto_hmac_metadata_set PORTABLE C */
330 /* 6.1 */
331 /* */
332 /* AUTHOR */
333 /* */
334 /* Timothy Stapko, Microsoft Corporation */
335 /* */
336 /* DESCRIPTION */
337 /* */
338 /* This function sets HMAC metadata. */
339 /* */
340 /* INPUT */
341 /* */
342 /* hmac_metadata pointer to HMAC metadata */
343 /* context crypto context */
344 /* k_ipad ipad key */
345 /* k_opad opad key */
346 /* algorithm algorithm */
347 /* block_size block size */
348 /* output_length output length */
349 /* crypto_intitialize initializtion function */
350 /* crypto_update update function */
351 /* crypto_digest_calculate digest calculation function */
352 /* */
353 /* OUTPUT */
354 /* */
355 /* None */
356 /* */
357 /* CALLS */
358 /* */
359 /* None */
360 /* */
361 /* CALLED BY */
362 /* */
363 /* Application Code */
364 /* _nx_crypto_method_hmac_md5_operation Handle HMAC-MD5 operation */
365 /* _nx_crypto_method_hmac_sha1_operation Handle HMAC-SHA1 operation */
366 /* _nx_crypto_method_hmac_sha256_operation Handle HMAC-SHA256 operation*/
367 /* _nx_crypto_method_hmac_sha512_operation Handle HMAC-SHA512 operation*/
368 /* */
369 /* RELEASE HISTORY */
370 /* */
371 /* DATE NAME DESCRIPTION */
372 /* */
373 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
374 /* 09-30-2020 Timothy Stapko Modified comment(s), */
375 /* resulting in version 6.1 */
376 /* */
377 /**************************************************************************/
_nx_crypto_hmac_metadata_set(NX_CRYPTO_HMAC * hmac_metadata,VOID * context,UINT algorithm,UINT block_size,UINT output_length,UINT (* crypto_initialize)(VOID *,UINT),UINT (* crypto_update)(VOID *,UCHAR *,UINT),UINT (* crypto_digest_calculate)(VOID *,UCHAR *,UINT))378 NX_CRYPTO_KEEP VOID _nx_crypto_hmac_metadata_set(NX_CRYPTO_HMAC *hmac_metadata,
379 VOID *context,
380 UINT algorithm, UINT block_size, UINT output_length,
381 UINT (*crypto_initialize)(VOID *, UINT),
382 UINT (*crypto_update)(VOID *, UCHAR *, UINT),
383 UINT (*crypto_digest_calculate)(VOID *, UCHAR *, UINT))
384 {
385
386 hmac_metadata -> context = context;
387 hmac_metadata -> algorithm = algorithm;
388 hmac_metadata -> block_size = block_size;
389 hmac_metadata -> output_length = output_length;
390 hmac_metadata -> crypto_initialize = crypto_initialize;
391 hmac_metadata -> crypto_update = crypto_update;
392 hmac_metadata -> crypto_digest_calculate = crypto_digest_calculate;
393 }
394
395 /**************************************************************************/
396 /* */
397 /* FUNCTION RELEASE */
398 /* */
399 /* _nx_crypto_hmac_hash_initialize PORTABLE C */
400 /* 6.1 */
401 /* */
402 /* AUTHOR */
403 /* */
404 /* Timothy Stapko, Microsoft Corporation */
405 /* */
406 /* DESCRIPTION */
407 /* */
408 /* This function is a build-in wrappers for hash initialization. */
409 /* */
410 /* INPUT */
411 /* */
412 /* context Crypto context */
413 /* algorithm Hash algorithm */
414 /* */
415 /* OUTPUT */
416 /* */
417 /* status Completion status */
418 /* */
419 /* CALLS */
420 /* */
421 /* None */
422 /* */
423 /* CALLED BY */
424 /* */
425 /* None */
426 /* */
427 /* RELEASE HISTORY */
428 /* */
429 /* DATE NAME DESCRIPTION */
430 /* */
431 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
432 /* 09-30-2020 Timothy Stapko Modified comment(s), */
433 /* resulting in version 6.1 */
434 /* */
435 /**************************************************************************/
_nx_crypto_hmac_hash_initialize(VOID * context,UINT algorithm)436 UINT _nx_crypto_hmac_hash_initialize(VOID *context, UINT algorithm)
437 {
438 NX_CRYPTO_HMAC *hmac;
439 NX_CRYPTO_METHOD *hash;
440 UINT metadata_size;
441 UINT status;
442
443 NX_CRYPTO_PARAMETER_NOT_USED(algorithm);
444
445 /* Get the HMAC context. */
446 hmac = (NX_CRYPTO_HMAC*)context;
447
448 /* Get the hash method and it's metadata. */
449 hash = hmac->hash_method;
450 metadata_size = hash->nx_crypto_metadata_area_size;
451
452 status = hash->nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
453 NX_CRYPTO_NULL,
454 hash,
455 NX_CRYPTO_NULL,
456 0,
457 NX_CRYPTO_NULL,
458 0,
459 NX_CRYPTO_NULL,
460 NX_CRYPTO_NULL,
461 0,
462 hmac->hash_context,
463 metadata_size,
464 NX_CRYPTO_NULL,
465 NX_CRYPTO_NULL);
466
467
468 return(status);
469 }
470
471
472 /**************************************************************************/
473 /* */
474 /* FUNCTION RELEASE */
475 /* */
476 /* _nx_crypto_hmac_hash_update PORTABLE C */
477 /* 6.1 */
478 /* */
479 /* AUTHOR */
480 /* */
481 /* Timothy Stapko, Microsoft Corporation */
482 /* */
483 /* DESCRIPTION */
484 /* */
485 /* This function is a build-in wrappers for hash data update. */
486 /* */
487 /* INPUT */
488 /* */
489 /* context Crypto context */
490 /* input Input Stream */
491 /* input_length Input Stream Length */
492 /* */
493 /* OUTPUT */
494 /* */
495 /* status Completion status */
496 /* */
497 /* CALLS */
498 /* */
499 /* None */
500 /* */
501 /* CALLED BY */
502 /* */
503 /* None */
504 /* */
505 /* RELEASE HISTORY */
506 /* */
507 /* DATE NAME DESCRIPTION */
508 /* */
509 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
510 /* 09-30-2020 Timothy Stapko Modified comment(s), */
511 /* resulting in version 6.1 */
512 /* */
513 /**************************************************************************/
_nx_crypto_hmac_hash_update(VOID * context,UCHAR * input,UINT input_length)514 UINT _nx_crypto_hmac_hash_update(VOID *context, UCHAR *input, UINT input_length)
515 {
516 NX_CRYPTO_HMAC *hmac;
517 NX_CRYPTO_METHOD *hash;
518 UINT metadata_size;
519 UINT status;
520
521 /* Get the HMAC context. */
522 hmac = (NX_CRYPTO_HMAC*)context;
523
524 /* Get the hash method and it's metadata. */
525 hash = hmac->hash_method;
526 metadata_size = hash->nx_crypto_metadata_area_size;
527
528 /* Perform an update using the generic crypto API. */
529 status = hash->nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
530 NX_CRYPTO_NULL,
531 hash,
532 NX_CRYPTO_NULL,
533 0,
534 input,
535 input_length,
536 NX_CRYPTO_NULL,
537 NX_CRYPTO_NULL,
538 0,
539 hmac->hash_context,
540 metadata_size,
541 NX_CRYPTO_NULL,
542 NX_CRYPTO_NULL);
543
544 return(status);
545 }
546
547
548 /**************************************************************************/
549 /* */
550 /* FUNCTION RELEASE */
551 /* */
552 /* _nx_crypto_hmac_hash_digest_calculate PORTABLE C */
553 /* 6.1 */
554 /* */
555 /* AUTHOR */
556 /* */
557 /* Timothy Stapko, Microsoft Corporation */
558 /* */
559 /* DESCRIPTION */
560 /* */
561 /* This function is a build-in wrappers for hash digest calculate. */
562 /* */
563 /* INPUT */
564 /* */
565 /* context Crypto context */
566 /* digest Digest for output */
567 /* algorithm Hash algorithm */
568 /* */
569 /* OUTPUT */
570 /* */
571 /* status Completion status */
572 /* */
573 /* CALLS */
574 /* */
575 /* None */
576 /* */
577 /* CALLED BY */
578 /* */
579 /* None */
580 /* */
581 /* RELEASE HISTORY */
582 /* */
583 /* DATE NAME DESCRIPTION */
584 /* */
585 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
586 /* 09-30-2020 Timothy Stapko Modified comment(s), */
587 /* resulting in version 6.1 */
588 /* */
589 /**************************************************************************/
_nx_crypto_hmac_hash_digest_calculate(VOID * context,UCHAR * digest,UINT algorithm)590 UINT _nx_crypto_hmac_hash_digest_calculate(VOID *context, UCHAR *digest, UINT algorithm)
591 {
592 NX_CRYPTO_HMAC *hmac;
593 NX_CRYPTO_METHOD *hash;
594 UINT metadata_size;
595 UINT status;
596
597 NX_CRYPTO_PARAMETER_NOT_USED(algorithm);
598
599 /* Get the HMAC context. */
600 hmac = (NX_CRYPTO_HMAC*)context;
601
602 /* Get the hash method and it's metadata. */
603 hash = hmac->hash_method;
604 metadata_size = hash->nx_crypto_metadata_area_size;
605
606 /* Perform a digest calculation using the generic crypto API. */
607 status = hash->nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
608 NX_CRYPTO_NULL,
609 hash,
610 NX_CRYPTO_NULL,
611 0,
612 NX_CRYPTO_NULL,
613 0,
614 NX_CRYPTO_NULL,
615 digest,
616 (hash->nx_crypto_ICV_size_in_bits >> 3),
617 hmac->hash_context,
618 metadata_size,
619 NX_CRYPTO_NULL,
620 NX_CRYPTO_NULL);
621
622 return(status);
623 }
624
625
626 /**************************************************************************/
627 /* */
628 /* FUNCTION RELEASE */
629 /* */
630 /* _nx_crypto_method_hmac_init PORTABLE C */
631 /* 6.3.0 */
632 /* AUTHOR */
633 /* */
634 /* Timothy Stapko, Microsoft Corporation */
635 /* */
636 /* DESCRIPTION */
637 /* */
638 /* This function is the common crypto method initialization routine */
639 /* for the Microsoft implementation of the HMAC cryptographic */
640 /* algorithm. */
641 /* */
642 /* INPUT */
643 /* */
644 /* method Pointer to crypto method */
645 /* key Pointer to key */
646 /* key_size_in_bits Length of key size in bits */
647 /* handler Returned crypto handler */
648 /* crypto_metadata Metadata area */
649 /* crypto_metadata_size Size of the metadata area */
650 /* */
651 /* OUTPUT */
652 /* */
653 /* status Completion status */
654 /* */
655 /* CALLS */
656 /* */
657 /* None */
658 /* */
659 /* CALLED BY */
660 /* */
661 /* Application Code */
662 /* */
663 /* RELEASE HISTORY */
664 /* */
665 /* DATE NAME DESCRIPTION */
666 /* */
667 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
668 /* 09-30-2020 Timothy Stapko Modified comment(s), */
669 /* resulting in version 6.1 */
670 /* 10-31-2023 Yanwu Cai Modified comment(s), */
671 /* resulting in version 6.3.0 */
672 /* */
673 /**************************************************************************/
_nx_crypto_method_hmac_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)674 NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_init(struct NX_CRYPTO_METHOD_STRUCT *method,
675 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
676 VOID **handle,
677 VOID *crypto_metadata,
678 ULONG crypto_metadata_size)
679 {
680 /* NX_CRYPTO_HMAC *hmac;*/
681
682 NX_CRYPTO_PARAMETER_NOT_USED(handle);
683 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
684
685 NX_CRYPTO_STATE_CHECK
686
687 if ((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
688 {
689 return(NX_CRYPTO_PTR_ERROR);
690 }
691
692 /* Verify the metadata address is 4-byte aligned. */
693 if((((ULONG)crypto_metadata) & 0x3) != 0)
694 {
695 return(NX_CRYPTO_PTR_ERROR);
696 }
697
698 if(crypto_metadata_size < sizeof(NX_CRYPTO_HMAC))
699 {
700 return(NX_CRYPTO_PTR_ERROR);
701 }
702
703 #if 0
704 hmac = (NX_CRYPTO_HMAC *)crypto_metadata;
705
706 /* Set the method for later. */
707 hmac->hash_method = method;
708 #endif
709
710 return(NX_CRYPTO_SUCCESS);
711 }
712
713
714 /**************************************************************************/
715 /* */
716 /* FUNCTION RELEASE */
717 /* */
718 /* _nx_crypto_method_hmac_cleanup PORTABLE C */
719 /* 6.1 */
720 /* AUTHOR */
721 /* */
722 /* Timothy Stapko, Microsoft Corporation */
723 /* */
724 /* DESCRIPTION */
725 /* */
726 /* This function cleans up the crypto metadata for the HMAC operation. */
727 /* */
728 /* INPUT */
729 /* */
730 /* crypto_metadata Crypto metadata */
731 /* */
732 /* OUTPUT */
733 /* */
734 /* status Completion status */
735 /* */
736 /* CALLS */
737 /* */
738 /* NX_CRYPTO_MEMSET Set the memory */
739 /* */
740 /* CALLED BY */
741 /* */
742 /* Application Code */
743 /* */
744 /* RELEASE HISTORY */
745 /* */
746 /* DATE NAME DESCRIPTION */
747 /* */
748 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
749 /* 09-30-2020 Timothy Stapko Modified comment(s), */
750 /* resulting in version 6.1 */
751 /* */
752 /**************************************************************************/
_nx_crypto_method_hmac_cleanup(VOID * crypto_metadata)753 NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_cleanup(VOID *crypto_metadata)
754 {
755
756 NX_CRYPTO_STATE_CHECK
757
758 #ifdef NX_SECURE_KEY_CLEAR
759 if (!crypto_metadata)
760 return (NX_CRYPTO_SUCCESS);
761
762 /* Clean up the crypto metadata. */
763 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_HMAC));
764 #else
765 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
766 #endif/* NX_SECURE_KEY_CLEAR */
767
768 return(NX_CRYPTO_SUCCESS);
769 }
770
771
772
773
774
775 /**************************************************************************/
776 /* */
777 /* FUNCTION RELEASE */
778 /* */
779 /* _nx_crypto_method_hmac_operation PORTABLE C */
780 /* 6.3.0 */
781 /* */
782 /* AUTHOR */
783 /* */
784 /* Timothy Stapko, Microsoft Corporation */
785 /* */
786 /* DESCRIPTION */
787 /* */
788 /* This function is the generic operation for HMAC. HMAC does not care */
789 /* what hash is used as long as the hash size is known. Therefore, this*/
790 /* method may be used with an arbitrary hash routine as long as the */
791 /* hash has an NX_CRYPTO_METHOD instance properly filled out. */
792 /* */
793 /* INPUT */
794 /* */
795 /* hmac_metadata pointer to HMAC metadata */
796 /* context crypto context */
797 /* k_ipad ipad key */
798 /* k_opad opad key */
799 /* algorithm algorithm */
800 /* block_size block size */
801 /* output_length output length */
802 /* crypto_intitialize initializtion function */
803 /* crypto_update update function */
804 /* crypto_digest_calculate digest calculation function */
805 /* */
806 /* OUTPUT */
807 /* */
808 /* None */
809 /* */
810 /* CALLS */
811 /* */
812 /* None */
813 /* */
814 /* CALLED BY */
815 /* */
816 /* Application Code */
817 /* */
818 /* RELEASE HISTORY */
819 /* */
820 /* DATE NAME DESCRIPTION */
821 /* */
822 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
823 /* 09-30-2020 Timothy Stapko Modified comment(s), */
824 /* resulting in version 6.1 */
825 /* 10-31-2023 Yanwu Cai Modified comment(s), */
826 /* resulting in version 6.3.0 */
827 /* */
828 /**************************************************************************/
_nx_crypto_method_hmac_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 * packet_ptr,UINT status))829 NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
830 VOID *handle, /* Crypto handler */
831 struct NX_CRYPTO_METHOD_STRUCT *method,
832 UCHAR *key,
833 NX_CRYPTO_KEY_SIZE key_size_in_bits,
834 UCHAR *input,
835 ULONG input_length_in_byte,
836 UCHAR *iv_ptr,
837 UCHAR *output,
838 ULONG output_length_in_byte,
839 VOID *crypto_metadata,
840 ULONG crypto_metadata_size,
841 VOID *packet_ptr,
842 VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
843 {
844 NX_CRYPTO_HMAC *hmac;
845 UINT status;
846
847 NX_CRYPTO_PARAMETER_NOT_USED(handle);
848 NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
849 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
850 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
851
852 NX_CRYPTO_STATE_CHECK
853
854 /* Verify the metadata address is 4-byte aligned. */
855 if((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
856 {
857 return(NX_CRYPTO_PTR_ERROR);
858 }
859
860 if(crypto_metadata_size < sizeof(NX_CRYPTO_HMAC))
861 {
862 return(NX_CRYPTO_PTR_ERROR);
863 }
864
865 /* Get our control block for HKDF. */
866 hmac = (NX_CRYPTO_HMAC *)(crypto_metadata);
867
868 /* Get the metadata for our hash routine. */
869 hmac->context = hmac;
870 hmac->hash_context = ((UCHAR*)(crypto_metadata)) + sizeof(NX_CRYPTO_HMAC);
871
872 status = NX_CRYPTO_SUCCESS;
873 switch (op)
874 {
875 case NX_CRYPTO_HMAC_SET_HASH:
876 hmac->hash_method = method;
877
878 /* Set up the HMAC metadata using the HMAC context for the hash context - this is because our built-in routines
879 * (_nx_crypto_hmac_hash_initialize/update/digest_calculate) need the full HMAC context, unlike when HMAC routines
880 * are built around HMAC (as opposed to when HMAC is used as a hash wrapper). */
881 _nx_crypto_hmac_metadata_set(hmac, hmac,
882 method->nx_crypto_algorithm, method->nx_crypto_block_size_in_bytes, method->nx_crypto_ICV_size_in_bits >> 3,
883 _nx_crypto_hmac_hash_initialize,
884 _nx_crypto_hmac_hash_update,
885 _nx_crypto_hmac_hash_digest_calculate);
886
887 /* Initialize the hash routine. */
888 status = method->nx_crypto_init(method, NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, hmac->hash_context, method->nx_crypto_metadata_area_size);
889 break;
890
891 case NX_CRYPTO_HASH_INITIALIZE:
892 /* Initialize the hash method. */
893 if(key == NX_CRYPTO_NULL)
894 {
895 return(NX_CRYPTO_PTR_ERROR);
896 }
897
898 status = _nx_crypto_hmac_initialize(hmac, key, key_size_in_bits >> 3);
899 break;
900
901 case NX_CRYPTO_HASH_UPDATE:
902 status = _nx_crypto_hmac_update(hmac, input, input_length_in_byte);
903 break;
904
905 case NX_CRYPTO_HASH_CALCULATE:
906 if(output_length_in_byte == 0)
907 {
908 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
909 }
910 status = _nx_crypto_hmac_digest_calculate(hmac, output,
911 (output_length_in_byte > (ULONG)((hmac-> hash_method -> nx_crypto_ICV_size_in_bits) >> 3) ?
912 ((hmac-> hash_method -> nx_crypto_ICV_size_in_bits) >> 3) : output_length_in_byte));
913 break;
914
915 default:
916 /* Do entire HMAC operation in one pass (init, update, calculate). */
917 if(key == NX_CRYPTO_NULL)
918 {
919 return(NX_CRYPTO_PTR_ERROR);
920 }
921
922 if(output_length_in_byte == 0)
923 {
924 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
925 }
926 _nx_crypto_hmac(hmac, input, input_length_in_byte, key, (key_size_in_bits >> 3), output,
927 (output_length_in_byte > (ULONG)((hmac -> hash_method -> nx_crypto_ICV_size_in_bits) >> 3) ?
928 ((hmac -> hash_method -> nx_crypto_ICV_size_in_bits) >> 3) : output_length_in_byte));
929 break;
930 }
931
932 return(status);
933
934
935
936 }
937
938