2 IPsec inbound and outbound traffic processing.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "IpSecImpl.h"
17 #include "IpSecDebug.h"
18 #include "IpSecCryptIo.h"
20 extern LIST_ENTRY mConfigData
[IPsecConfigDataTypeMaximum
];
23 The call back function of NetbufFromExt.
25 @param[in] Arg The argument passed from the caller.
30 IpSecOnRecyclePacket (
37 This is a Notification function. It is called when the related IP6_TXTOKEN_WRAP
40 @param[in] Event The related event.
41 @param[in] Context The data passed by the caller.
46 IpSecRecycleCallback (
51 IPSEC_RECYCLE_CONTEXT
*RecycleContext
;
53 RecycleContext
= (IPSEC_RECYCLE_CONTEXT
*) Context
;
55 if (RecycleContext
->FragmentTable
!= NULL
) {
56 FreePool (RecycleContext
->FragmentTable
);
59 if (RecycleContext
->PayloadBuffer
!= NULL
) {
60 FreePool (RecycleContext
->PayloadBuffer
);
63 FreePool (RecycleContext
);
64 gBS
->CloseEvent (Event
);
69 Calculate the extension header of IP. The return length only doesn't contain
70 the fixed IP header length.
72 @param[in] IpHead Points to an IP head to be calculated.
73 @param[in] LastHead Points to the last header of the IP header.
75 @return The length of the extension header.
79 IpSecGetPlainExtHeadSize (
86 Size
= (UINT16
) (LastHead
- (UINT8
*) IpHead
);
88 if (Size
> sizeof (EFI_IP6_HEADER
)) {
90 // * (LastHead+1) point the last header's length but not include the first
91 // 8 octers, so this formluation add 8 at the end.
93 Size
= (UINT16
) (Size
- sizeof (EFI_IP6_HEADER
) + *(LastHead
+ 1) + 8);
102 Authenticate the IpSec Payload and store the result in the IcvBuffer.
104 @param[in] BufferToAuth The buffer to be Authenticated.
105 @param[in] AuthSize The size of the buffer to be Authenticated.
106 @param[in, out] IcvBuffer The buffer to store the ICV.
107 @param[in] IcvSize The size of ICV.
108 @param[in] Key The Key passed to the CryptLib to generate a
110 @param[in] AuthAlgId The Authentication Algorithm ID.
112 @retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.
113 @retval EFI_SUCCESS Authenticated the payload successfully.
114 @retval otherwise Authentication of the payload failed.
118 IN UINT8
*BufferToAuth
,
120 IN OUT UINT8
*IcvBuffer
,
127 case EFI_IPSEC_AALG_NONE
:
128 case EFI_IPSEC_AALG_NULL
:
132 return EFI_UNSUPPORTED
;
137 Verify if the Authentication payload is correct.
139 @param[in] EspBuffer Points to the ESP wrapped buffer.
140 @param[in] EspSize The size of the ESP wrapped buffer.
141 @param[in] SadEntry The related SAD entry to store the authentication
143 @param[in] IcvSize The length of ICV.
145 @retval EFI_SUCCESS The authentication data is correct.
146 @retval EFI_ACCESS_DENIED The authentication data is not correct.
150 IpSecEspAuthVerifyPayload (
153 IN IPSEC_SAD_ENTRY
*SadEntry
,
162 // Calculate the size of authentication payload.
164 *IcvSize
= IpSecGetIcvLength (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthAlgoId
);
165 AuthSize
= EspSize
- *IcvSize
;
168 // Calculate the icv buffer and size of the payload.
170 Status
= IpSecAuthPayload (
175 SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthKey
,
176 SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthAlgoId
178 if (EFI_ERROR (Status
)) {
182 // Compare the calculated icv and the appended original icv.
184 if (CompareMem (EspBuffer
+ AuthSize
, IcvBuffer
, *IcvSize
) == 0) {
188 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
189 return EFI_ACCESS_DENIED
;
193 ESP Decrypt the payload.
195 @param[in, out] PayloadBuffer Pointer to the buffer containing the ESP wrapped;
196 to be decrypted on input, and plaintext on return. The
197 number of bytes of data to be decrypted is
198 specified by EncryptSize.
199 @param[in] EncryptSize The size of the PayloadBuffer as input.
200 @param[in] SadEntry The related SAD entry.
201 @param[in] IvSize The size of IV.
202 @param[out] PlainPayloadSize Contains the return value of decrypted size.
203 @param[out] PaddingSize Contains the return value of Padding size.
204 @param[out] NextHeader Contains the return value of the last protocol header
207 @retval EFI_UNSUPPORTED The Algorithm pointed to by the SAD entry is not supported.
208 @retval EFI_SUCCESS The operation completed successfully.
212 IpSecEspDecryptPayload (
213 IN OUT UINT8
*PayloadBuffer
,
214 IN UINTN EncryptSize
,
215 IN IPSEC_SAD_ENTRY
*SadEntry
,
217 OUT UINTN
*PlainPayloadSize
,
218 OUT UINTN
*PaddingSize
,
219 OUT UINT8
*NextHeader
222 EFI_ESP_TAIL
*EspTail
;
224 switch (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.EncAlgoId
) {
225 case EFI_IPSEC_EALG_NULL
:
226 EspTail
= (EFI_ESP_TAIL
*) (PayloadBuffer
+ EncryptSize
- sizeof (EFI_ESP_TAIL
));
227 *PaddingSize
= EspTail
->PaddingLength
;
228 *NextHeader
= EspTail
->NextHeader
;
229 *PlainPayloadSize
= EncryptSize
- EspTail
->PaddingLength
- sizeof (EFI_ESP_TAIL
);
232 case EFI_IPSEC_EALG_3DESCBC
:
233 case EFI_IPSEC_EALG_AESCBC
:
235 // TODO: support these algorithm
237 return EFI_UNSUPPORTED
;
239 return EFI_UNSUPPORTED
;
246 ESP Encrypt the payload.
248 @param[in, out] BufferToEncrypt Pointer to the buffer containing plaintext to be
249 encrypted on input, and ciphertext on return. The
250 number of bytes of data to be encrypted is
251 specified by EncryptSize.
252 @param[in, out] EncryptSize The size of the plaintext on input, and the size of the
253 ciphertext on return.
254 @param[in] IvBuffer Points to IV data.
255 @param[in] IvSize Size of IV.
256 @param[in] SadEntry Related SAD entry.
258 @retval EFI_UNSUPPORTED The Algorithm pointed by SAD entry is not supported.
259 @retval EFI_SUCCESS The operation completed successfully.
263 IpSecEspEncryptPayload (
264 IN OUT UINT8
*BufferToEncrypt
,
265 IN OUT UINTN EncryptSize
,
268 IN IPSEC_SAD_ENTRY
*SadEntry
271 switch (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.EncAlgoId
) {
272 case EFI_IPSEC_EALG_NULL
:
275 case EFI_IPSEC_EALG_3DESCBC
:
276 case EFI_IPSEC_EALG_AESCBC
:
278 // TODO: support these algorithms
280 return EFI_UNSUPPORTED
;
282 return EFI_UNSUPPORTED
;
288 The actual entry to relative function processes the inbound traffic of ESP header.
290 This function is the subfunction of IpSecProtectInboundPacket(). It checks the
291 received packet security property and trim the ESP header and then returns without
292 an IPsec protected IP Header and FramgmentTable.
294 @param[in] IpVersion The version of IP.
295 @param[in, out] IpHead Points to the IP header containing the ESP header
296 to be trimed on input, and without ESP header
298 @param[out] LastHead The Last Header in IP header on return.
299 @param[in] OptionsBuffer Pointer to the options buffer. It is optional.
300 @param[in] OptionsLength Length of the options buffer. It is optional.
301 @param[in, out] FragmentTable Pointer to a list of fragments in the form of IPsec
302 protected on input, and without IPsec protected
304 @param[in] FragmentCount The number of fragments.
305 @param[out] SpdEntry Pointer to contain the address of SPD entry on return.
306 @param[out] RecycleEvent The event for recycling of resources.
308 @retval EFI_SUCCESS The operation was successful.
309 @retval EFI_ACCESS_DENIED One or more following conditions is TRUE:
310 - ESP header was not found.
311 - The related SAD entry was not found.
312 - The related SAD entry does not support the ESP protocol.
313 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
317 IpSecEspInboundPacket (
321 IN VOID
*OptionsBuffer
, OPTIONAL
322 IN UINT32 OptionsLength
, OPTIONAL
323 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
324 IN UINT32
*FragmentCount
,
325 OUT IPSEC_SPD_ENTRY
**SpdEntry
,
326 OUT EFI_EVENT
*RecycleEvent
333 UINTN PlainPayloadSize
;
336 UINT8
*ProcessBuffer
;
337 EFI_IP_ADDRESS DestIp
;
338 EFI_ESP_HEADER
*EspHeader
;
339 EFI_ESP_TAIL
*EspTail
;
340 EFI_IPSEC_SA_ID
*SaId
;
341 IPSEC_SAD_DATA
*SadData
;
342 IPSEC_SAD_ENTRY
*SadEntry
;
343 IPSEC_RECYCLE_CONTEXT
*RecycleContext
;
346 UINT16 IpSecHeadSize
;
348 Status
= EFI_SUCCESS
;
350 ProcessBuffer
= NULL
;
351 RecycleContext
= NULL
;
352 *RecycleEvent
= NULL
;
353 PlainPayloadSize
= 0;
356 // Build netbuf from fragment table first.
358 Payload
= NetbufFromExt (
359 (NET_FRAGMENT
*) *FragmentTable
,
362 sizeof (EFI_ESP_HEADER
),
363 IpSecOnRecyclePacket
,
366 if (Payload
== NULL
) {
367 Status
= EFI_OUT_OF_RESOURCES
;
371 // Get the esp size and eso header from netbuf.
373 EspSize
= Payload
->TotalSize
;
374 EspHeader
= (EFI_ESP_HEADER
*) NetbufGetByte (Payload
, 0, NULL
);
375 if (EspHeader
== NULL
) {
376 Status
= EFI_ACCESS_DENIED
;
380 // Parse destination address from ip header.
382 ZeroMem (&DestIp
, sizeof (EFI_IP_ADDRESS
));
383 if (IpVersion
== IP_VERSION_4
) {
386 &((IP4_HEAD
*) IpHead
)->Dst
,
392 &((EFI_IP6_HEADER
*) IpHead
)->DestinationAddress
,
393 sizeof (EFI_IPv6_ADDRESS
)
397 // Lookup sad entry according to the spi and dest address.
399 Spi
= NTOHL (EspHeader
->Spi
);
400 SadEntry
= IpSecLookupSadBySpi (Spi
, &DestIp
);
401 if (SadEntry
== NULL
) {
402 Status
= EFI_ACCESS_DENIED
;
407 SadData
= SadEntry
->Data
;
410 // Only support esp protocol currently.
412 if (SaId
->Proto
!= EfiIPsecESP
) {
413 Status
= EFI_ACCESS_DENIED
;
417 if (!SadData
->ManualSet
) {
419 // TODO: Check sa lifetime and sequence number
423 // Allocate buffer for decryption and authentication by esp.
425 ProcessBuffer
= AllocateZeroPool (EspSize
);
426 if (ProcessBuffer
== NULL
) {
427 Status
= EFI_OUT_OF_RESOURCES
;
431 NetbufCopy (Payload
, 0, (UINT32
) EspSize
, ProcessBuffer
);
434 // Authenticate the esp wrapped buffer by the sad entry if has auth key.
437 if (SadData
->AlgoInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
438 Status
= IpSecEspAuthVerifyPayload (
444 if (EFI_ERROR (Status
)) {
449 // Decrypt the payload by the sad entry if has decrypt key.
452 if (SadData
->AlgoInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
453 Status
= IpSecEspDecryptPayload (
454 ProcessBuffer
+ sizeof (EFI_ESP_HEADER
),
455 EspSize
- sizeof (EFI_ESP_HEADER
) - IcvSize
,
462 if (EFI_ERROR (Status
)) {
466 EspTail
= (EFI_ESP_TAIL
*) (ProcessBuffer
+ EspSize
- IcvSize
- sizeof (EFI_ESP_TAIL
));
467 PaddingSize
= EspTail
->PaddingLength
;
468 NextHeader
= EspTail
->NextHeader
;
469 PlainPayloadSize
= EspSize
- sizeof (EFI_ESP_HEADER
) - IvSize
- IcvSize
- sizeof (EFI_ESP_TAIL
) - PaddingSize
;
472 // TODO: handle anti-replay window
475 // Decryption and authentication with esp has been done, so it's time to
476 // reload the new packet, create recycle event and fixup ip header.
478 RecycleContext
= AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT
));
479 if (RecycleContext
== NULL
) {
480 Status
= EFI_OUT_OF_RESOURCES
;
484 Status
= gBS
->CreateEvent (
487 IpSecRecycleCallback
,
491 if (EFI_ERROR (Status
)) {
495 // TODO: Who take responsible to handle the original fragment table?
497 *FragmentTable
= AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA
));
498 if (*FragmentTable
== NULL
) {
499 Status
= EFI_OUT_OF_RESOURCES
;
503 RecycleContext
->PayloadBuffer
= ProcessBuffer
;
504 RecycleContext
->FragmentTable
= *FragmentTable
;
505 (*FragmentTable
)[0].FragmentBuffer
= ProcessBuffer
+ sizeof (EFI_ESP_HEADER
) + IvSize
;
506 (*FragmentTable
)[0].FragmentLength
= (UINT32
) PlainPayloadSize
;
510 // Update the total length field in ip header since processed by esp.
512 if (IpVersion
== IP_VERSION_4
) {
513 ((IP4_HEAD
*) IpHead
)->TotalLen
= HTONS ((UINT16
) (((IP4_HEAD
*) IpHead
)->HeadLen
+ PlainPayloadSize
));
515 IpSecHeadSize
= IpSecGetPlainExtHeadSize (IpHead
, LastHead
);
516 ((EFI_IP6_HEADER
*) IpHead
)->PayloadLength
= HTONS ((UINT16
)(IpSecHeadSize
+ PlainPayloadSize
));
519 // Update the next layer field in ip header since esp header inserted.
521 *LastHead
= NextHeader
;
524 // Update the spd association of the sad entry.
526 *SpdEntry
= SadData
->SpdEntry
;
529 if (Payload
!= NULL
) {
530 NetbufFree (Payload
);
533 if (EFI_ERROR (Status
)) {
534 if (ProcessBuffer
!= NULL
) {
535 FreePool (ProcessBuffer
);
538 if (RecycleContext
!= NULL
) {
539 FreePool (RecycleContext
);
542 if (*RecycleEvent
!= NULL
) {
543 gBS
->CloseEvent (*RecycleEvent
);
551 The actual entry to the relative function processes the output traffic using the ESP protocol.
553 This function is the subfunction of IpSecProtectOutboundPacket(). It protected
554 the sending packet by encrypting its payload and inserting ESP header in the orginal
555 IP header, then return the IpHeader and IPsec protected Fragmentable.
557 @param[in] IpVersion The version of IP.
558 @param[in, out] IpHead Points to IP header containing the orginal IP header
559 to be processed on input, and inserted ESP header
561 @param[in] LastHead The Last Header in IP header.
562 @param[in] OptionsBuffer Pointer to the options buffer. It is optional.
563 @param[in] OptionsLength Length of the options buffer. It is optional.
564 @param[in, out] FragmentTable Pointer to a list of fragments to be protected by
565 IPsec on input, and with IPsec protected
567 @param[in] FragmentCount The number of fragments.
568 @param[in] SadEntry The related SAD entry.
569 @param[out] RecycleEvent The event for recycling of resources.
571 @retval EFI_SUCCESS The operation was successful.
572 @retval EFI_OUT_OF_RESOURCES The required system resources can't be allocated.
576 IpSecEspOutboundPacket (
580 IN VOID
*OptionsBuffer
, OPTIONAL
581 IN UINT32 OptionsLength
, OPTIONAL
582 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
583 IN UINT32
*FragmentCount
,
584 IN IPSEC_SAD_ENTRY
*SadEntry
,
585 OUT EFI_EVENT
*RecycleEvent
590 EFI_IPSEC_SA_ID
*SaId
;
591 IPSEC_SAD_DATA
*SadData
;
592 IPSEC_RECYCLE_CONTEXT
*RecycleContext
;
593 UINT8
*ProcessBuffer
;
595 INTN EncryptBlockSize
;// Size of encryption block, 4 bytes aligned and >= 4
596 UINTN EspSize
; // Total size of esp wrapped ip payload
597 UINTN IvSize
; // Size of IV, optional, might be 0
598 UINTN PlainPayloadSize
;// Original IP payload size
599 UINTN PaddingSize
; // Size of padding
600 UINTN EncryptSize
; // Size of data to be encrypted, start after IV and
602 UINTN IcvSize
; // Size of ICV, optional, might be 0
603 UINT8
*RestOfPayload
; // Start of Payload after IV
604 UINT8
*Padding
; // Start address of padding
605 EFI_ESP_HEADER
*EspHeader
; // Start address of ESP frame
606 EFI_ESP_TAIL
*EspTail
; // Address behind padding
608 Status
= EFI_ACCESS_DENIED
;
610 SadData
= SadEntry
->Data
;
611 ProcessBuffer
= NULL
;
612 RecycleContext
= NULL
;
613 *RecycleEvent
= NULL
;
615 if (!SadData
->ManualSet
&&
616 SadData
->AlgoInfo
.EspAlgoInfo
.EncKey
== NULL
&&
617 SadData
->AlgoInfo
.EspAlgoInfo
.AuthKey
== NULL
620 // Invalid manual sad entry configuration.
625 // Calculate enctrypt block size, need iv by default and 4 bytes alignment.
627 EncryptBlockSize
= 4;
629 if (SadData
->AlgoInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
630 EncryptBlockSize
= IpSecGetEncryptBlockSize (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.EncAlgoId
);
632 if (EncryptBlockSize
< 0 || (EncryptBlockSize
!= 1 && EncryptBlockSize
% 4 != 0)) {
637 // Calculate the plain payload size accroding to the fragment table.
639 PlainPayloadSize
= 0;
640 for (Index
= 0; Index
< *FragmentCount
; Index
++) {
641 PlainPayloadSize
+= (*FragmentTable
)[Index
].FragmentLength
;
644 // Calculate icv size, optional by default and 4 bytes alignment.
647 if (SadData
->AlgoInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
648 IcvSize
= IpSecGetIcvLength (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthAlgoId
);
649 if (IcvSize
% 4 != 0) {
654 // Calcuate the total size of esp wrapped ip payload.
656 IvSize
= IpSecGetEncryptIvLength (SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.EncAlgoId
);
657 EncryptSize
= (PlainPayloadSize
+ sizeof (EFI_ESP_TAIL
) + EncryptBlockSize
- 1) / EncryptBlockSize
* EncryptBlockSize
;
658 PaddingSize
= EncryptSize
- PlainPayloadSize
- sizeof (EFI_ESP_TAIL
);
659 EspSize
= sizeof (EFI_ESP_HEADER
) + IvSize
+ EncryptSize
+ IcvSize
;
661 ProcessBuffer
= AllocateZeroPool (EspSize
);
662 if (ProcessBuffer
== NULL
) {
663 Status
= EFI_OUT_OF_RESOURCES
;
667 // Calculate esp header and esp tail including header, payload and padding.
669 EspHeader
= (EFI_ESP_HEADER
*) ProcessBuffer
;
670 RestOfPayload
= (UINT8
*) (EspHeader
+ 1) + IvSize
;
671 Padding
= RestOfPayload
+ PlainPayloadSize
;
672 EspTail
= (EFI_ESP_TAIL
*) (Padding
+ PaddingSize
);
675 // Fill the sn and spi fields in esp header.
677 EspHeader
->SequenceNumber
= HTONL ((UINT32
) SadData
->SequenceNumber
+ 1);
678 EspHeader
->Spi
= HTONL (SaId
->Spi
);
681 // Copy the rest of payload (after iv) from the original fragment buffer.
684 for (Index
= 0; Index
< *FragmentCount
; Index
++) {
686 (RestOfPayload
+ BytesCopied
),
687 (*FragmentTable
)[Index
].FragmentBuffer
,
688 (*FragmentTable
)[Index
].FragmentLength
690 BytesCopied
+= (*FragmentTable
)[Index
].FragmentLength
;
693 // Fill the padding buffer by natural number sequence.
695 for (Index
= 0; Index
< PaddingSize
; Index
++) {
696 Padding
[Index
] = (UINT8
) (Index
+ 1);
699 // Fill the padding length and next header fields in esp tail.
701 EspTail
->PaddingLength
= (UINT8
) PaddingSize
;
702 EspTail
->NextHeader
= *LastHead
;
705 // Generate iv at random by crypt library.
707 Status
= IpSecGenerateIv (
708 (UINT8
*) (EspHeader
+ 1),
713 if (EFI_ERROR (Status
)) {
717 // Encrypt the payload (after iv) by the sad entry if has encrypt key.
719 if (SadData
->AlgoInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
720 Status
= IpSecEspEncryptPayload (
723 (UINT8
*) (EspHeader
+ 1),
727 if (EFI_ERROR (Status
)) {
732 // Authenticate the esp wrapped buffer by the sad entry if has auth key.
734 if (SadData
->AlgoInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
735 Status
= IpSecAuthPayload (
738 ProcessBuffer
+ EspSize
- IcvSize
,
740 SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthKey
,
741 SadEntry
->Data
->AlgoInfo
.EspAlgoInfo
.AuthAlgoId
743 if (EFI_ERROR (Status
)) {
748 // Encryption and authentication with esp has been done, so it's time to
749 // reload the new packet, create recycle event and fixup ip header.
751 RecycleContext
= AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT
));
752 if (RecycleContext
== NULL
) {
753 Status
= EFI_OUT_OF_RESOURCES
;
757 Status
= gBS
->CreateEvent (
760 IpSecRecycleCallback
,
764 if (EFI_ERROR (Status
)) {
768 // TODO: Who take responsible to handle the original fragment table?
770 *FragmentTable
= AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA
));
771 if (*FragmentTable
== NULL
) {
772 Status
= EFI_OUT_OF_RESOURCES
;
776 RecycleContext
->FragmentTable
= *FragmentTable
;
777 RecycleContext
->PayloadBuffer
= ProcessBuffer
;
778 (*FragmentTable
)[0].FragmentBuffer
= ProcessBuffer
;
779 (*FragmentTable
)[0].FragmentLength
= (UINT32
) EspSize
;
783 // Update the total length field in ip header since processed by esp.
785 if (IpVersion
== IP_VERSION_4
) {
786 ((IP4_HEAD
*) IpHead
)->TotalLen
= HTONS ((UINT16
) (((IP4_HEAD
*) IpHead
)->HeadLen
+ EspSize
));
788 ((EFI_IP6_HEADER
*) IpHead
)->PayloadLength
= (UINT16
) (IpSecGetPlainExtHeadSize (IpHead
, LastHead
) + EspSize
);
791 // Update the next layer field in ip header since esp header inserted.
793 *LastHead
= IPSEC_ESP_PROTOCOL
;
796 // Increase the sn number in sad entry according to rfc4303.
798 SadData
->SequenceNumber
++;
801 if (EFI_ERROR (Status
)) {
802 if (ProcessBuffer
!= NULL
) {
803 FreePool (ProcessBuffer
);
806 if (RecycleContext
!= NULL
) {
807 FreePool (RecycleContext
);
810 if (*RecycleEvent
!= NULL
) {
811 gBS
->CloseEvent (*RecycleEvent
);
819 This function processes the inbound traffic with IPsec.
821 It checks the received packet security property, trims the ESP/AH header, and then
822 returns without an IPsec protected IP Header and FragmentTable.
824 @param[in] IpVersion The version of IP.
825 @param[in, out] IpHead Points to IP header containing the ESP/AH header
826 to be trimed on input, and without ESP/AH header
828 @param[in] LastHead The Last Header in IP header on return.
829 @param[in] OptionsBuffer Pointer to the options buffer. It is optional.
830 @param[in] OptionsLength Length of the options buffer. It is optional.
831 @param[in, out] FragmentTable Pointer to a list of fragments in form of IPsec
832 protected on input, and without IPsec protected
834 @param[in] FragmentCount The number of fragments.
835 @param[out] SpdEntry Pointer to contain the address of SPD entry on return.
836 @param[out] RecycleEvent The event for recycling of resources.
838 @retval EFI_SUCCESS The operation was successful.
839 @retval EFI_UNSUPPORTED The IPSEC protocol is not supported.
843 IpSecProtectInboundPacket (
847 IN VOID
*OptionsBuffer
, OPTIONAL
848 IN UINT32 OptionsLength
, OPTIONAL
849 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
850 IN UINT32
*FragmentCount
,
851 OUT IPSEC_SPD_ENTRY
**SpdEntry
,
852 OUT EFI_EVENT
*RecycleEvent
855 if (*LastHead
== IPSEC_ESP_PROTOCOL
) {
857 // Process the esp ipsec header of the inbound traffic.
859 return IpSecEspInboundPacket (
872 // The other protocols are not supported.
874 return EFI_UNSUPPORTED
;
878 This function processes the output traffic with IPsec.
880 It protected the sending packet by encrypting it payload and inserting ESP/AH header
881 in the orginal IP header, then returns the IpHeader and IPsec protected Fragmentable.
883 @param[in] IpVersion The version of IP.
884 @param[in, out] IpHead Points to IP header containing the orginal IP header
885 to be processed on input, and inserted ESP/AH header
887 @param[in] LastHead The Last Header in the IP header.
888 @param[in] OptionsBuffer Pointer to the options buffer. It is optional.
889 @param[in] OptionsLength Length of the options buffer. It is optional.
890 @param[in, out] FragmentTable Pointer to a list of fragments to be protected by
891 IPsec on input, and with IPsec protected
893 @param[in] FragmentCount The number of fragments.
894 @param[in] SadEntry The related SAD entry.
895 @param[out] RecycleEvent The event for recycling of resources.
897 @retval EFI_SUCCESS The operation was successful.
898 @retval EFI_UNSUPPORTED If the IPSEC protocol is not supported.
902 IpSecProtectOutboundPacket (
906 IN VOID
*OptionsBuffer
, OPTIONAL
907 IN UINT32 OptionsLength
, OPTIONAL
908 IN OUT EFI_IPSEC_FRAGMENT_DATA
**FragmentTable
,
909 IN UINT32
*FragmentCount
,
910 IN IPSEC_SAD_ENTRY
*SadEntry
,
911 OUT EFI_EVENT
*RecycleEvent
914 if (SadEntry
->Id
->Proto
== EfiIPsecESP
) {
916 // Process the esp ipsec header of the outbound traffic.
918 return IpSecEspOutboundPacket (
931 // The other protocols are not supported.
933 return EFI_UNSUPPORTED
;