]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecCryptIo.c
MdeModulePkg/StatusCodeHandlerRuntimeDxe: make global variable static
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecCryptIo.c
1 /** @file
2 Common interfaces to call Security library.
3
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "IpSecCryptIo.h"
11 //
12 // The informations for the supported Encrypt/Decrpt Alogrithm.
13 //
14 GLOBAL_REMOVE_IF_UNREFERENCED ENCRYPT_ALGORITHM mIpsecEncryptAlgorithmList[IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE] = {
15 {IKE_EALG_NULL, 0, 0, 1, NULL, NULL, NULL, NULL},
16 {IKE_EALG_NONE, 0, 0, 1, NULL, NULL, NULL, NULL},
17 {IKE_EALG_3DESCBC, 24, 8, 8, TdesGetContextSize, TdesInit, TdesCbcEncrypt, TdesCbcDecrypt},
18 {IKE_EALG_AESCBC, 16, 16, 16, AesGetContextSize, AesInit, AesCbcEncrypt, AesCbcDecrypt}
19 };
20
21 //
22 // The informations for the supported Authentication algorithm
23 //
24 GLOBAL_REMOVE_IF_UNREFERENCED AUTH_ALGORITHM mIpsecAuthAlgorithmList[IPSEC_AUTH_ALGORITHM_LIST_SIZE] = {
25 {IKE_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
26 {IKE_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
27 {IKE_AALG_SHA1HMAC, 20, 12, 64, HmacSha1GetContextSize, HmacSha1Init, HmacSha1Update, HmacSha1Final}
28 };
29
30 //
31 // The information for the supported Hash aglorithm
32 //
33 GLOBAL_REMOVE_IF_UNREFERENCED HASH_ALGORITHM mIpsecHashAlgorithmList[IPSEC_HASH_ALGORITHM_LIST_SIZE] = {
34 {IKE_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
35 {IKE_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
36 {IKE_AALG_SHA1HMAC, 20, 12, 64, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final}
37 };
38
39 BOOLEAN mInitialRandomSeed = FALSE;
40
41 /**
42 Get the block size of specified encryption algorithm.
43
44 @param[in] AlgorithmId The encryption algorithm ID.
45
46 @return The value of block size.
47
48 **/
49 UINTN
50 IpSecGetEncryptBlockSize (
51 IN UINT8 AlgorithmId
52 )
53 {
54 UINT8 Index;
55
56 for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
57 if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
58 return mIpsecEncryptAlgorithmList[Index].BlockSize;
59 }
60 }
61
62 return (UINTN) -1;
63 }
64
65 /**
66 Get the key length of the specified encryption algorithm.
67
68 @param[in] AlgorithmId The encryption algorithm ID.
69
70 @return The value of key length.
71
72 **/
73 UINTN
74 IpSecGetEncryptKeyLength (
75 IN UINT8 AlgorithmId
76 )
77 {
78 UINT8 Index;
79
80 for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
81 if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
82 return mIpsecEncryptAlgorithmList[Index].KeyLength;
83 }
84 }
85
86 return (UINTN) -1;
87 }
88
89 /**
90 Get the IV size of the specified encryption algorithm.
91
92 @param[in] AlgorithmId The encryption algorithm ID.
93
94 @return The value of IV size.
95
96 **/
97 UINTN
98 IpSecGetEncryptIvLength (
99 IN UINT8 AlgorithmId
100 )
101 {
102 UINT8 Index;
103
104 for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
105 if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
106 return mIpsecEncryptAlgorithmList[Index].IvLength;
107 }
108 }
109
110 return (UINTN) -1;
111 }
112
113 /**
114 Get the HMAC digest length by the specified Algorithm ID.
115
116 @param[in] AlgorithmId The specified Alogrithm ID.
117
118 @return The digest length of the specified Authentication Algorithm ID.
119
120 **/
121 UINTN
122 IpSecGetHmacDigestLength (
123 IN UINT8 AlgorithmId
124 )
125 {
126 UINT8 Index;
127
128 for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
129 if (mIpsecAuthAlgorithmList[Index].AlgorithmId == AlgorithmId) {
130 //
131 // Return the Digest Length of the Algorithm.
132 //
133 return mIpsecAuthAlgorithmList[Index].DigestLength;
134 }
135 }
136
137 return 0;
138 }
139
140 /**
141 Get the ICV size of the specified Authenticaion algorithm.
142
143 @param[in] AlgorithmId The Authentication algorithm ID.
144
145 @return The value of ICV size.
146
147 **/
148 UINTN
149 IpSecGetIcvLength (
150 IN UINT8 AlgorithmId
151 )
152 {
153 UINT8 Index;
154
155 for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
156 if (AlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
157 return mIpsecAuthAlgorithmList[Index].IcvLength;
158 }
159 }
160
161 return (UINTN) -1;
162 }
163
164 /**
165 Generate a random data for IV. If the IvSize is zero, not needed to create
166 IV and return EFI_SUCCESS.
167
168 @param[in] IvBuffer The pointer of the IV buffer.
169 @param[in] IvSize The IV size in bytes.
170
171 @retval EFI_SUCCESS Create a random data for IV.
172
173 **/
174 EFI_STATUS
175 IpSecGenerateIv (
176 IN UINT8 *IvBuffer,
177 IN UINTN IvSize
178 )
179 {
180 if (IvSize != 0) {
181 return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize);
182 }
183
184 return EFI_SUCCESS;
185 }
186
187 /**
188 Get index of the specified encryption algorithm from the mIpsecEncryptAlgorithmList.
189
190 @param[in] AlgorithmId The encryption algorithm ID.
191
192 @return the index.
193
194 **/
195 UINTN
196 IpSecGetIndexFromEncList (
197 IN UINT8 AlgorithmId
198 )
199 {
200 UINT8 Index;
201
202 for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
203 if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
204 return Index;
205 }
206 }
207
208 return (UINTN) -1;
209 }
210
211 /**
212 Get index of the specified encryption algorithm from the mIpsecAuthAlgorithmList.
213
214 @param[in] AlgorithmId The encryption algorithm ID.
215
216 @return the index.
217
218 **/
219 UINTN
220 IpSecGetIndexFromAuthList (
221 IN UINT8 AlgorithmId
222 )
223 {
224 UINT8 Index;
225
226 for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
227 if (AlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
228 //
229 // The BlockSize is same with IvSize.
230 //
231 return Index;
232 }
233 }
234
235 return (UINTN) -1;
236 }
237
238 /**
239 Encrypt the buffer.
240
241 This function calls relevant encryption interface from CryptoLib according to
242 the input algorithm ID. The InData should be multiple of block size. This function
243 doesn't perform the padding. If it has the Ivec data, the length of it should be
244 same with the block size. The block size is different from the different algorithm.
245
246 @param[in] AlgorithmId The Algorithm identification defined in RFC.
247 @param[in] Key Pointer to the buffer containing encrypting key.
248 @param[in] KeyBits The length of the key in bits.
249 @param[in] Ivec Point to the buffer containing the Initialization
250 Vector (IV) data.
251 @param[in] InData Point to the buffer containing the data to be
252 encrypted.
253 @param[in] InDataLength The length of InData in Bytes.
254 @param[out] OutData Point to the buffer that receives the encryption
255 output.
256
257 @retval EFI_UNSUPPORTED The input Algorithm is not supported.
258 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
259 @retval EFI_SUCCESS The operation completed successfully.
260
261 **/
262 EFI_STATUS
263 IpSecCryptoIoEncrypt (
264 IN CONST UINT8 AlgorithmId,
265 IN CONST UINT8 *Key,
266 IN CONST UINTN KeyBits,
267 IN CONST UINT8 *Ivec, OPTIONAL
268 IN UINT8 *InData,
269 IN UINTN InDataLength,
270 OUT UINT8 *OutData
271 )
272 {
273 UINTN Index;
274 UINTN ContextSize;
275 UINT8 *Context;
276 EFI_STATUS Status;
277
278 Status = EFI_UNSUPPORTED;
279
280 switch (AlgorithmId) {
281
282 case IKE_EALG_NULL:
283 case IKE_EALG_NONE:
284 CopyMem (OutData, InData, InDataLength);
285 return EFI_SUCCESS;
286
287 case IKE_EALG_3DESCBC:
288 case IKE_EALG_AESCBC:
289 Index = IpSecGetIndexFromEncList (AlgorithmId);
290 if (Index == -1) {
291 return Status;
292 }
293 //
294 // Get Context Size
295 //
296 ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize ();
297 Context = AllocateZeroPool (ContextSize);
298
299 if (Context == NULL) {
300 return EFI_OUT_OF_RESOURCES;
301 }
302 //
303 // Initiate Context
304 //
305 if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {
306 if (mIpsecEncryptAlgorithmList[Index].CipherEncrypt (Context, InData, InDataLength, Ivec, OutData)) {
307 Status = EFI_SUCCESS;
308 }
309 }
310 break;
311
312 default:
313 return Status;
314
315 }
316
317 if (Context != NULL) {
318 FreePool (Context);
319 }
320
321 return Status;
322 }
323
324 /**
325 Decrypts the buffer.
326
327 This function calls relevant Decryption interface from CryptoLib according to
328 the input algorithm ID. The InData should be multiple of block size. This function
329 doesn't perform the padding. If it has the Ivec data, the length of it should be
330 same with the block size. The block size is different from the different algorithm.
331
332 @param[in] AlgorithmId The Algorithm identification defined in RFC.
333 @param[in] Key Pointer to the buffer containing encrypting key.
334 @param[in] KeyBits The length of the key in bits.
335 @param[in] Ivec Point to the buffer containing the Initialization
336 Vector (IV) data.
337 @param[in] InData Point to the buffer containing the data to be
338 decrypted.
339 @param[in] InDataLength The length of InData in Bytes.
340 @param[out] OutData Pointer to the buffer that receives the decryption
341 output.
342
343 @retval EFI_UNSUPPORTED The input Algorithm is not supported.
344 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
345 @retval EFI_SUCCESS The operation completed successfully.
346
347 **/
348 EFI_STATUS
349 IpSecCryptoIoDecrypt (
350 IN CONST UINT8 AlgorithmId,
351 IN CONST UINT8 *Key,
352 IN CONST UINTN KeyBits,
353 IN CONST UINT8 *Ivec, OPTIONAL
354 IN UINT8 *InData,
355 IN UINTN InDataLength,
356 OUT UINT8 *OutData
357 )
358 {
359 UINTN Index;
360 UINTN ContextSize;
361 UINT8 *Context;
362 EFI_STATUS Status;
363
364 Status = EFI_UNSUPPORTED;
365
366 switch (AlgorithmId) {
367
368 case IKE_EALG_NULL:
369 case IKE_EALG_NONE:
370 CopyMem (OutData, InData, InDataLength);
371 return EFI_SUCCESS;
372
373 case IKE_EALG_3DESCBC:
374 case IKE_EALG_AESCBC:
375 Index = IpSecGetIndexFromEncList(AlgorithmId);
376 if (Index == -1) {
377 return Status;
378 }
379
380 //
381 // Get Context Size
382 //
383 ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize();
384 Context = AllocateZeroPool (ContextSize);
385 if (Context == NULL) {
386 return EFI_OUT_OF_RESOURCES;
387 }
388
389 //
390 // Initiate Context
391 //
392 if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {
393 if (mIpsecEncryptAlgorithmList[Index].CipherDecrypt (Context, InData, InDataLength, Ivec, OutData)) {
394 Status = EFI_SUCCESS;
395 }
396 }
397 break;
398
399 default:
400 return Status;
401 }
402
403 if (Context != NULL) {
404 FreePool (Context);
405 }
406
407 return Status;
408 }
409
410 /**
411 Digests the Payload with key and store the result into the OutData.
412
413 This function calls relevant Hmac interface from CryptoLib according to
414 the input algorithm ID. It computes all datas from InDataFragment and output
415 the result into the OutData buffer. If the OutDataSize is larger than the related
416 HMAC algorithm output size, return EFI_INVALID_PARAMETER.
417
418 @param[in] AlgorithmId The authentication Identification.
419 @param[in] Key Pointer of the authentication key.
420 @param[in] KeyLength The length of the Key in bytes.
421 @param[in] InDataFragment The list contains all data to be authenticated.
422 @param[in] FragmentCount The size of the InDataFragment.
423 @param[out] OutData For in, the buffer to receive the output data.
424 For out, the buffer contains the authenticated data.
425 @param[in] OutDataSize The size of the buffer of OutData.
426
427 @retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.
428 @retval EFI_INVALID_PARAMETER The OutData buffer size is larger than algorithm digest size.
429 @retval EFI_SUCCESS Authenticate the payload successfully.
430 @retval otherwise Authentication of the payload fails.
431
432 **/
433 EFI_STATUS
434 IpSecCryptoIoHmac (
435 IN CONST UINT8 AlgorithmId,
436 IN CONST UINT8 *Key,
437 IN UINTN KeyLength,
438 IN HASH_DATA_FRAGMENT *InDataFragment,
439 IN UINTN FragmentCount,
440 OUT UINT8 *OutData,
441 IN UINTN OutDataSize
442 )
443 {
444 UINTN ContextSize;
445 UINTN Index;
446 UINT8 FragmentIndex;
447 UINT8 *HashContext;
448 EFI_STATUS Status;
449 UINT8 *OutHashData;
450 UINTN OutHashSize;
451
452 Status = EFI_UNSUPPORTED;
453 OutHashData = NULL;
454
455 OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);
456 //
457 // If the expected hash data size is larger than the related Hash algorithm
458 // output length, return EFI_INVALID_PARAMETER.
459 //
460 if (OutDataSize > OutHashSize) {
461 return EFI_INVALID_PARAMETER;
462 }
463 OutHashData = AllocatePool (OutHashSize);
464
465 if (OutHashData == NULL) {
466 return EFI_OUT_OF_RESOURCES;
467 }
468
469 switch (AlgorithmId) {
470
471 case IKE_AALG_NONE :
472 case IKE_AALG_NULL :
473 return EFI_SUCCESS;
474
475 case IKE_AALG_SHA1HMAC:
476 Index = IpSecGetIndexFromAuthList (AlgorithmId);
477 if (Index == -1) {
478 return Status;
479 }
480
481 //
482 // Get Context Size
483 //
484 ContextSize = mIpsecAuthAlgorithmList[Index].HmacGetContextSize();
485 HashContext = AllocateZeroPool (ContextSize);
486
487 if (HashContext == NULL) {
488 Status = EFI_OUT_OF_RESOURCES;
489 goto Exit;
490 }
491
492 //
493 // Initiate HMAC context and hash the input data.
494 //
495 if (mIpsecAuthAlgorithmList[Index].HmacInitiate(HashContext, Key, KeyLength)) {
496 for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) {
497 if (!mIpsecAuthAlgorithmList[Index].HmacUpdate (
498 HashContext,
499 InDataFragment[FragmentIndex].Data,
500 InDataFragment[FragmentIndex].DataSize
501 )
502 ) {
503 goto Exit;
504 }
505 }
506 if (mIpsecAuthAlgorithmList[Index].HmacFinal (HashContext, OutHashData)) {
507 //
508 // In some cases, like the Icv computing, the Icv size might be less than
509 // the key length size, so copy the part of hash data to the OutData.
510 //
511 CopyMem (OutData, OutHashData, OutDataSize);
512 Status = EFI_SUCCESS;
513 }
514
515 goto Exit;
516 }
517
518 default:
519 return Status;
520 }
521
522 Exit:
523 if (HashContext != NULL) {
524 FreePool (HashContext);
525 }
526 if (OutHashData != NULL) {
527 FreePool (OutHashData);
528 }
529
530 return Status;
531 }
532
533 /**
534 Digests the Payload and store the result into the OutData.
535
536 This function calls relevant Hash interface from CryptoLib according to
537 the input algorithm ID. It computes all datas from InDataFragment and output
538 the result into the OutData buffer. If the OutDataSize is larger than the related
539 Hash algorithm output size, return EFI_INVALID_PARAMETER.
540
541 @param[in] AlgorithmId The authentication Identification.
542 @param[in] InDataFragment A list contains all data to be authenticated.
543 @param[in] FragmentCount The size of the InDataFragment.
544 @param[out] OutData For in, the buffer to receive the output data.
545 For out, the buffer contains the authenticated data.
546 @param[in] OutDataSize The size of the buffer of OutData.
547
548 @retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.
549 @retval EFI_SUCCESS Authenticated the payload successfully.
550 @retval EFI_INVALID_PARAMETER If the OutDataSize is larger than the related Hash
551 algorithm could handle.
552 @retval otherwise Authentication of the payload failed.
553
554 **/
555 EFI_STATUS
556 IpSecCryptoIoHash (
557 IN CONST UINT8 AlgorithmId,
558 IN HASH_DATA_FRAGMENT *InDataFragment,
559 IN UINTN FragmentCount,
560 OUT UINT8 *OutData,
561 IN UINTN OutDataSize
562 )
563 {
564 UINTN ContextSize;
565 UINTN Index;
566 UINT8 FragmentIndex;
567 UINT8 *HashContext;
568 EFI_STATUS Status;
569 UINT8 *OutHashData;
570 UINTN OutHashSize;
571
572 Status = EFI_UNSUPPORTED;
573 OutHashData = NULL;
574
575 OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);
576 //
577 // If the expected hash data size is larger than the related Hash algorithm
578 // output length, return EFI_INVALID_PARAMETER.
579 //
580 if (OutDataSize > OutHashSize) {
581 return EFI_INVALID_PARAMETER;
582 }
583 OutHashData = AllocatePool (OutHashSize);
584 if (OutHashData == NULL) {
585 return EFI_OUT_OF_RESOURCES;
586 }
587
588 switch (AlgorithmId) {
589
590 case IKE_AALG_NONE:
591 case IKE_AALG_NULL:
592 return EFI_SUCCESS;
593
594 case IKE_AALG_SHA1HMAC:
595 Index = IpSecGetIndexFromAuthList (AlgorithmId);
596 if (Index == -1) {
597 return Status;
598 }
599 //
600 // Get Context Size
601 //
602 ContextSize = mIpsecHashAlgorithmList[Index].HashGetContextSize();
603 HashContext = AllocateZeroPool (ContextSize);
604 if (HashContext == NULL) {
605 Status = EFI_OUT_OF_RESOURCES;
606 goto Exit;
607 }
608
609 //
610 // Initiate Hash context and hash the input data.
611 //
612 if (mIpsecHashAlgorithmList[Index].HashInitiate(HashContext)) {
613 for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) {
614 if (!mIpsecHashAlgorithmList[Index].HashUpdate (
615 HashContext,
616 InDataFragment[FragmentIndex].Data,
617 InDataFragment[FragmentIndex].DataSize
618 )
619 ) {
620 goto Exit;
621 }
622 }
623 if (mIpsecHashAlgorithmList[Index].HashFinal (HashContext, OutHashData)) {
624 //
625 // In some cases, like the Icv computing, the Icv size might be less than
626 // the key length size, so copy the part of hash data to the OutData.
627 //
628 CopyMem (OutData, OutHashData, OutDataSize);
629 Status = EFI_SUCCESS;
630 }
631
632 goto Exit;
633 }
634
635 default:
636 return Status;
637 }
638
639 Exit:
640 if (HashContext != NULL) {
641 FreePool (HashContext);
642 }
643 if (OutHashData != NULL) {
644 FreePool (OutHashData);
645 }
646
647 return Status;
648 }
649
650 /**
651 Generates the Diffie-Hellman public key.
652
653 This function first initiate a DHContext, then call the DhSetParameter() to set
654 the prime and primelength, at end call the DhGenerateKey() to generates random
655 secret exponent, and computes the public key. The output returned via parameter
656 PublicKey and PublicKeySize. DH context is updated accordingly. If the PublicKey
657 buffer is too small to hold the public key, EFI_INVALID_PARAMETER is returned
658 and PublicKeySize is set to the required buffer size to obtain the public key.
659
660 @param[in, out] DhContext Pointer to the DH context.
661 @param[in] Generator Value of generator.
662 @param[in] PrimeLength Length in bits of prime to be generated.
663 @param[in] Prime Pointer to the buffer to receive the generated
664 prime number.
665 @param[out] PublicKey Pointer to the buffer to receive generated public key.
666 @param[in, out] PublicKeySize For in, the size of PublicKey buffer in bytes.
667 For out, the size of data returned in PublicKey
668 buffer in bytes.
669
670 @retval EFI_SUCCESS The operation performs successfully.
671 @retval Otherwise The operation is failed.
672
673 **/
674 EFI_STATUS
675 IpSecCryptoIoDhGetPublicKey (
676 IN OUT UINT8 **DhContext,
677 IN UINTN Generator,
678 IN UINTN PrimeLength,
679 IN CONST UINT8 *Prime,
680 OUT UINT8 *PublicKey,
681 IN OUT UINTN *PublicKeySize
682 )
683 {
684 EFI_STATUS Status;
685
686 *DhContext = DhNew ();
687 ASSERT (*DhContext != NULL);
688 if (!DhSetParameter (*DhContext, Generator, PrimeLength, Prime)) {
689 Status = EFI_INVALID_PARAMETER;
690 goto Exit;
691 }
692
693 if (!DhGenerateKey (*DhContext, PublicKey, PublicKeySize)) {
694 Status = EFI_INVALID_PARAMETER;
695 goto Exit;
696 }
697 return EFI_SUCCESS;
698
699 Exit:
700 if (*DhContext != NULL) {
701 DhFree (*DhContext);
702 DhContext = NULL;
703 }
704
705 return Status;
706 }
707
708 /**
709 Generates exchanged common key.
710
711 Given peer's public key, this function computes the exchanged common key, based
712 on its own context including value of prime modulus and random secret exponent.
713
714 @param[in, out] DhContext Pointer to the DH context.
715 @param[in] PeerPublicKey Pointer to the peer's Public Key.
716 @param[in] PeerPublicKeySize Size of peer's public key in bytes.
717 @param[out] Key Pointer to the buffer to receive generated key.
718 @param[in, out] KeySize For in, the size of Key buffer in bytes.
719 For out, the size of data returned in Key
720 buffer in bytes.
721
722 @retval EFI_SUCCESS The operation performs successfully.
723 @retval Otherwise The operation is failed.
724
725 **/
726 EFI_STATUS
727 IpSecCryptoIoDhComputeKey (
728 IN OUT UINT8 *DhContext,
729 IN CONST UINT8 *PeerPublicKey,
730 IN UINTN PeerPublicKeySize,
731 OUT UINT8 *Key,
732 IN OUT UINTN *KeySize
733 )
734 {
735 if (!DhComputeKey (DhContext, PeerPublicKey, PeerPublicKeySize, Key, KeySize)) {
736 return EFI_INVALID_PARAMETER;
737 }
738
739 return EFI_SUCCESS;
740 }
741
742 /**
743 Releases the DH context. If DhContext is NULL, return EFI_INVALID_PARAMETER.
744
745 @param[in, out] DhContext Pointer to the DH context to be freed.
746
747 @retval EFI_SUCCESS The operation performs successfully.
748 @retval EFI_INVALID_PARAMETER The DhContext is NULL.
749
750 **/
751 EFI_STATUS
752 IpSecCryptoIoFreeDh (
753 IN OUT UINT8 **DhContext
754 )
755 {
756 if (*DhContext == NULL) {
757 return EFI_INVALID_PARAMETER;
758 }
759
760 DhFree (*DhContext);
761 return EFI_SUCCESS;
762 }
763
764 /**
765 Generates random numbers of specified size.
766
767 If the Random Generator wasn't initiated, initiate it first, then call RandomBytes.
768
769 @param[out] OutBuffer Pointer to buffer to receive random value.
770 @param[in] Bytes Size of random bytes to generate.
771
772 @retval EFI_SUCCESS The operation performs successfully.
773 @retval Otherwise The operation is failed.
774
775 **/
776 EFI_STATUS
777 IpSecCryptoIoGenerateRandomBytes (
778 OUT UINT8* OutBuffer,
779 IN UINTN Bytes
780 )
781 {
782 if (!mInitialRandomSeed) {
783 RandomSeed (NULL, 0);
784 mInitialRandomSeed = TRUE;
785 }
786 if (RandomBytes (OutBuffer, Bytes)) {
787 return EFI_SUCCESS;
788 } else {
789 return EFI_INVALID_PARAMETER;
790 }
791 }
792
793 /**
794 Authenticate data with the certificate.
795
796 @param[in] InData Pointer to the Data to be signed.
797 @param[in] InDataSize InData size in bytes.
798 @param[in] PrivateKey Pointer to the private key.
799 @param[in] PrivateKeySize The size of Private Key in bytes.
800 @param[in] KeyPassWord Pointer to the password for retrieving private key.
801 @param[in] KeyPwdSize The size of Key Password in bytes.
802 @param[out] OutData The pointer to the signed data.
803 @param[in, out] OutDataSize Pointer to contain the size of out data.
804
805 **/
806 VOID
807 IpSecCryptoIoAuthDataWithCertificate (
808 IN UINT8 *InData,
809 IN UINTN InDataSize,
810 IN UINT8 *PrivateKey,
811 IN UINTN PrivateKeySize,
812 IN UINT8 *KeyPassWord,
813 IN UINTN KeyPwdSize,
814 OUT UINT8 **OutData,
815 IN OUT UINTN *OutDataSize
816 )
817 {
818 UINT8 *RsaContext;
819 UINT8 *Signature;
820 UINTN SigSize;
821
822 SigSize = 0;
823 RsaContext = NULL;
824
825 //
826 // Retrieve RSA Private Key from password-protected PEM data
827 //
828 RsaGetPrivateKeyFromPem (
829 (CONST UINT8 *)PrivateKey,
830 PrivateKeySize,
831 (CONST CHAR8 *)KeyPassWord,
832 (VOID **) &RsaContext
833 );
834 if (RsaContext == NULL) {
835 return;
836 }
837
838 //
839 // Sign data
840 //
841 Signature = NULL;
842 if (!RsaPkcs1Sign (RsaContext, InData, InDataSize, Signature, &SigSize)) {
843 Signature = AllocateZeroPool (SigSize);
844 } else {
845 return;
846 }
847
848 RsaPkcs1Sign (RsaContext, InData, InDataSize, Signature, &SigSize);
849
850 *OutData = Signature;
851 *OutDataSize = SigSize;
852
853 if (RsaContext != NULL) {
854 RsaFree (RsaContext);
855 }
856 }
857
858 /**
859 Verify the singed data with the public key which is contained in a certificate.
860
861 @param[in] InCert Pointer to the Certificate which contains the
862 public key.
863 @param[in] CertLen The size of Certificate in bytes.
864 @param[in] InCa Pointer to the CA certificate
865 @param[in] CaLen The size of CA certificate in bytes.
866 @param[in] InData Pointer to octet message hash to be checked.
867 @param[in] InDataSize Size of the message hash in bytes.
868 @param[in] Singnature The pointer to the RSA PKCS1-V1_5 signature to be verified.
869 @param[in] SigSize Size of signature in bytes.
870
871 @retval TRUE Valid signature encoded in PKCS1-v1_5.
872 @retval FALSE Invalid signature or invalid RSA context.
873
874 **/
875 BOOLEAN
876 IpSecCryptoIoVerifySignDataByCertificate (
877 IN UINT8 *InCert,
878 IN UINTN CertLen,
879 IN UINT8 *InCa,
880 IN UINTN CaLen,
881 IN UINT8 *InData,
882 IN UINTN InDataSize,
883 IN UINT8 *Singnature,
884 IN UINTN SigSize
885 )
886 {
887 UINT8 *RsaContext;
888 BOOLEAN Status;
889
890 //
891 // Create the RSA Context
892 //
893 RsaContext = RsaNew ();
894 if (RsaContext == NULL) {
895 return FALSE;
896 }
897
898 //
899 // Verify the validity of X509 Certificate
900 //
901 if (!X509VerifyCert (InCert, CertLen, InCa, CaLen)) {
902 return FALSE;
903 }
904
905 //
906 // Retrieve the RSA public Key from Certificate
907 //
908 RsaGetPublicKeyFromX509 ((CONST UINT8 *)InCert, CertLen, (VOID **)&RsaContext);
909
910 //
911 // Verify data
912 //
913 Status = RsaPkcs1Verify (RsaContext, InData, InDataSize, Singnature, SigSize);
914
915 if (RsaContext != NULL) {
916 RsaFree (RsaContext);
917 }
918
919 return Status;
920 }
921
922 /**
923 Retrieves the RSA Public Key from one X509 certificate (DER format only).
924
925 @param[in] InCert Pointer to the certificate.
926 @param[in] CertLen The size of the certificate in bytes.
927 @param[out] PublicKey Pointer to the retrieved public key.
928 @param[out] PublicKeyLen Size of Public Key in bytes.
929
930 @retval EFI_SUCCESS Successfully get the public Key.
931 @retval EFI_INVALID_PARAMETER The certificate is malformed.
932
933 **/
934 EFI_STATUS
935 IpSecCryptoIoGetPublicKeyFromCert (
936 IN UINT8 *InCert,
937 IN UINTN CertLen,
938 OUT UINT8 **PublicKey,
939 OUT UINTN *PublicKeyLen
940 )
941 {
942 UINT8 *RsaContext;
943 EFI_STATUS Status;
944
945 Status = EFI_SUCCESS;
946
947 //
948 // Create the RSA Context
949 //
950 RsaContext = RsaNew ();
951
952 //
953 // Retrieve the RSA public key from CA Certificate
954 //
955 if (!RsaGetPublicKeyFromX509 ((CONST UINT8 *)InCert, CertLen, (VOID **) &RsaContext)) {
956 Status = EFI_INVALID_PARAMETER;
957 goto EXIT;
958 }
959
960 *PublicKeyLen = 0;
961
962 RsaGetKey (RsaContext, RsaKeyN, NULL, PublicKeyLen);
963
964 *PublicKey = AllocateZeroPool (*PublicKeyLen);
965 if (*PublicKey == NULL) {
966 Status = EFI_OUT_OF_RESOURCES;
967 goto EXIT;
968 }
969
970 if (!RsaGetKey (RsaContext, RsaKeyN, *PublicKey, PublicKeyLen)) {
971 Status = EFI_INVALID_PARAMETER;
972 }
973
974 EXIT:
975 if (RsaContext != NULL) {
976 RsaFree (RsaContext);
977 }
978
979 return Status;
980 }
981
982 /**
983 Retrieves the subject name from one X509 certificate (DER format only).
984
985 @param[in] InCert Pointer to the X509 certificate.
986 @param[in] CertSize The size of the X509 certificate in bytes.
987 @param[out] CertSubject Pointer to the retrieved certificate subject.
988 @param[out] SubjectSize The size of Certificate Subject in bytes.
989
990 @retval EFI_SUCCESS Retrieved the certificate subject successfully.
991 @retval EFI_INVALID_PARAMETER The certificate is malformed.
992
993 **/
994 EFI_STATUS
995 IpSecCryptoIoGetSubjectFromCert (
996 IN UINT8 *InCert,
997 IN UINTN CertSize,
998 OUT UINT8 **CertSubject,
999 OUT UINTN *SubjectSize
1000 )
1001 {
1002 EFI_STATUS Status;
1003
1004 Status = EFI_SUCCESS;
1005
1006 *SubjectSize = 0;
1007 X509GetSubjectName (InCert, CertSize, *CertSubject, SubjectSize);
1008
1009 *CertSubject = AllocateZeroPool (*SubjectSize);
1010 if (!X509GetSubjectName (InCert, CertSize, *CertSubject, SubjectSize)) {
1011 Status = EFI_INVALID_PARAMETER;
1012 }
1013
1014 return Status;
1015 }