+++ /dev/null
-/** @file\r
- The implementation of Payloads Creation.\r
-\r
- (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Utility.h"\r
-#include "IpSecDebug.h"\r
-#include "IpSecConfigImpl.h"\r
-#include "IpSecCryptIo.h"\r
-\r
-//\r
-// The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.\r
-//\r
-#define CONSTANT_KEY_SIZE 17\r
-GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey[CONSTANT_KEY_SIZE] =\r
-{\r
- 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'\r
-};\r
-\r
-/**\r
- Generate Ikev2 SA payload according to SessionSaData\r
-\r
- @param[in] SessionSaData The data used in SA payload.\r
- @param[in] NextPayload The payload type presented in NextPayload field of\r
- SA Payload header.\r
- @param[in] Type The SA type. It MUST be neither (1) for IKE_SA or\r
- (2) for CHILD_SA or (3) for INFO.\r
-\r
- @retval a Pointer to SA IKE payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateSaPayload (\r
- IN IKEV2_SA_DATA *SessionSaData,\r
- IN UINT8 NextPayload,\r
- IN IKE_SESSION_TYPE Type\r
- )\r
-{\r
- IKE_PAYLOAD *SaPayload;\r
- IKEV2_SA_DATA *SaData;\r
- UINTN SaDataSize;\r
-\r
- SaPayload = IkePayloadAlloc ();\r
- if (SaPayload == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // TODO: Get the Proposal Number and Transform Number from IPsec Config,\r
- // after the Ipsecconfig Application is support it.\r
- //\r
-\r
- if (Type == IkeSessionTypeIkeSa) {\r
- SaDataSize = sizeof (IKEV2_SA_DATA) +\r
- SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
- sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 4;\r
- } else {\r
- SaDataSize = sizeof (IKEV2_SA_DATA) +\r
- SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
- sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 3;\r
-\r
- }\r
-\r
- SaData = AllocateZeroPool (SaDataSize);\r
- if (SaData == NULL) {\r
- IkePayloadFree (SaPayload);\r
- return NULL;\r
- }\r
-\r
- CopyMem (SaData, SessionSaData, SaDataSize);\r
- SaData->SaHeader.Header.NextPayload = NextPayload;\r
- SaPayload->PayloadType = IKEV2_PAYLOAD_TYPE_SA;\r
- SaPayload->PayloadBuf = (UINT8 *) SaData;\r
-\r
- return SaPayload;\r
-}\r
-\r
-/**\r
- Generate a Nonce payload containing the input parameter NonceBuf.\r
-\r
- @param[in] NonceBuf The nonce buffer contains the whole Nonce payload block\r
- except the payload header.\r
- @param[in] NonceSize The buffer size of the NonceBuf\r
- @param[in] NextPayload The payload type presented in the NextPayload field\r
- of Nonce Payload header.\r
-\r
- @retval Pointer to Nonce IKE paload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateNoncePayload (\r
- IN UINT8 *NonceBuf,\r
- IN UINTN NonceSize,\r
- IN UINT8 NextPayload\r
- )\r
-{\r
- IKE_PAYLOAD *NoncePayload;\r
- IKEV2_NONCE *Nonce;\r
- UINTN Size;\r
- UINT8 *NonceBlock;\r
-\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Nonce Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- Size = sizeof (IKEV2_NONCE) + NonceSize;\r
- NonceBlock = NonceBuf;\r
-\r
- Nonce = AllocateZeroPool (Size);\r
- if (Nonce == NULL) {\r
- return NULL;\r
- }\r
-\r
- CopyMem (Nonce + 1, NonceBlock, Size - sizeof (IKEV2_NONCE));\r
-\r
- Nonce->Header.NextPayload = NextPayload;\r
- Nonce->Header.PayloadLength = (UINT16) Size;\r
- NoncePayload = IkePayloadAlloc ();\r
- if (NoncePayload == NULL) {\r
- FreePool (Nonce);\r
- return NULL;\r
- }\r
-\r
- NoncePayload->PayloadType = IKEV2_PAYLOAD_TYPE_NONCE;\r
- NoncePayload->PayloadBuf = (UINT8 *) Nonce;\r
- NoncePayload->PayloadSize = Size;\r
-\r
- return NoncePayload;\r
-}\r
-\r
-/**\r
- Generate a Key Exchange payload according to the DH group type and save the\r
- public Key into IkeSaSession IkeKey field.\r
-\r
- @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.\r
- @param[in] NextPayload The payload type presented in the NextPayload field of Key\r
- Exchange Payload header.\r
-\r
- @retval Pointer to Key IKE payload.\r
-\r
-**/\r
-IKE_PAYLOAD*\r
-Ikev2GenerateKePayload (\r
- IN OUT IKEV2_SA_SESSION *IkeSaSession,\r
- IN UINT8 NextPayload\r
- )\r
-{\r
- IKE_PAYLOAD *KePayload;\r
- IKEV2_KEY_EXCHANGE *Ke;\r
- UINTN KeSize;\r
- IKEV2_SESSION_KEYS *IkeKeys;\r
-\r
- //\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! DH Group # ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Key Exchange Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- IkeKeys = IkeSaSession->IkeKeys;\r
-\r
- if (IkeSaSession->SessionCommon.IsInitiator) {\r
- KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;\r
- } else {\r
- KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;\r
- }\r
-\r
- //\r
- // Allocate buffer for Key Exchange\r
- //\r
- Ke = AllocateZeroPool (KeSize);\r
- if (Ke == NULL) {\r
- return NULL;\r
- }\r
-\r
- Ke->Header.NextPayload = NextPayload;\r
- Ke->Header.PayloadLength = (UINT16) KeSize;\r
- Ke->DhGroup = IkeSaSession->SessionCommon.PreferDhGroup;\r
-\r
- CopyMem (Ke + 1, IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);\r
-\r
- //\r
- // Create IKE_PAYLOAD to point to Key Exchange payload\r
- //\r
- KePayload = IkePayloadAlloc ();\r
- if (KePayload == NULL) {\r
- FreePool (Ke);\r
- return NULL;\r
- }\r
-\r
- KePayload->PayloadType = IKEV2_PAYLOAD_TYPE_KE;\r
- KePayload->PayloadBuf = (UINT8 *) Ke;\r
- KePayload->PayloadSize = KeSize;\r
- return KePayload;\r
-}\r
-\r
-/**\r
- Generate a ID payload.\r
-\r
- @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.\r
- @param[in] NextPayload The payload type presented in the NextPayload field\r
- of ID Payload header.\r
-\r
- @retval Pointer to ID IKE payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateIdPayload (\r
- IN IKEV2_SESSION_COMMON *CommonSession,\r
- IN UINT8 NextPayload\r
- )\r
-{\r
- IKE_PAYLOAD *IdPayload;\r
- IKEV2_ID *Id;\r
- UINTN IdSize;\r
- UINT8 IpVersion;\r
- UINT8 AddrSize;\r
-\r
- //\r
- // ID payload\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload ! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! ID Type ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Identification Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- IpVersion = CommonSession->UdpService->IpVersion;\r
- AddrSize = (UINT8) ((IpVersion == IP_VERSION_4) ? sizeof(EFI_IPv4_ADDRESS) : sizeof(EFI_IPv6_ADDRESS));\r
- IdSize = sizeof (IKEV2_ID) + AddrSize;\r
-\r
- Id = (IKEV2_ID *) AllocateZeroPool (IdSize);\r
- if (Id == NULL) {\r
- return NULL;\r
- }\r
-\r
- IdPayload = IkePayloadAlloc ();\r
- if (IdPayload == NULL) {\r
- FreePool (Id);\r
- return NULL;\r
- }\r
-\r
- IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);\r
- IdPayload->PayloadBuf = (UINT8 *) Id;\r
- IdPayload->PayloadSize = IdSize;\r
-\r
- //\r
- // Set generic header of identification payload\r
- //\r
- Id->Header.NextPayload = NextPayload;\r
- Id->Header.PayloadLength = (UINT16) IdSize;\r
- Id->IdType = (UINT8) ((IpVersion == IP_VERSION_4) ? IKEV2_ID_TYPE_IPV4_ADDR : IKEV2_ID_TYPE_IPV6_ADDR);\r
- CopyMem (Id + 1, &CommonSession->LocalPeerIp, AddrSize);\r
-\r
- return IdPayload;\r
-}\r
-\r
-/**\r
- Generate a ID payload.\r
-\r
- @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.\r
- @param[in] NextPayload The payload type presented in the NextPayload field\r
- of ID Payload header.\r
- @param[in] InCert Pointer to the Certificate which distinguished name\r
- will be added into the Id payload.\r
- @param[in] CertSize Size of the Certificate.\r
-\r
- @retval Pointer to ID IKE payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateCertIdPayload (\r
- IN IKEV2_SESSION_COMMON *CommonSession,\r
- IN UINT8 NextPayload,\r
- IN UINT8 *InCert,\r
- IN UINTN CertSize\r
- )\r
-{\r
- IKE_PAYLOAD *IdPayload;\r
- IKEV2_ID *Id;\r
- UINTN IdSize;\r
- UINTN SubjectSize;\r
- UINT8 *CertSubject;\r
-\r
- //\r
- // ID payload\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload ! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! ID Type ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Identification Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- SubjectSize = 0;\r
- CertSubject = NULL;\r
- IpSecCryptoIoGetSubjectFromCert (\r
- InCert,\r
- CertSize,\r
- &CertSubject,\r
- &SubjectSize\r
- );\r
- if (SubjectSize != 0) {\r
- ASSERT (CertSubject != NULL);\r
- }\r
-\r
- IdSize = sizeof (IKEV2_ID) + SubjectSize;\r
-\r
- Id = (IKEV2_ID *) AllocateZeroPool (IdSize);\r
- if (Id == NULL) {\r
- return NULL;\r
- }\r
-\r
- IdPayload = IkePayloadAlloc ();\r
- if (IdPayload == NULL) {\r
- FreePool (Id);\r
- return NULL;\r
- }\r
-\r
- IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);\r
- IdPayload->PayloadBuf = (UINT8 *) Id;\r
- IdPayload->PayloadSize = IdSize;\r
-\r
- //\r
- // Set generic header of identification payload\r
- //\r
- Id->Header.NextPayload = NextPayload;\r
- Id->Header.PayloadLength = (UINT16) IdSize;\r
- Id->IdType = 9;\r
- CopyMem (Id + 1, CertSubject, SubjectSize);\r
-\r
- if (CertSubject != NULL) {\r
- FreePool (CertSubject);\r
- }\r
- return IdPayload;\r
-}\r
-\r
-/**\r
- Generate a Authentication Payload.\r
-\r
- This function is used for both Authentication generation and verification. When the\r
- IsVerify is TRUE, it create a Auth Data for verification. This function choose the\r
- related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type\r
- and the value of IsVerify parameter.\r
-\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.\r
- @param[in] IdPayload Pointer to the ID payload to be used for Authentication\r
- payload generation.\r
- @param[in] NextPayload The type filled into the Authentication Payload next\r
- payload field.\r
- @param[in] IsVerify If it is TURE, the Authentication payload is used for\r
- verification.\r
-\r
- @return pointer to IKE Authentication payload for Pre-shared key method.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2PskGenerateAuthPayload (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN IKE_PAYLOAD *IdPayload,\r
- IN UINT8 NextPayload,\r
- IN BOOLEAN IsVerify\r
- )\r
-{\r
- UINT8 *Digest;\r
- UINTN DigestSize;\r
- PRF_DATA_FRAGMENT Fragments[3];\r
- UINT8 *KeyBuf;\r
- UINTN KeySize;\r
- IKE_PAYLOAD *AuthPayload;\r
- IKEV2_AUTH *PayloadBuf;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
- //\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Auth Method ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Authentication Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- KeyBuf = NULL;\r
- AuthPayload = NULL;\r
- Digest = NULL;\r
-\r
- DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);\r
- Digest = AllocateZeroPool (DigestSize);\r
- if (Digest == NULL) {\r
- return NULL;\r
- }\r
-\r
- if (IdPayload == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Calcualte Prf(Seceret, "Key Pad for IKEv2");\r
- //\r
- Fragments[0].Data = (UINT8 *) mConstantKey;\r
- Fragments[0].DataSize = CONSTANT_KEY_SIZE;\r
-\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- IkeSaSession->Pad->Data->AuthData,\r
- IkeSaSession->Pad->Data->AuthDataSize,\r
- (HASH_DATA_FRAGMENT *)Fragments,\r
- 1,\r
- Digest,\r
- DigestSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Store the AuthKey into KeyBuf\r
- //\r
- KeyBuf = AllocateZeroPool (DigestSize);\r
- if (KeyBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- CopyMem (KeyBuf, Digest, DigestSize);\r
- KeySize = DigestSize;\r
-\r
- //\r
- // Calculate Prf(SK_Pi/r, IDi/r)\r
- //\r
- Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
- Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
-\r
- if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
- (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
- ) {\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- IkeSaSession->IkeKeys->SkPrKey,\r
- IkeSaSession->IkeKeys->SkPrKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- Digest,\r
- DigestSize\r
- );\r
- } else {\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- IkeSaSession->IkeKeys->SkPiKey,\r
- IkeSaSession->IkeKeys->SkPiKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- Digest,\r
- DigestSize\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Copy data to Fragments.\r
- //\r
- if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
- (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
- ) {\r
- Fragments[0].Data = IkeSaSession->RespPacket;\r
- Fragments[0].DataSize = IkeSaSession->RespPacketSize;\r
- Fragments[1].Data = IkeSaSession->NiBlock;\r
- Fragments[1].DataSize = IkeSaSession->NiBlkSize;\r
- } else {\r
- Fragments[0].Data = IkeSaSession->InitPacket;\r
- Fragments[0].DataSize = IkeSaSession->InitPacketSize;\r
- Fragments[1].Data = IkeSaSession->NrBlock;\r
- Fragments[1].DataSize = IkeSaSession->NrBlkSize;\r
- }\r
-\r
- //\r
- // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].\r
- //\r
- Fragments[2].Data = AllocateZeroPool (DigestSize);\r
- if (Fragments[2].Data == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- Fragments[2].DataSize = DigestSize;\r
- CopyMem (Fragments[2].Data, Digest, DigestSize);\r
-\r
- //\r
- // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
- //\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- KeyBuf,\r
- KeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 3,\r
- Digest,\r
- DigestSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Allocate buffer for Auth Payload\r
- //\r
- AuthPayload = IkePayloadAlloc ();\r
- if (AuthPayload == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;\r
- PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);\r
- if (PayloadBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Fill in Auth payload.\r
- //\r
- PayloadBuf->Header.NextPayload = NextPayload;\r
- PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);\r
- if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodPreSharedSecret) {\r
- //\r
- // Only support Shared Key Message Integrity\r
- //\r
- PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_SKMI;\r
- } else {\r
- //\r
- // Not support other Auth method.\r
- //\r
- Status = EFI_UNSUPPORTED;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth\r
- // payload block.\r
- //\r
- CopyMem (\r
- PayloadBuf + 1,\r
- Digest,\r
- DigestSize\r
- );\r
-\r
- //\r
- // Fill in IKE_PACKET\r
- //\r
- AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;\r
- AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;\r
-\r
-EXIT:\r
- if (KeyBuf != NULL) {\r
- FreePool (KeyBuf);\r
- }\r
- if (Digest != NULL) {\r
- FreePool (Digest);\r
- }\r
- if (Fragments[2].Data != NULL) {\r
- //\r
- // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)\r
- //\r
- FreePool (Fragments[2].Data);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- if (AuthPayload != NULL) {\r
- IkePayloadFree (AuthPayload);\r
- }\r
- return NULL;\r
- } else {\r
- return AuthPayload;\r
- }\r
-}\r
-\r
-/**\r
- Generate a Authentication Payload for Certificate Auth method.\r
-\r
- This function has two functions. One is creating a local Authentication\r
- Payload for sending and other is creating the remote Authentication data\r
- for verification when the IsVerify is TURE.\r
-\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.\r
- @param[in] IdPayload Pointer to the ID payload to be used for Authentication\r
- payload generation.\r
- @param[in] NextPayload The type filled into the Authentication Payload\r
- next payload field.\r
- @param[in] IsVerify If it is TURE, the Authentication payload is used\r
- for verification.\r
- @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when\r
- verify the authenticate payload.\r
- @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it\r
- when verify the authenticate payload.\r
- @param[in] UefiKeyPwd Pointer to the password of UEFI private key.\r
- Ignore it when verify the authenticate payload.\r
- @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when\r
- verify the authenticate payload.\r
-\r
- @return pointer to IKE Authentication payload for Cerifitcation method.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2CertGenerateAuthPayload (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN IKE_PAYLOAD *IdPayload,\r
- IN UINT8 NextPayload,\r
- IN BOOLEAN IsVerify,\r
- IN UINT8 *UefiPrivateKey,\r
- IN UINTN UefiPrivateKeyLen,\r
- IN UINT8 *UefiKeyPwd,\r
- IN UINTN UefiKeyPwdLen\r
- )\r
-{\r
- UINT8 *Digest;\r
- UINTN DigestSize;\r
- PRF_DATA_FRAGMENT Fragments[3];\r
- IKE_PAYLOAD *AuthPayload;\r
- IKEV2_AUTH *PayloadBuf;\r
- EFI_STATUS Status;\r
- UINT8 *Signature;\r
- UINTN SigSize;\r
-\r
- //\r
- // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
- //\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Auth Method ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Authentication Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- //\r
- // Initial point\r
- //\r
- AuthPayload = NULL;\r
- Digest = NULL;\r
- Signature = NULL;\r
- SigSize = 0;\r
-\r
- if (IdPayload == NULL) {\r
- return NULL;\r
- }\r
- DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);\r
- Digest = AllocateZeroPool (DigestSize);\r
- if (Digest == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Calculate Prf(SK_Pi/r, IDi/r)\r
- //\r
- Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
- Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
-\r
- IpSecDumpBuf ("RestofIDPayload", Fragments[0].Data, Fragments[0].DataSize);\r
-\r
- if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
- (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
- ) {\r
- Status = IpSecCryptoIoHmac(\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- IkeSaSession->IkeKeys->SkPrKey,\r
- IkeSaSession->IkeKeys->SkPrKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- Digest,\r
- DigestSize\r
- );\r
- IpSecDumpBuf ("MACedIDForR", Digest, DigestSize);\r
- } else {\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- IkeSaSession->IkeKeys->SkPiKey,\r
- IkeSaSession->IkeKeys->SkPiKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- Digest,\r
- DigestSize\r
- );\r
- IpSecDumpBuf ("MACedIDForI", Digest, DigestSize);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Copy data to Fragments.\r
- //\r
- if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
- (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
- ) {\r
- Fragments[0].Data = IkeSaSession->RespPacket;\r
- Fragments[0].DataSize = IkeSaSession->RespPacketSize;\r
- Fragments[1].Data = IkeSaSession->NiBlock;\r
- Fragments[1].DataSize = IkeSaSession->NiBlkSize;\r
- IpSecDumpBuf ("RealMessage2", Fragments[0].Data, Fragments[0].DataSize);\r
- IpSecDumpBuf ("NonceIDdata", Fragments[1].Data, Fragments[1].DataSize);\r
- } else {\r
- Fragments[0].Data = IkeSaSession->InitPacket;\r
- Fragments[0].DataSize = IkeSaSession->InitPacketSize;\r
- Fragments[1].Data = IkeSaSession->NrBlock;\r
- Fragments[1].DataSize = IkeSaSession->NrBlkSize;\r
- IpSecDumpBuf ("RealMessage1", Fragments[0].Data, Fragments[0].DataSize);\r
- IpSecDumpBuf ("NonceRDdata", Fragments[1].Data, Fragments[1].DataSize);\r
- }\r
-\r
- //\r
- // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].\r
- //\r
- Fragments[2].Data = AllocateZeroPool (DigestSize);\r
- if (Fragments[2].Data == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- Fragments[2].DataSize = DigestSize;\r
- CopyMem (Fragments[2].Data, Digest, DigestSize);\r
-\r
- //\r
- // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
- //\r
- Status = IpSecCryptoIoHash (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 3,\r
- Digest,\r
- DigestSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- IpSecDumpBuf ("HashSignedOctects", Digest, DigestSize);\r
- //\r
- // Sign the data by the private Key\r
- //\r
- if (!IsVerify) {\r
- IpSecCryptoIoAuthDataWithCertificate (\r
- Digest,\r
- DigestSize,\r
- UefiPrivateKey,\r
- UefiPrivateKeyLen,\r
- UefiKeyPwd,\r
- UefiKeyPwdLen,\r
- &Signature,\r
- &SigSize\r
- );\r
-\r
- if (SigSize == 0 || Signature == NULL) {\r
- goto EXIT;\r
- }\r
- }\r
-\r
- //\r
- // Allocate buffer for Auth Payload\r
- //\r
- AuthPayload = IkePayloadAlloc ();\r
- if (AuthPayload == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- if (!IsVerify) {\r
- AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + SigSize;\r
- } else {\r
- AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;\r
- }\r
-\r
- PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);\r
- if (PayloadBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Fill in Auth payload.\r
- //\r
- PayloadBuf->Header.NextPayload = NextPayload;\r
- PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);\r
- if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodCertificates) {\r
- PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_RSA;\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth\r
- // payload block.\r
- //\r
- if (!IsVerify) {\r
- CopyMem (PayloadBuf + 1, Signature, SigSize);\r
- } else {\r
- CopyMem (PayloadBuf + 1, Digest, DigestSize);\r
- }\r
-\r
- //\r
- // Fill in IKE_PACKET\r
- //\r
- AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;\r
- AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;\r
-\r
-EXIT:\r
- if (Digest != NULL) {\r
- FreePool (Digest);\r
- }\r
- if (Signature != NULL) {\r
- FreePool (Signature);\r
- }\r
- if (Fragments[2].Data != NULL) {\r
- //\r
- // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)\r
- //\r
- FreePool (Fragments[2].Data);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- if (AuthPayload != NULL) {\r
- IkePayloadFree (AuthPayload);\r
- }\r
- return NULL;\r
- } else {\r
- return AuthPayload;\r
- }\r
-}\r
-\r
-/**\r
- Generate TS payload.\r
-\r
- This function generates TSi or TSr payload according to type of next payload.\r
- If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate\r
- TSr payload.\r
-\r
- @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.\r
- @param[in] NextPayload The payload type presented in the NextPayload field\r
- of ID Payload header.\r
- @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.\r
- If yes, it means the Tsi and Tsr payload should be with\r
- Max port range and address range and protocol is marked\r
- as zero.\r
-\r
- @retval Pointer to Ts IKE payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateTsPayload (\r
- IN IKEV2_CHILD_SA_SESSION *ChildSa,\r
- IN UINT8 NextPayload,\r
- IN BOOLEAN IsTunnel\r
- )\r
-{\r
- IKE_PAYLOAD *TsPayload;\r
- IKEV2_TS *TsPayloadBuf;\r
- TRAFFIC_SELECTOR *TsSelector;\r
- UINTN SelectorSize;\r
- UINTN TsPayloadSize;\r
- UINT8 IpVersion;\r
- UINT8 AddrSize;\r
-\r
- //\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Number of TSs ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ <Traffic Selectors> ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- TsPayload = IkePayloadAlloc();\r
- if (TsPayload == NULL) {\r
- return NULL;\r
- }\r
-\r
- IpVersion = ChildSa->SessionCommon.UdpService->IpVersion;\r
- //\r
- // The Starting Address and Ending Address is variable length depends on\r
- // is IPv4 or IPv6\r
- //\r
- AddrSize = (UINT8)((IpVersion == IP_VERSION_4) ? sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS));\r
- SelectorSize = sizeof (TRAFFIC_SELECTOR) + 2 * AddrSize;\r
- TsPayloadSize = sizeof (IKEV2_TS) + SelectorSize;\r
- TsPayloadBuf = AllocateZeroPool (TsPayloadSize);\r
- if (TsPayloadBuf == NULL) {\r
- goto ON_ERROR;\r
- }\r
-\r
- TsPayload->PayloadBuf = (UINT8 *) TsPayloadBuf;\r
- TsSelector = (TRAFFIC_SELECTOR*)(TsPayloadBuf + 1);\r
-\r
- TsSelector->TSType = (UINT8)((IpVersion == IP_VERSION_4) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE : IKEV2_TS_TYPS_IPV6_ADDR_RANGE);\r
-\r
- //\r
- // For tunnel mode\r
- //\r
- if (IsTunnel) {\r
- TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;\r
- TsSelector->SelecorLen = (UINT16) SelectorSize;\r
- TsSelector->StartPort = 0;\r
- TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
- ZeroMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR), AddrSize);\r
- SetMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize, AddrSize, 0xff);\r
-\r
- } else {\r
- //\r
- // TODO: Support port range and address range\r
- //\r
- if (NextPayload == IKEV2_PAYLOAD_TYPE_TS_RSP){\r
- //\r
- // Create initiator Traffic Selector\r
- //\r
- TsSelector->SelecorLen = (UINT16)SelectorSize;\r
-\r
- //\r
- // Currently only support the port range from 0~0xffff. Don't support other\r
- // port range.\r
- // TODO: support Port range\r
- //\r
- if (ChildSa->SessionCommon.IsInitiator) {\r
- if (ChildSa->Spd->Selector->LocalPort != 0 &&\r
- ChildSa->Spd->Selector->LocalPortRange == 0) {\r
- //\r
- // For not port range.\r
- //\r
- TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;\r
- TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;\r
- } else if (ChildSa->Spd->Selector->LocalPort == 0){\r
- //\r
- // For port from 0~0xffff\r
- //\r
- TsSelector->StartPort = 0;\r
- TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
- } else {\r
- //\r
- // Not support now.\r
- //\r
- goto ON_ERROR;\r
- }\r
- } else {\r
- if (ChildSa->Spd->Selector->RemotePort != 0 &&\r
- ChildSa->Spd->Selector->RemotePortRange == 0) {\r
- //\r
- // For not port range.\r
- //\r
- TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;\r
- TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;\r
- } else if (ChildSa->Spd->Selector->RemotePort == 0) {\r
- //\r
- // For port from 0~0xffff\r
- //\r
- TsSelector->StartPort = 0;\r
- TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
- } else {\r
- //\r
- // Not support now.\r
- //\r
- goto ON_ERROR;\r
- }\r
- }\r
- //\r
- // Copy Address.Currently the address range is not supported.\r
- // The Starting address is same as Ending address\r
- // TODO: Support Address Range.\r
- //\r
- CopyMem (\r
- (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),\r
- ChildSa->SessionCommon.IsInitiator ?\r
- ChildSa->Spd->Selector->LocalAddress :\r
- ChildSa->Spd->Selector->RemoteAddress,\r
- AddrSize\r
- );\r
- CopyMem (\r
- (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,\r
- ChildSa->SessionCommon.IsInitiator ?\r
- ChildSa->Spd->Selector->LocalAddress :\r
- ChildSa->Spd->Selector->RemoteAddress,\r
- AddrSize\r
- );\r
- //\r
- // If the Next Payload is not TS responder, this TS payload type is the TS responder.\r
- //\r
- TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_INIT;\r
- }else{\r
- //\r
- // Create responder Traffic Selector\r
- //\r
- TsSelector->SelecorLen = (UINT16)SelectorSize;\r
-\r
- //\r
- // Currently only support the port range from 0~0xffff. Don't support other\r
- // port range.\r
- // TODO: support Port range\r
- //\r
- if (!ChildSa->SessionCommon.IsInitiator) {\r
- if (ChildSa->Spd->Selector->LocalPort != 0 &&\r
- ChildSa->Spd->Selector->LocalPortRange == 0) {\r
- //\r
- // For not port range.\r
- //\r
- TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;\r
- TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;\r
- } else if (ChildSa->Spd->Selector->LocalPort == 0){\r
- //\r
- // For port from 0~0xffff\r
- //\r
- TsSelector->StartPort = 0;\r
- TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
- } else {\r
- //\r
- // Not support now.\r
- //\r
- goto ON_ERROR;\r
- }\r
- } else {\r
- if (ChildSa->Spd->Selector->RemotePort != 0 &&\r
- ChildSa->Spd->Selector->RemotePortRange == 0) {\r
- //\r
- // For not port range.\r
- //\r
- TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;\r
- TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;\r
- } else if (ChildSa->Spd->Selector->RemotePort == 0){\r
- //\r
- // For port from 0~0xffff\r
- //\r
- TsSelector->StartPort = 0;\r
- TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
- } else {\r
- //\r
- // Not support now.\r
- //\r
- goto ON_ERROR;\r
- }\r
- }\r
- //\r
- // Copy Address.Currently the address range is not supported.\r
- // The Starting address is same as Ending address\r
- // TODO: Support Address Range.\r
- //\r
- CopyMem (\r
- (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),\r
- ChildSa->SessionCommon.IsInitiator ?\r
- ChildSa->Spd->Selector->RemoteAddress :\r
- ChildSa->Spd->Selector->LocalAddress,\r
- AddrSize\r
- );\r
- CopyMem (\r
- (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,\r
- ChildSa->SessionCommon.IsInitiator ?\r
- ChildSa->Spd->Selector->RemoteAddress :\r
- ChildSa->Spd->Selector->LocalAddress,\r
- AddrSize\r
- );\r
- //\r
- // If the Next Payload is not TS responder, this TS payload type is the TS responder.\r
- //\r
- TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_RSP;\r
- }\r
- }\r
-\r
- if (ChildSa->Spd->Selector->NextLayerProtocol != 0xffff) {\r
- TsSelector->IpProtocolId = (UINT8)ChildSa->Spd->Selector->NextLayerProtocol;\r
- } else {\r
- TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;\r
- }\r
-\r
- TsPayloadBuf->Header.NextPayload = NextPayload;\r
- TsPayloadBuf->Header.PayloadLength = (UINT16)TsPayloadSize;\r
- TsPayloadBuf->TSNumbers = 1;\r
- TsPayload->PayloadSize = TsPayloadSize;\r
- goto ON_EXIT;\r
-\r
-ON_ERROR:\r
- if (TsPayload != NULL) {\r
- IkePayloadFree (TsPayload);\r
- TsPayload = NULL;\r
- }\r
-ON_EXIT:\r
- return TsPayload;\r
-}\r
-\r
-/**\r
- Generate the Notify payload.\r
-\r
- Since the structure of Notify payload which defined in RFC 4306 is simple, so\r
- there is no internal data structure for Notify payload. This function generate\r
- Notify payload defined in RFC 4306, but all the fields in this payload are still\r
- in host order and need call Ikev2EncodePayload() to convert those fields from\r
- the host order to network order beforing sending it.\r
-\r
- @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).\r
- For IPsec SAs it MUST be neither (2) for AH or (3)\r
- for ESP.\r
- @param[in] NextPayload The next paylaod type in NextPayload field of\r
- the Notify payload.\r
- @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.\r
- @param[in] MessageType The message type in NotifyMessageType field of the\r
- Notify Payload.\r
- @param[in] SpiBuf Pointer to buffer contains the SPI value.\r
- @param[in] NotifyData Pointer to buffer contains the notification data.\r
- @param[in] NotifyDataSize The size of NotifyData in bytes.\r
-\r
-\r
- @retval Pointer to IKE Notify Payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateNotifyPayload (\r
- IN UINT8 ProtocolId,\r
- IN UINT8 NextPayload,\r
- IN UINT8 SpiSize,\r
- IN UINT16 MessageType,\r
- IN UINT8 *SpiBuf,\r
- IN UINT8 *NotifyData,\r
- IN UINTN NotifyDataSize\r
- )\r
-{\r
- IKE_PAYLOAD *NotifyPayload;\r
- IKEV2_NOTIFY *Notify;\r
- UINT16 NotifyPayloadLen;\r
- UINT8 *MessageData;\r
-\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Protocol ID ! SPI Size ! Notify Message Type !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Security Parameter Index (SPI) ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Notification Data ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- //\r
- NotifyPayloadLen = (UINT16) (sizeof (IKEV2_NOTIFY) + NotifyDataSize + SpiSize);\r
- Notify = (IKEV2_NOTIFY *) AllocateZeroPool (NotifyPayloadLen);\r
- if (Notify == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Set Delete Payload's Generic Header\r
- //\r
- Notify->Header.NextPayload = NextPayload;\r
- Notify->Header.PayloadLength = NotifyPayloadLen;\r
- Notify->SpiSize = SpiSize;\r
- Notify->ProtocolId = ProtocolId;\r
- Notify->MessageType = MessageType;\r
-\r
- //\r
- // Copy Spi , for Cookie Notify, there is no SPI.\r
- //\r
- if (SpiBuf != NULL && SpiSize != 0 ) {\r
- CopyMem (Notify + 1, SpiBuf, SpiSize);\r
- }\r
-\r
- MessageData = ((UINT8 *) (Notify + 1)) + SpiSize;\r
-\r
- //\r
- // Copy Notification Data\r
- //\r
- if (NotifyDataSize != 0) {\r
- CopyMem (MessageData, NotifyData, NotifyDataSize);\r
- }\r
-\r
- //\r
- // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY\r
- //\r
- NotifyPayload = IkePayloadAlloc ();\r
- if (NotifyPayload == NULL) {\r
- FreePool (Notify);\r
- return NULL;\r
- }\r
-\r
- NotifyPayload->PayloadType = IKEV2_PAYLOAD_TYPE_NOTIFY;\r
- NotifyPayload->PayloadBuf = (UINT8 *) Notify;\r
- NotifyPayload->PayloadSize = NotifyPayloadLen;\r
- return NotifyPayload;\r
-}\r
-\r
-/**\r
- Generate the Delete payload.\r
-\r
- Since the structure of Delete payload which defined in RFC 4306 is simple,\r
- there is no internal data structure for Delete payload. This function generate\r
- Delete payload defined in RFC 4306, but all the fields in this payload are still\r
- in host order and need call Ikev2EncodePayload() to convert those fields from\r
- the host order to network order beforing sending it.\r
-\r
- @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.\r
- @param[in] NextPayload The next paylaod type in NextPayload field of\r
- the Delete payload.\r
- @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.\r
- @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.\r
- @param[in] SpiBuf Pointer to buffer contains the SPI value.\r
-\r
- @retval a Pointer of IKE Delete Payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateDeletePayload (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN UINT8 NextPayload,\r
- IN UINT8 SpiSize,\r
- IN UINT16 SpiNum,\r
- IN UINT8 *SpiBuf\r
-\r
- )\r
-{\r
- IKE_PAYLOAD *DelPayload;\r
- IKEV2_DELETE *Del;\r
- UINT16 SpiBufSize;\r
- UINT16 DelPayloadLen;\r
-\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Protocol ID ! SPI Size ! # of SPIs !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Security Parameter Index(es) (SPI) ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- SpiBufSize = (UINT16) (SpiSize * SpiNum);\r
- if (SpiBufSize != 0 && SpiBuf == NULL) {\r
- return NULL;\r
- }\r
-\r
- DelPayloadLen = (UINT16) (sizeof (IKEV2_DELETE) + SpiBufSize);\r
-\r
- Del = AllocateZeroPool (DelPayloadLen);\r
- if (Del == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Set Delete Payload's Generic Header\r
- //\r
- Del->Header.NextPayload = NextPayload;\r
- Del->Header.PayloadLength = DelPayloadLen;\r
- Del->NumSpis = SpiNum;\r
- Del->SpiSize = SpiSize;\r
-\r
- if (SpiSize == 4) {\r
- //\r
- // TODO: should consider the AH if needs to support.\r
- //\r
- Del->ProtocolId = IPSEC_PROTO_IPSEC_ESP;\r
- } else {\r
- Del->ProtocolId = IPSEC_PROTO_ISAKMP;\r
- }\r
-\r
- //\r
- // Set Del Payload's Idntification Data\r
- //\r
- CopyMem (Del + 1, SpiBuf, SpiBufSize);\r
- DelPayload = IkePayloadAlloc ();\r
- if (DelPayload == NULL) {\r
- FreePool (Del);\r
- return NULL;\r
- }\r
-\r
- DelPayload->PayloadType = IKEV2_PAYLOAD_TYPE_DELETE;\r
- DelPayload->PayloadBuf = (UINT8 *) Del;\r
- DelPayload->PayloadSize = DelPayloadLen;\r
- return DelPayload;\r
-}\r
-\r
-/**\r
- Generate the Configuration payload.\r
-\r
- This function generate configuration payload defined in RFC 4306, but all the\r
- fields in this payload are still in host order and need call Ikev2EncodePayload()\r
- to convert those fields from the host order to network order beforing sending it.\r
-\r
- @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload\r
- generation.\r
- @param[in] NextPayload The next paylaod type in NextPayload field of\r
- the Delete payload.\r
- @param[in] CfgType The attribute type in the Configuration attribute.\r
-\r
- @retval Pointer to IKE CP Payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateCpPayload (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN UINT8 NextPayload,\r
- IN UINT8 CfgType\r
- )\r
-{\r
- IKE_PAYLOAD *CpPayload;\r
- IKEV2_CFG *Cfg;\r
- UINT16 PayloadLen;\r
- IKEV2_CFG_ATTRIBUTES *CfgAttributes;\r
-\r
- //\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! CFG Type ! RESERVED !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ Configuration Attributes ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- PayloadLen = (UINT16) (sizeof (IKEV2_CFG) + sizeof (IKEV2_CFG_ATTRIBUTES));\r
- Cfg = (IKEV2_CFG *) AllocateZeroPool (PayloadLen);\r
-\r
- if (Cfg == NULL) {\r
- return NULL;\r
- }\r
-\r
- CfgAttributes = (IKEV2_CFG_ATTRIBUTES *)((UINT8 *)Cfg + sizeof (IKEV2_CFG));\r
-\r
- //\r
- // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS\r
- // or INTERNAL_IP6_ADDRESS.\r
- //\r
-\r
- Cfg->Header.NextPayload = NextPayload;\r
- Cfg->Header.PayloadLength = PayloadLen;\r
- Cfg->CfgType = IKEV2_CFG_TYPE_REQUEST;\r
-\r
- CfgAttributes->AttritType = CfgType;\r
- CfgAttributes->ValueLength = 0;\r
-\r
- CpPayload = IkePayloadAlloc ();\r
- if (CpPayload == NULL) {\r
- if (Cfg != NULL) {\r
- FreePool (Cfg);\r
- }\r
- return NULL;\r
- }\r
-\r
- CpPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CP;\r
- CpPayload->PayloadBuf = (UINT8 *) Cfg;\r
- CpPayload->PayloadSize = PayloadLen;\r
- return CpPayload;\r
-}\r
-\r
-/**\r
- Parser the Notify Cookie payload.\r
-\r
- This function parses the Notify Cookie payload.If the Notify ProtocolId is not\r
- IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not\r
- the COOKIE, return EFI_INVALID_PARAMETER.\r
-\r
- @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the\r
- Notify Cookie payload.\r
- the Notify payload.\r
- @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.\r
-\r
- @retval EFI_SUCCESS The Notify Cookie Payload is valid.\r
- @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.\r
- @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2ParserNotifyCookiePayload (\r
- IN IKE_PAYLOAD *IkeNCookie,\r
- IN OUT IKEV2_SA_SESSION *IkeSaSession\r
- )\r
-{\r
- IKEV2_NOTIFY *NotifyPayload;\r
- UINTN NotifyDataSize;\r
-\r
- NotifyPayload = (IKEV2_NOTIFY *)IkeNCookie->PayloadBuf;\r
-\r
- if ((NotifyPayload->ProtocolId != IPSEC_PROTO_ISAKMP) ||\r
- (NotifyPayload->SpiSize != 0) ||\r
- (NotifyPayload->MessageType != IKEV2_NOTIFICATION_COOKIE)\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- NotifyDataSize = NotifyPayload->Header.PayloadLength - sizeof (IKEV2_NOTIFY);\r
- IkeSaSession->NCookie = AllocateZeroPool (NotifyDataSize);\r
- if (IkeSaSession->NCookie == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- IkeSaSession->NCookieSize = NotifyDataSize;\r
-\r
- CopyMem (\r
- IkeSaSession->NCookie,\r
- (UINT8 *)NotifyPayload + sizeof (IKEV2_NOTIFY),\r
- NotifyDataSize\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Generate the Certificate payload or Certificate Request Payload.\r
-\r
- Since the Certificate Payload structure is same with Certificate Request Payload,\r
- the only difference is that one contains the Certificate Data, other contains\r
- the acceptable certificateion CA. This function generate Certificate payload\r
- or Certificate Request Payload defined in RFC 4306, but all the fields\r
- in the payload are still in host order and need call Ikev2EncodePayload()\r
- to convert those fields from the host order to network order beforing sending it.\r
-\r
- @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload\r
- generation.\r
- @param[in] NextPayload The next paylaod type in NextPayload field of\r
- the Delete payload.\r
- @param[in] Certificate Pointer of buffer contains the certification data.\r
- @param[in] CertificateLen The length of Certificate in byte.\r
- @param[in] EncodeType Specified the Certificate Encodeing which is defined\r
- in RFC 4306.\r
- @param[in] IsRequest To indicate create Certificate Payload or Certificate\r
- Request Payload. If it is TURE, create Certificate\r
- Request Payload. Otherwise, create Certificate Payload.\r
-\r
- @retval a Pointer to IKE Payload whose payload buffer containing the Certificate\r
- payload or Certificated Request payload.\r
-\r
-**/\r
-IKE_PAYLOAD *\r
-Ikev2GenerateCertificatePayload (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN UINT8 NextPayload,\r
- IN UINT8 *Certificate,\r
- IN UINTN CertificateLen,\r
- IN UINT8 EncodeType,\r
- IN BOOLEAN IsRequest\r
- )\r
-{\r
- IKE_PAYLOAD *CertPayload;\r
- IKEV2_CERT *Cert;\r
- UINT16 PayloadLen;\r
- UINT8 *PublicKey;\r
- UINTN PublicKeyLen;\r
- HASH_DATA_FRAGMENT Fragment[1];\r
- UINT8 *HashData;\r
- UINTN HashDataSize;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // 1 2 3\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload !C! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Cert Encoding ! !\r
- // +-+-+-+-+-+-+-+-+ !\r
- // ~ Certificate Data/Authority ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
-\r
- Status = EFI_SUCCESS;\r
- PublicKey = NULL;\r
- PublicKeyLen = 0;\r
-\r
- if (!IsRequest) {\r
- PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + CertificateLen);\r
- } else {\r
- //\r
- // SHA1 Hash length is 20.\r
- //\r
- PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + 20);\r
- }\r
-\r
- Cert = AllocateZeroPool (PayloadLen);\r
- if (Cert == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Generate Certificate Payload or Certificate Request Payload.\r
- //\r
- Cert->Header.NextPayload = NextPayload;\r
- Cert->Header.PayloadLength = PayloadLen;\r
- Cert->CertEncoding = EncodeType;\r
- if (!IsRequest) {\r
- CopyMem (\r
- ((UINT8 *)Cert) + sizeof (IKEV2_CERT),\r
- Certificate,\r
- CertificateLen\r
- );\r
- } else {\r
- Status = IpSecCryptoIoGetPublicKeyFromCert (\r
- Certificate,\r
- CertificateLen,\r
- &PublicKey,\r
- &PublicKeyLen\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- Fragment[0].Data = PublicKey;\r
- Fragment[0].DataSize = PublicKeyLen;\r
- HashDataSize = IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC);\r
- HashData = AllocateZeroPool (HashDataSize);\r
- if (HashData == NULL) {\r
- goto ON_EXIT;\r
- }\r
-\r
- Status = IpSecCryptoIoHash (\r
- IKE_AALG_SHA1HMAC,\r
- Fragment,\r
- 1,\r
- HashData,\r
- HashDataSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- CopyMem (\r
- ((UINT8 *)Cert) + sizeof (IKEV2_CERT),\r
- HashData,\r
- HashDataSize\r
- );\r
- }\r
-\r
- CertPayload = IkePayloadAlloc ();\r
- if (CertPayload == NULL) {\r
- goto ON_EXIT;\r
- }\r
-\r
- if (!IsRequest) {\r
- CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERT;\r
- } else {\r
- CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERTREQ;\r
- }\r
-\r
- CertPayload->PayloadBuf = (UINT8 *) Cert;\r
- CertPayload->PayloadSize = PayloadLen;\r
- return CertPayload;\r
-\r
-ON_EXIT:\r
- if (Cert != NULL) {\r
- FreePool (Cert);\r
- }\r
- if (PublicKey != NULL) {\r
- FreePool (PublicKey);\r
- }\r
- return NULL;\r
-}\r
-\r
-/**\r
- Remove and free all IkePayloads in the specified IkePacket.\r
-\r
- @param[in] IkePacket The pointer of IKE_PACKET.\r
-\r
-**/\r
-VOID\r
-ClearAllPayloads (\r
- IN IKE_PACKET *IkePacket\r
- )\r
-{\r
- LIST_ENTRY *PayloadEntry;\r
- IKE_PAYLOAD *IkePayload;\r
- //\r
- // remove all payloads from list and free each payload.\r
- //\r
- while (!IsListEmpty (&IkePacket->PayloadList)) {\r
- PayloadEntry = IkePacket->PayloadList.ForwardLink;\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (PayloadEntry);\r
- IKE_PACKET_REMOVE_PAYLOAD (IkePacket, IkePayload);\r
- IkePayloadFree (IkePayload);\r
- }\r
-}\r
-\r
-/**\r
- Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.\r
-\r
- @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.\r
- @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.\r
-\r
- @retval return the pointer of IKEV2_SA.\r
-\r
-**/\r
-IKEV2_SA*\r
-Ikev2EncodeSa (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN IKEV2_SA_DATA *SaData\r
- )\r
-{\r
- IKEV2_SA *Sa;\r
- UINTN SaSize;\r
- IKEV2_PROPOSAL_DATA *ProposalData;\r
- IKEV2_TRANSFORM_DATA *TransformData;\r
- UINTN TotalTransforms;\r
- UINTN SaAttrsSize;\r
- UINTN TransformsSize;\r
- UINTN TransformSize;\r
- UINTN ProposalsSize;\r
- UINTN ProposalSize;\r
- UINTN ProposalIndex;\r
- UINTN TransformIndex;\r
- IKE_SA_ATTRIBUTE *SaAttribute;\r
- IKEV2_PROPOSAL *Proposal;\r
- IKEV2_TRANSFORM *Transform;\r
-\r
- //\r
- // Transform IKE_SA_DATA structure to IKE_SA Payload.\r
- // Header length is host order.\r
- // The returned IKE_SA struct should be freed by caller.\r
- //\r
- TotalTransforms = 0;\r
- //\r
- // Calculate the Proposal numbers and Transform numbers.\r
- //\r
- for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {\r
-\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1) + ProposalIndex;\r
- TotalTransforms += ProposalData->NumTransforms;\r
-\r
- }\r
- SaSize = sizeof (IKEV2_SA) +\r
- SaData->NumProposals * sizeof (IKEV2_PROPOSAL) +\r
- TotalTransforms * (sizeof (IKEV2_TRANSFORM) + MAX_SA_ATTRS_SIZE);\r
- //\r
- // Allocate buffer for IKE_SA.\r
- //\r
- Sa = AllocateZeroPool (SaSize);\r
- if (Sa == NULL) {\r
- return NULL;\r
- }\r
-\r
- CopyMem (Sa, SaData, sizeof (IKEV2_SA));\r
- Sa->Header.PayloadLength = (UINT16) sizeof (IKEV2_SA);\r
- ProposalsSize = 0;\r
- Proposal = (IKEV2_PROPOSAL *) (Sa + 1);\r
-\r
- //\r
- // Set IKE_PROPOSAL\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);\r
- for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {\r
- Proposal->ProposalIndex = ProposalData->ProposalIndex;\r
- Proposal->ProtocolId = ProposalData->ProtocolId;\r
- Proposal->NumTransforms = ProposalData->NumTransforms;\r
-\r
- if (ProposalData->Spi == 0) {\r
- Proposal->SpiSize = 0;\r
- } else {\r
- Proposal->SpiSize = 4;\r
- *(UINT32 *) (Proposal + 1) = HTONL (*((UINT32*)ProposalData->Spi));\r
- }\r
-\r
- TransformsSize = 0;\r
- Transform = (IKEV2_TRANSFORM *) ((UINT8 *) (Proposal + 1) + Proposal->SpiSize);\r
-\r
- //\r
- // Set IKE_TRANSFORM\r
- //\r
- for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;\r
- Transform->TransformType = TransformData->TransformType;\r
- Transform->TransformId = HTONS (TransformData->TransformId);\r
- SaAttrsSize = 0;\r
-\r
- //\r
- // If the Encryption Algorithm is variable key length set the key length in attribute.\r
- // Note that only a single attribute type (Key Length) is defined and it is fixed length.\r
- //\r
- if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_ENCR && TransformData->Attribute.Attr.AttrValue != 0) {\r
- SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);\r
- SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);\r
- SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);\r
- SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);\r
- }\r
-\r
- //\r
- // If the Integrity Algorithm is variable key length set the key length in attribute.\r
- //\r
- if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_INTEG && TransformData->Attribute.Attr.AttrValue != 0) {\r
- SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);\r
- SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);\r
- SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);\r
- SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);\r
- }\r
-\r
- TransformSize = sizeof (IKEV2_TRANSFORM) + SaAttrsSize;\r
- TransformsSize += TransformSize;\r
-\r
- Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_MORE;\r
- Transform->Header.PayloadLength = HTONS ((UINT16)TransformSize);\r
-\r
- if (TransformIndex == ((UINT32)ProposalData->NumTransforms - 1)) {\r
- Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_NONE;\r
- }\r
-\r
- Transform = (IKEV2_TRANSFORM *)((UINT8 *) Transform + TransformSize);\r
- }\r
-\r
- //\r
- // Set Proposal's Generic Header.\r
- //\r
- ProposalSize = sizeof (IKEV2_PROPOSAL) + Proposal->SpiSize + TransformsSize;\r
- ProposalsSize += ProposalSize;\r
- Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_MORE;\r
- Proposal->Header.PayloadLength = HTONS ((UINT16)ProposalSize);\r
-\r
- if (ProposalIndex == (UINTN)(SaData->NumProposals - 1)) {\r
- Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_NONE;\r
- }\r
-\r
- //\r
- // Point to next Proposal Payload\r
- //\r
- Proposal = (IKEV2_PROPOSAL *) ((UINT8 *) Proposal + ProposalSize);\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)(((UINT8 *)ProposalData) + sizeof (IKEV2_PROPOSAL_DATA) + (TransformIndex * sizeof (IKEV2_TRANSFORM_DATA)));\r
- }\r
- //\r
- // Set SA's Generic Header.\r
- //\r
- Sa->Header.PayloadLength = (UINT16) (Sa->Header.PayloadLength + ProposalsSize);\r
- return Sa;\r
-}\r
-\r
-/**\r
- Decode SA payload.\r
-\r
- This function converts the received SA payload to internal data structure.\r
-\r
- @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA\r
- Payload.\r
- @param[in] Sa Pointer to SA Payload\r
-\r
- @return a Pointer to internal data structure for SA payload.\r
-\r
-**/\r
-IKEV2_SA_DATA *\r
-Ikev2DecodeSa (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN IKEV2_SA *Sa\r
- )\r
-{\r
- IKEV2_SA_DATA *SaData;\r
- EFI_STATUS Status;\r
- IKEV2_PROPOSAL *Proposal;\r
- IKEV2_TRANSFORM *Transform;\r
- UINTN TotalProposals;\r
- UINTN TotalTransforms;\r
- UINTN ProposalNextPayloadSum;\r
- UINTN ProposalIndex;\r
- UINTN TransformIndex;\r
- UINTN SaRemaining;\r
- UINT16 ProposalSize;\r
- UINTN ProposalRemaining;\r
- UINT16 TransformSize;\r
- UINTN SaAttrRemaining;\r
- IKE_SA_ATTRIBUTE *SaAttribute;\r
- IKEV2_PROPOSAL_DATA *ProposalData;\r
- IKEV2_TRANSFORM_DATA *TransformData;\r
- UINT8 *Spi;\r
-\r
- //\r
- // Transfrom from IKE_SA payload to IKE_SA_DATA structure.\r
- // Header length NTOH is already done\r
- // The returned IKE_SA_DATA should be freed by caller\r
- //\r
- SaData = NULL;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // First round sanity check and size calculae\r
- //\r
- TotalProposals = 0;\r
- TotalTransforms = 0;\r
- ProposalNextPayloadSum = 0;\r
- SaRemaining = Sa->Header.PayloadLength - sizeof (IKEV2_SA);// Point to current position in SA\r
- Proposal = (IKEV2_PROPOSAL *)((IKEV2_SA *)(Sa)+1);\r
-\r
- //\r
- // Calculate the number of Proposal payload and the total numbers of\r
- // Transforms payload (the transforms in all proposal payload).\r
- //\r
- while (SaRemaining > sizeof (IKEV2_PROPOSAL)) {\r
- ProposalSize = NTOHS (Proposal->Header.PayloadLength);\r
- if (SaRemaining < ProposalSize) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- if (Proposal->SpiSize != 0 && Proposal->SpiSize != 4) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- TotalProposals++;\r
- TotalTransforms += Proposal->NumTransforms;\r
- SaRemaining -= ProposalSize;\r
- ProposalNextPayloadSum += Proposal->Header.NextPayload;\r
- Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);\r
- }\r
-\r
- //\r
- // Check the proposal number.\r
- // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)\r
- // which Specifies whether this is the last Proposal Substructure in the SA.\r
- // Here suming all Proposal NextPayLoad field to check the proposal number is correct\r
- // or not.\r
- //\r
- if (TotalProposals == 0 ||\r
- (TotalProposals - 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE != ProposalNextPayloadSum\r
- ) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // Second round sanity check and decode. Transform the SA payload into\r
- // a IKE_SA_DATA structure.\r
- //\r
- SaData = (IKEV2_SA_DATA *) AllocateZeroPool (\r
- sizeof (IKEV2_SA_DATA) +\r
- TotalProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
- TotalTransforms * sizeof (IKEV2_TRANSFORM_DATA)\r
- );\r
- if (SaData == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- CopyMem (SaData, Sa, sizeof (IKEV2_SA));\r
- SaData->NumProposals = TotalProposals;\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);\r
-\r
- //\r
- // Proposal Payload\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload ! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! SPI (variable) !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- for (ProposalIndex = 0, Proposal = IKEV2_SA_FIRST_PROPOSAL (Sa);\r
- ProposalIndex < TotalProposals;\r
- ProposalIndex++\r
- ) {\r
-\r
- //\r
- // TODO: check ProposalId\r
- //\r
- ProposalData->ProposalIndex = Proposal->ProposalIndex;\r
- ProposalData->ProtocolId = Proposal->ProtocolId;\r
- if (Proposal->SpiSize == 0) {\r
- ProposalData->Spi = 0;\r
- } else {\r
- //\r
- // SpiSize == 4\r
- //\r
- Spi = AllocateZeroPool (Proposal->SpiSize);\r
- if (Spi == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- CopyMem (Spi, (UINT32 *) (Proposal + 1), Proposal->SpiSize);\r
- *((UINT32*) Spi) = NTOHL (*((UINT32*) Spi));\r
- ProposalData->Spi = Spi;\r
- }\r
-\r
- ProposalData->NumTransforms = Proposal->NumTransforms;\r
- ProposalSize = NTOHS (Proposal->Header.PayloadLength);\r
- ProposalRemaining = ProposalSize;\r
- //\r
- // Transform Payload\r
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! Next Payload ! RESERVED ! Payload Length !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // !Transform Type ! RESERVED ! Transform ID !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- // ! !\r
- // ~ SA Attributes ~\r
- // ! !\r
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
- //\r
- Transform = IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal);\r
- for (TransformIndex = 0; TransformIndex < Proposal->NumTransforms; TransformIndex++) {\r
-\r
- //\r
- // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;\r
- TransformData->TransformId = NTOHS (Transform->TransformId);\r
- TransformData->TransformType = Transform->TransformType;\r
- TransformSize = NTOHS (Transform->Header.PayloadLength);\r
- //\r
- // Check the Proposal Data is correct.\r
- //\r
- if (ProposalRemaining < TransformSize) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // Check if the Transform payload includes Attribution.\r
- //\r
- SaAttrRemaining = TransformSize - sizeof (IKEV2_TRANSFORM);\r
-\r
- //\r
- // According to RFC 4603, currently only the Key length attribute type is\r
- // supported. For each Transform, there is only one attributeion.\r
- //\r
- if (SaAttrRemaining > 0) {\r
- if (SaAttrRemaining != sizeof (IKE_SA_ATTRIBUTE)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
- SaAttribute = (IKE_SA_ATTRIBUTE *) ((IKEV2_TRANSFORM *)(Transform) + 1);\r
- TransformData->Attribute.AttrType = (UINT16)((NTOHS (SaAttribute->AttrType)) & ~SA_ATTR_FORMAT_BIT);\r
- TransformData->Attribute.Attr.AttrValue = NTOHS (SaAttribute->Attr.AttrValue);\r
-\r
- //\r
- // Currently, only supports the Key Length Attribution.\r
- //\r
- if (TransformData->Attribute.AttrType != IKEV2_ATTRIBUTE_TYPE_KEYLEN) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
- }\r
-\r
- //\r
- // Move to next Transform\r
- //\r
- Transform = IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform, TransformSize);\r
- }\r
- Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) ((UINT8 *)(ProposalData + 1) +\r
- ProposalData->NumTransforms *\r
- sizeof (IKEV2_TRANSFORM_DATA));\r
- }\r
-\r
-Exit:\r
- if (EFI_ERROR (Status) && SaData != NULL) {\r
- FreePool (SaData);\r
- SaData = NULL;\r
- }\r
- return SaData;\r
-}\r
-\r
-/**\r
- General interface of payload encoding.\r
-\r
- This function encodes the internal data structure into payload which\r
- is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input\r
- payload and converted payload. Only the SA payload use the interal structure\r
- to store the attribute. Other payload use structure which is same with the RFC\r
- defined, for this kind payloads just do host order to network order change of\r
- some fields.\r
-\r
- @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.\r
- @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and\r
- store the encoded result as output.\r
-\r
- @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.\r
- @retval EFI_SUCCESS Encoded successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2EncodePayload (\r
- IN UINT8 *SessionCommon,\r
- IN OUT IKE_PAYLOAD *IkePayload\r
- )\r
-{\r
- IKEV2_SA_DATA *SaData;\r
- IKEV2_SA *SaPayload;\r
- IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
- IKEV2_NOTIFY *NotifyPayload;\r
- IKEV2_DELETE *DeletePayload;\r
- IKEV2_KEY_EXCHANGE *KeyPayload;\r
- IKEV2_TS *TsPayload;\r
- IKEV2_CFG_ATTRIBUTES *CfgAttribute;\r
- UINT8 *TsBuffer;\r
- UINT8 Index;\r
- TRAFFIC_SELECTOR *TrafficSelector;\r
-\r
- //\r
- // Transform the Internal IKE structure to IKE payload.\r
- // Only the SA payload use the interal structure to store the attribute.\r
- // Other payload use structure which same with the RFC defined, so there is\r
- // no need to tranform them to IKE payload.\r
- //\r
- switch (IkePayload->PayloadType) {\r
- case IKEV2_PAYLOAD_TYPE_SA:\r
- //\r
- // Transform IKE_SA_DATA to IK_SA payload\r
- //\r
- SaData = (IKEV2_SA_DATA *) IkePayload->PayloadBuf;\r
- SaPayload = Ikev2EncodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, SaData);\r
-\r
- if (SaPayload == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- if (!IkePayload->IsPayloadBufExt) {\r
- FreePool (IkePayload->PayloadBuf);\r
- }\r
- IkePayload->PayloadBuf = (UINT8 *) SaPayload;\r
- IkePayload->IsPayloadBufExt = FALSE;\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_NOTIFY:\r
- NotifyPayload = (IKEV2_NOTIFY *) IkePayload->PayloadBuf;\r
- NotifyPayload->MessageType = HTONS (NotifyPayload->MessageType);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_DELETE:\r
- DeletePayload = (IKEV2_DELETE *) IkePayload->PayloadBuf;\r
- DeletePayload->NumSpis = HTONS (DeletePayload->NumSpis);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_KE:\r
- KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;\r
- KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_TS_INIT:\r
- case IKEV2_PAYLOAD_TYPE_TS_RSP:\r
- TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;\r
- TsBuffer = IkePayload->PayloadBuf + sizeof (IKEV2_TS);\r
-\r
- for (Index = 0; Index < TsPayload->TSNumbers; Index++) {\r
- TrafficSelector = (TRAFFIC_SELECTOR *) TsBuffer;\r
- TsBuffer = TsBuffer + TrafficSelector->SelecorLen;\r
- //\r
- // Host order to network order\r
- //\r
- TrafficSelector->SelecorLen = HTONS (TrafficSelector->SelecorLen);\r
- TrafficSelector->StartPort = HTONS (TrafficSelector->StartPort);\r
- TrafficSelector->EndPort = HTONS (TrafficSelector->EndPort);\r
-\r
- }\r
-\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_CP:\r
- CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);\r
- CfgAttribute->AttritType = HTONS (CfgAttribute->AttritType);\r
- CfgAttribute->ValueLength = HTONS (CfgAttribute->ValueLength);\r
-\r
- case IKEV2_PAYLOAD_TYPE_ID_INIT:\r
- case IKEV2_PAYLOAD_TYPE_ID_RSP:\r
- case IKEV2_PAYLOAD_TYPE_AUTH:\r
- default:\r
- break;\r
- }\r
-\r
- PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;\r
- IkePayload->PayloadSize = PayloadHdr->PayloadLength;\r
- PayloadHdr->PayloadLength = HTONS (PayloadHdr->PayloadLength);\r
- IKEV2_DUMP_PAYLOAD (IkePayload);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- The general interface for decoding Payload.\r
-\r
- This function converts the received Payload into internal structure.\r
-\r
- @param[in] SessionCommon Pointer to IKE Session Common used for decoding.\r
- @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and\r
- store the decoded result as output.\r
-\r
- @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.\r
- @retval EFI_SUCCESS Decoded successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2DecodePayload (\r
- IN UINT8 *SessionCommon,\r
- IN OUT IKE_PAYLOAD *IkePayload\r
- )\r
-{\r
- IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
- UINT16 PayloadSize;\r
- UINT8 PayloadType;\r
- IKEV2_SA_DATA *SaData;\r
- EFI_STATUS Status;\r
- IKEV2_NOTIFY *NotifyPayload;\r
- IKEV2_DELETE *DeletePayload;\r
- UINT16 TsTotalSize;\r
- TRAFFIC_SELECTOR *TsSelector;\r
- IKEV2_TS *TsPayload;\r
- IKEV2_KEY_EXCHANGE *KeyPayload;\r
- IKEV2_CFG_ATTRIBUTES *CfgAttribute;\r
- UINT8 Index;\r
-\r
- //\r
- // Transform the IKE payload to Internal IKE structure.\r
- // Only the SA payload and Hash Payload use the interal\r
- // structure to store the attribute. Other payloads use\r
- // structure which is same with the definitions in RFC,\r
- // so there is no need to tranform them to internal IKE\r
- // structure.\r
- //\r
- Status = EFI_SUCCESS;\r
- PayloadSize = (UINT16) IkePayload->PayloadSize;\r
- PayloadType = IkePayload->PayloadType;\r
- PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;\r
- //\r
- // The PayloadSize is the size of whole payload.\r
- // Replace HTONS operation to assignment statements, since the result is same.\r
- //\r
- PayloadHdr->PayloadLength = PayloadSize;\r
-\r
- IKEV2_DUMP_PAYLOAD (IkePayload);\r
- switch (PayloadType) {\r
- case IKEV2_PAYLOAD_TYPE_SA:\r
- if (PayloadSize < sizeof (IKEV2_SA)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- SaData = Ikev2DecodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, (IKEV2_SA *) PayloadHdr);\r
- if (SaData == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- if (!IkePayload->IsPayloadBufExt) {\r
- FreePool (IkePayload->PayloadBuf);\r
- }\r
-\r
- IkePayload->PayloadBuf = (UINT8 *) SaData;\r
- IkePayload->IsPayloadBufExt = FALSE;\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_ID_INIT:\r
- case IKEV2_PAYLOAD_TYPE_ID_RSP :\r
- if (PayloadSize < sizeof (IKEV2_ID)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_NOTIFY:\r
- if (PayloadSize < sizeof (IKEV2_NOTIFY)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- NotifyPayload = (IKEV2_NOTIFY *) PayloadHdr;\r
- NotifyPayload->MessageType = NTOHS (NotifyPayload->MessageType);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_DELETE:\r
- if (PayloadSize < sizeof (IKEV2_DELETE)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- DeletePayload = (IKEV2_DELETE *) PayloadHdr;\r
- DeletePayload->NumSpis = NTOHS (DeletePayload->NumSpis);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_AUTH:\r
- if (PayloadSize < sizeof (IKEV2_AUTH)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_KE:\r
- KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;\r
- KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);\r
- break;\r
-\r
- case IKEV2_PAYLOAD_TYPE_TS_INIT:\r
- case IKEV2_PAYLOAD_TYPE_TS_RSP :\r
- TsTotalSize = 0;\r
- if (PayloadSize < sizeof (IKEV2_TS)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
- //\r
- // Parse each traffic selector and transfer network-order to host-order\r
- //\r
- TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;\r
- TsSelector = (TRAFFIC_SELECTOR *) (IkePayload->PayloadBuf + sizeof (IKEV2_TS));\r
-\r
- for (Index = 0; Index < TsPayload->TSNumbers; Index++) {\r
- TsSelector->SelecorLen = NTOHS (TsSelector->SelecorLen);\r
- TsSelector->StartPort = NTOHS (TsSelector->StartPort);\r
- TsSelector->EndPort = NTOHS (TsSelector->EndPort);\r
-\r
- TsTotalSize = (UINT16) (TsTotalSize + TsSelector->SelecorLen);\r
- TsSelector = (TRAFFIC_SELECTOR *) ((UINT8 *) TsSelector + TsSelector->SelecorLen);\r
- }\r
- //\r
- // Check if the total size of Traffic Selectors is correct.\r
- //\r
- if (TsTotalSize != PayloadSize - sizeof(IKEV2_TS)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
- case IKEV2_PAYLOAD_TYPE_CP:\r
- CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);\r
- CfgAttribute->AttritType = NTOHS (CfgAttribute->AttritType);\r
- CfgAttribute->ValueLength = NTOHS (CfgAttribute->ValueLength);\r
-\r
- default:\r
- break;\r
- }\r
-\r
- Exit:\r
- return Status;\r
-}\r
-\r
-/**\r
- Decode the IKE packet.\r
-\r
- This function first decrypts the IKE packet if needed , then separates the whole\r
- IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.\r
-\r
- @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing\r
- some parameter used by IKE packet decoding.\r
- @param[in, out] IkePacket The IKE Packet to be decoded on input, and\r
- the decoded result on return.\r
- @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
- IKE_CHILD_TYPE are supported.\r
-\r
- @retval EFI_SUCCESS The IKE packet is decoded successfully.\r
- @retval Otherwise The IKE packet decoding is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2DecodePacket (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN OUT IKE_PACKET *IkePacket,\r
- IN UINTN IkeType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
- UINT8 PayloadType;\r
- UINTN RemainBytes;\r
- UINT16 PayloadSize;\r
- IKE_PAYLOAD *IkePayload;\r
- IKE_HEADER *IkeHeader;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
-\r
- IkeHeader = NULL;\r
-\r
- //\r
- // Check if the IkePacket need decrypt.\r
- //\r
- if (SessionCommon->State >= IkeStateAuth) {\r
- Status = Ikev2DecryptPacket (SessionCommon, IkePacket, IkeType);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // If the IkePacket doesn't contain any payload return invalid parameter.\r
- //\r
- if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE) {\r
- if ((SessionCommon->State >= IkeStateAuth) &&\r
- (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INFO)\r
- ) {\r
- //\r
- // If it is Liveness check, there will be no payload load in the encrypt payload.\r
- //\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // If the PayloadTotalSize < Header length, return invalid parameter.\r
- //\r
- RemainBytes = IkePacket->PayloadTotalSize;\r
- if (RemainBytes < sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // If the packet is first or second message, store whole message in\r
- // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload\r
- // calculate.\r
- //\r
- if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {\r
- IkeHeader = AllocateZeroPool (sizeof (IKE_HEADER));\r
- if (IkeHeader == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- CopyMem (IkeHeader, IkePacket->Header, sizeof (IKE_HEADER));\r
-\r
- //\r
- // Before store the whole packet, roll back the host order to network order,\r
- // since the header order was changed in the IkePacketFromNetbuf.\r
- //\r
- IkeHdrNetToHost (IkeHeader);\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
- if (SessionCommon->IsInitiator) {\r
- IkeSaSession->RespPacket = AllocateZeroPool (IkePacket->Header->Length);\r
- if (IkeSaSession->RespPacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
- IkeSaSession->RespPacketSize = IkePacket->Header->Length;\r
- CopyMem (IkeSaSession->RespPacket, IkeHeader, sizeof (IKE_HEADER));\r
- CopyMem (\r
- IkeSaSession->RespPacket + sizeof (IKE_HEADER),\r
- IkePacket->PayloadsBuf,\r
- IkePacket->Header->Length - sizeof (IKE_HEADER)\r
- );\r
- } else {\r
- IkeSaSession->InitPacket = AllocateZeroPool (IkePacket->Header->Length);\r
- if (IkeSaSession->InitPacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
- IkeSaSession->InitPacketSize = IkePacket->Header->Length;\r
- CopyMem (IkeSaSession->InitPacket, IkeHeader, sizeof (IKE_HEADER));\r
- CopyMem (\r
- IkeSaSession->InitPacket + sizeof (IKE_HEADER),\r
- IkePacket->PayloadsBuf,\r
- IkePacket->Header->Length - sizeof (IKE_HEADER)\r
- );\r
- }\r
- }\r
-\r
- //\r
- // Point to the first Payload\r
- //\r
- PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePacket->PayloadsBuf;\r
- PayloadType = IkePacket->Header->NextPayload;\r
-\r
- //\r
- // Parse each payload\r
- //\r
- while (RemainBytes >= sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {\r
- PayloadSize = NTOHS (PayloadHdr->PayloadLength);\r
-\r
- //\r
- //Check the size of the payload is correct.\r
- //\r
- if (RemainBytes < PayloadSize) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // At certain states, it should save some datas before decoding.\r
- //\r
- if (SessionCommon->BeforeDecodePayload != NULL) {\r
- SessionCommon->BeforeDecodePayload (\r
- (UINT8 *) SessionCommon,\r
- (UINT8 *) PayloadHdr,\r
- PayloadSize,\r
- PayloadType\r
- );\r
- }\r
-\r
- //\r
- // Initial IkePayload\r
- //\r
- IkePayload = IkePayloadAlloc ();\r
- if (IkePayload == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- IkePayload->PayloadType = PayloadType;\r
- IkePayload->PayloadBuf = (UINT8 *) PayloadHdr;\r
- IkePayload->PayloadSize = PayloadSize;\r
- IkePayload->IsPayloadBufExt = TRUE;\r
-\r
- Status = Ikev2DecodePayload ((UINT8 *) SessionCommon, IkePayload);\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
-\r
- IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload->PayloadBuf, IkePayload->PayloadSize);\r
- //\r
- // Add each payload into packet\r
- // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length\r
- // which is before the decoding.\r
- //\r
- IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);\r
-\r
- RemainBytes -= PayloadSize;\r
- PayloadType = PayloadHdr->NextPayload;\r
- if (PayloadType == IKEV2_PAYLOAD_TYPE_NONE) {\r
- break;\r
- }\r
-\r
- PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) ((UINT8 *) PayloadHdr + PayloadSize);\r
- }\r
-\r
- if (PayloadType != IKEV2_PAYLOAD_TYPE_NONE) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
- }\r
-\r
-Exit:\r
- if (EFI_ERROR (Status)) {\r
- ClearAllPayloads (IkePacket);\r
- }\r
-\r
- if (IkeHeader != NULL) {\r
- FreePool (IkeHeader);\r
- }\r
- return Status;\r
-}\r
-\r
-/**\r
- Encode the IKE packet.\r
-\r
- This function puts all Payloads into one payload then encrypt it if needed.\r
-\r
- @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing\r
- some parameter used during IKE packet encoding.\r
- @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,\r
- and the encoded result as output.\r
- @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
- IKE_CHILD_TYPE are supportted.\r
-\r
- @retval EFI_SUCCESS Encode IKE packet successfully.\r
- @retval Otherwise Encode IKE packet failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2EncodePacket (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN OUT IKE_PACKET *IkePacket,\r
- IN UINTN IkeType\r
- )\r
-{\r
- IKE_PAYLOAD *IkePayload;\r
- UINTN PayloadTotalSize;\r
- LIST_ENTRY *Entry;\r
- EFI_STATUS Status;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
-\r
- PayloadTotalSize = 0;\r
- //\r
- // Encode each payload\r
- //\r
- for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
- Entry = Entry->ForwardLink;\r
- Status = Ikev2EncodePayload ((UINT8 *) SessionCommon, IkePayload);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if (SessionCommon->AfterEncodePayload != NULL) {\r
- //\r
- // For certain states, save some payload for further calculation\r
- //\r
- SessionCommon->AfterEncodePayload (\r
- (UINT8 *) SessionCommon,\r
- IkePayload->PayloadBuf,\r
- IkePayload->PayloadSize,\r
- IkePayload->PayloadType\r
- );\r
- }\r
-\r
- PayloadTotalSize += IkePayload->PayloadSize;\r
- }\r
- IkePacket->PayloadTotalSize = PayloadTotalSize;\r
-\r
- Status = EFI_SUCCESS;\r
- if (SessionCommon->State >= IkeStateAuth) {\r
- //\r
- // Encrypt all payload and transfer IKE packet header from Host order to Network order.\r
- //\r
- Status = Ikev2EncryptPacket (SessionCommon, IkePacket);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- } else {\r
- //\r
- // Fill in the lenght into IkePacket header and transfer Host order to Network order.\r
- //\r
- IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);\r
- IkeHdrHostToNet (IkePacket->Header);\r
- }\r
-\r
- //\r
- // If the packet is first message, store whole message in IkeSa->InitiPacket\r
- // for following Auth Payload calculation.\r
- //\r
- if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
- if (SessionCommon->IsInitiator) {\r
- IkeSaSession->InitPacketSize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);\r
- IkeSaSession->InitPacket = AllocateZeroPool (IkeSaSession->InitPacketSize);\r
- if (IkeSaSession->InitPacket == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- CopyMem (IkeSaSession->InitPacket, IkePacket->Header, sizeof (IKE_HEADER));\r
- PayloadTotalSize = 0;\r
- for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
- Entry = Entry->ForwardLink;\r
- CopyMem (\r
- IkeSaSession->InitPacket + sizeof (IKE_HEADER) + PayloadTotalSize,\r
- IkePayload->PayloadBuf,\r
- IkePayload->PayloadSize\r
- );\r
- PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;\r
- }\r
- } else {\r
- IkeSaSession->RespPacketSize = IkePacket->PayloadTotalSize + sizeof(IKE_HEADER);\r
- IkeSaSession->RespPacket = AllocateZeroPool (IkeSaSession->RespPacketSize);\r
- if (IkeSaSession->RespPacket == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- CopyMem (IkeSaSession->RespPacket, IkePacket->Header, sizeof (IKE_HEADER));\r
- PayloadTotalSize = 0;\r
- for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
- Entry = Entry->ForwardLink;\r
-\r
- CopyMem (\r
- IkeSaSession->RespPacket + sizeof (IKE_HEADER) + PayloadTotalSize,\r
- IkePayload->PayloadBuf,\r
- IkePayload->PayloadSize\r
- );\r
- PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;\r
- }\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Decrypt IKE packet.\r
-\r
- This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.\r
-\r
- @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing\r
- some parameter used during decrypting.\r
- @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,\r
- and the decrypted result as output.\r
- @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
- IKE_CHILD_TYPE are supportted.\r
-\r
- @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the\r
- IKE packet length is not aligned with Algorithm Block Size\r
- @retval EFI_SUCCESS Decrypt IKE packet successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2DecryptPacket (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN OUT IKE_PACKET *IkePacket,\r
- IN OUT UINTN IkeType\r
- )\r
-{\r
- UINT8 CryptBlockSize; // Encrypt Block Size\r
- UINTN DecryptedSize; // Encrypted IKE Payload Size\r
- UINT8 *DecryptedBuf; // Encrypted IKE Payload buffer\r
- UINTN IntegritySize;\r
- UINT8 *IntegrityBuffer;\r
- UINTN IvSize; // Iv Size\r
- UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth\r
- UINT8 *CheckSumData; // Check Sum data\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- EFI_STATUS Status;\r
- UINT8 PadLen;\r
- HASH_DATA_FRAGMENT Fragments[1];\r
-\r
- IvSize = 0;\r
- IkeSaSession = NULL;\r
- CryptBlockSize = 0;\r
- CheckSumSize = 0;\r
-\r
- //\r
- // Check if the first payload is the Encrypted payload\r
- //\r
- if (IkePacket->Header->NextPayload != IKEV2_PAYLOAD_TYPE_ENCRYPT) {\r
- return EFI_ACCESS_DENIED;\r
- }\r
- CheckSumData = NULL;\r
- DecryptedBuf = NULL;\r
- IntegrityBuffer = NULL;\r
-\r
- //\r
- // Get the Block Size\r
- //\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
-\r
- CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);\r
-\r
- CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
-\r
- } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {\r
-\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- IkeSaSession = ChildSaSession->IkeSaSession;\r
- CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);\r
- CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);\r
- } else {\r
- //\r
- // The type of SA Session would either be IkeSa or ChildSa.\r
- //\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- CheckSumData = AllocateZeroPool (CheckSumSize);\r
- if (CheckSumData == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Fill in the Integrity buffer\r
- //\r
- IntegritySize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);\r
- IntegrityBuffer = AllocateZeroPool (IntegritySize);\r
- if (IntegrityBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- CopyMem (IntegrityBuffer, IkePacket->Header, sizeof(IKE_HEADER));\r
- CopyMem (IntegrityBuffer + sizeof (IKE_HEADER), IkePacket->PayloadsBuf, IkePacket->PayloadTotalSize);\r
-\r
- //\r
- // Change Host order to Network order, since the header order was changed\r
- // in the IkePacketFromNetbuf.\r
- //\r
- IkeHdrHostToNet ((IKE_HEADER *)IntegrityBuffer);\r
-\r
- //\r
- // Calculate the Integrity CheckSum Data\r
- //\r
- Fragments[0].Data = IntegrityBuffer;\r
- Fragments[0].DataSize = IntegritySize - CheckSumSize;\r
-\r
- if (SessionCommon->IsInitiator) {\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
- IkeSaSession->IkeKeys->SkArKey,\r
- IkeSaSession->IkeKeys->SkArKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- CheckSumData,\r
- CheckSumSize\r
- );\r
- } else {\r
- Status = IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
- IkeSaSession->IkeKeys->SkAiKey,\r
- IkeSaSession->IkeKeys->SkAiKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- CheckSumData,\r
- CheckSumSize\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
- //\r
- // Compare the Integrity CheckSum Data with the one in IkePacket\r
- //\r
- if (CompareMem (\r
- IkePacket->PayloadsBuf + IkePacket->PayloadTotalSize - CheckSumSize,\r
- CheckSumData,\r
- CheckSumSize\r
- ) != 0) {\r
- DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));\r
- Status = EFI_ACCESS_DENIED;\r
- goto ON_EXIT;\r
- }\r
-\r
- IvSize = CryptBlockSize;\r
-\r
- //\r
- // Decrypt the payload with the key.\r
- //\r
- DecryptedSize = IkePacket->PayloadTotalSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER) - IvSize - CheckSumSize;\r
- DecryptedBuf = AllocateZeroPool (DecryptedSize);\r
- if (DecryptedBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- CopyMem (\r
- DecryptedBuf,\r
- IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER) + IvSize,\r
- DecryptedSize\r
- );\r
-\r
- if (SessionCommon->IsInitiator) {\r
- Status = IpSecCryptoIoDecrypt (\r
- (UINT8) SessionCommon->SaParams->EncAlgId,\r
- IkeSaSession->IkeKeys->SkErKey,\r
- IkeSaSession->IkeKeys->SkErKeySize << 3,\r
- IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),\r
- DecryptedBuf,\r
- DecryptedSize,\r
- DecryptedBuf\r
- );\r
- } else {\r
- Status = IpSecCryptoIoDecrypt (\r
- (UINT8) SessionCommon->SaParams->EncAlgId,\r
- IkeSaSession->IkeKeys->SkEiKey,\r
- IkeSaSession->IkeKeys->SkEiKeySize << 3,\r
- IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),\r
- DecryptedBuf,\r
- DecryptedSize,\r
- DecryptedBuf\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Error decrypt buffer with %r\n", Status));\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Get the Padding length\r
- //\r
- //\r
- PadLen = (UINT8) (*(DecryptedBuf + DecryptedSize - sizeof (IKEV2_PAD_LEN)));\r
-\r
- //\r
- // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload\r
- //\r
- IkePacket->Header->NextPayload = ((IKEV2_ENCRYPTED *) IkePacket->PayloadsBuf)->Header.NextPayload;\r
-\r
- //\r
- // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.\r
- //\r
- FreePool (IkePacket->PayloadsBuf);\r
- IkePacket->PayloadsBuf = DecryptedBuf;\r
- IkePacket->PayloadTotalSize = DecryptedSize - PadLen;\r
-\r
- IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf, DecryptedSize);\r
-\r
-\r
-ON_EXIT:\r
- if (CheckSumData != NULL) {\r
- FreePool (CheckSumData);\r
- }\r
-\r
- if (EFI_ERROR (Status) && DecryptedBuf != NULL) {\r
- FreePool (DecryptedBuf);\r
- }\r
-\r
- if (IntegrityBuffer != NULL) {\r
- FreePool (IntegrityBuffer);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Encrypt IKE packet.\r
-\r
- This function encrypt IKE packet before sending it. The Encrypted IKE packet\r
- is put in to IKEV2 Encrypted Payload.\r
-\r
- @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.\r
- @param[in, out] IkePacket Pointer to IKE packet to be encrypted.\r
-\r
- @retval EFI_SUCCESS Operation is successful.\r
- @retval Others Operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2EncryptPacket (\r
- IN IKEV2_SESSION_COMMON *SessionCommon,\r
- IN OUT IKE_PACKET *IkePacket\r
- )\r
-{\r
- UINT8 CryptBlockSize; // Encrypt Block Size\r
- UINT8 CryptBlockSizeMask; // Block Mask\r
- UINTN EncryptedSize; // Encrypted IKE Payload Size\r
- UINT8 *EncryptedBuf; // Encrypted IKE Payload buffer\r
- UINT8 *EncryptPayloadBuf; // Contain whole Encrypted Payload\r
- UINTN EncryptPayloadSize; // Total size of the Encrypted payload\r
- UINT8 *IntegrityBuf; // Buffer to be intergity\r
- UINT8 *IvBuffer; // Initialization Vector\r
- UINT8 IvSize; // Iv Size\r
- UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth\r
- UINT8 *CheckSumData; // Check Sum data\r
- UINTN Index;\r
- IKE_PAYLOAD *EncryptPayload;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Entry;\r
- IKE_PAYLOAD *IkePayload;\r
- HASH_DATA_FRAGMENT Fragments[1];\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // Initial all buffers to NULL.\r
- //\r
- EncryptedBuf = NULL;\r
- EncryptPayloadBuf = NULL;\r
- IvBuffer = NULL;\r
- CheckSumData = NULL;\r
- IkeSaSession = NULL;\r
- CryptBlockSize = 0;\r
- CheckSumSize = 0;\r
- IntegrityBuf = NULL;\r
- //\r
- // Get the Block Size\r
- //\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
-\r
- CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);\r
- CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
-\r
- } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {\r
-\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- IkeSaSession = ChildSaSession->IkeSaSession;\r
- CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);\r
- CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);\r
- }\r
-\r
- //\r
- // Calcualte the EncryptPayloadSize and the PAD length\r
- //\r
- CryptBlockSizeMask = (UINT8) (CryptBlockSize - 1);\r
- EncryptedSize = (IkePacket->PayloadTotalSize + sizeof (IKEV2_PAD_LEN) + CryptBlockSizeMask) & ~CryptBlockSizeMask;\r
- EncryptedBuf = (UINT8 *) AllocateZeroPool (EncryptedSize);\r
- if (EncryptedBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Copy all payload into EncryptedIkePayload\r
- //\r
- Index = 0;\r
- NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
-\r
- CopyMem (EncryptedBuf + Index, IkePayload->PayloadBuf, IkePayload->PayloadSize);\r
- Index += IkePayload->PayloadSize;\r
-\r
- };\r
-\r
- //\r
- // Fill in the Pading Length\r
- //\r
- *(EncryptedBuf + EncryptedSize - 1) = (UINT8)(EncryptedSize - IkePacket->PayloadTotalSize - 1);\r
-\r
- //\r
- // The IV size is equal with block size\r
- //\r
- IvSize = CryptBlockSize;\r
- IvBuffer = (UINT8 *) AllocateZeroPool (IvSize);\r
- if (IvBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Generate IV\r
- //\r
- IkeGenerateIv (IvBuffer, IvSize);\r
-\r
- //\r
- // Encrypt payload buf\r
- //\r
- if (SessionCommon->IsInitiator) {\r
- Status = IpSecCryptoIoEncrypt (\r
- (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,\r
- IkeSaSession->IkeKeys->SkEiKey,\r
- IkeSaSession->IkeKeys->SkEiKeySize << 3,\r
- IvBuffer,\r
- EncryptedBuf,\r
- EncryptedSize,\r
- EncryptedBuf\r
- );\r
- } else {\r
- Status = IpSecCryptoIoEncrypt (\r
- (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,\r
- IkeSaSession->IkeKeys->SkErKey,\r
- IkeSaSession->IkeKeys->SkErKeySize << 3,\r
- IvBuffer,\r
- EncryptedBuf,\r
- EncryptedSize,\r
- EncryptedBuf\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Allocate the buffer for the whole IKE payload (Encrypted Payload).\r
- //\r
- EncryptPayloadSize = sizeof(IKEV2_ENCRYPTED) + IvSize + EncryptedSize + CheckSumSize;\r
- EncryptPayloadBuf = AllocateZeroPool (EncryptPayloadSize);\r
- if (EncryptPayloadBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Fill in Header of Encrypted Payload\r
- //\r
- ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.NextPayload = IkePacket->Header->NextPayload;\r
- ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.PayloadLength = HTONS ((UINT16)EncryptPayloadSize);\r
-\r
- //\r
- // Fill in Iv\r
- //\r
- CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED), IvBuffer, IvSize);\r
-\r
- //\r
- // Fill in encrypted data\r
- //\r
- CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED) + IvSize, EncryptedBuf, EncryptedSize);\r
-\r
- //\r
- // Fill in the IKE Packet header\r
- //\r
- IkePacket->PayloadTotalSize = EncryptPayloadSize;\r
- IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);\r
- IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_ENCRYPT;\r
-\r
- IntegrityBuf = AllocateZeroPool (IkePacket->Header->Length);\r
- if (IntegrityBuf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
- IkeHdrHostToNet (IkePacket->Header);\r
-\r
- CopyMem (IntegrityBuf, IkePacket->Header, sizeof (IKE_HEADER));\r
- CopyMem (IntegrityBuf + sizeof (IKE_HEADER), EncryptPayloadBuf, EncryptPayloadSize);\r
-\r
- //\r
- // Calcualte Integrity CheckSum\r
- //\r
- Fragments[0].Data = IntegrityBuf;\r
- Fragments[0].DataSize = EncryptPayloadSize + sizeof (IKE_HEADER) - CheckSumSize;\r
-\r
- CheckSumData = AllocateZeroPool (CheckSumSize);\r
- if (CheckSumData == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
- if (SessionCommon->IsInitiator) {\r
-\r
- IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
- IkeSaSession->IkeKeys->SkAiKey,\r
- IkeSaSession->IkeKeys->SkAiKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- CheckSumData,\r
- CheckSumSize\r
- );\r
- } else {\r
-\r
- IpSecCryptoIoHmac (\r
- (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
- IkeSaSession->IkeKeys->SkArKey,\r
- IkeSaSession->IkeKeys->SkArKeySize,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- 1,\r
- CheckSumData,\r
- CheckSumSize\r
- );\r
- }\r
-\r
- //\r
- // Copy CheckSum into Encrypted Payload\r
- //\r
- CopyMem (EncryptPayloadBuf + EncryptPayloadSize - CheckSumSize, CheckSumData, CheckSumSize);\r
-\r
- IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf, EncryptPayloadSize);\r
- IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData, CheckSumSize);\r
-\r
- //\r
- // Clean all payload under IkePacket->PayloadList.\r
- //\r
- ClearAllPayloads (IkePacket);\r
-\r
- //\r
- // Create Encrypted Payload and add into IkePacket->PayloadList\r
- //\r
- EncryptPayload = IkePayloadAlloc ();\r
- if (EncryptPayload == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Fill the encrypted payload into the IKE_PAYLOAD structure.\r
- //\r
- EncryptPayload->PayloadBuf = EncryptPayloadBuf;\r
- EncryptPayload->PayloadSize = EncryptPayloadSize;\r
- EncryptPayload->PayloadType = IKEV2_PAYLOAD_TYPE_ENCRYPT;\r
-\r
- IKE_PACKET_APPEND_PAYLOAD (IkePacket, EncryptPayload);\r
-\r
-ON_EXIT:\r
- if (EncryptedBuf != NULL) {\r
- FreePool (EncryptedBuf);\r
- }\r
-\r
- if (EFI_ERROR (Status) && EncryptPayloadBuf != NULL) {\r
- FreePool (EncryptPayloadBuf);\r
- }\r
-\r
- if (IvBuffer != NULL) {\r
- FreePool (IvBuffer);\r
- }\r
-\r
- if (CheckSumData != NULL) {\r
- FreePool (CheckSumData);\r
- }\r
-\r
- if (IntegrityBuf != NULL) {\r
- FreePool (IntegrityBuf);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
-\r
- The notification function. It will be called when the related UDP_TX_TOKEN's event\r
- is signaled.\r
-\r
- This function frees the Net Buffer pointed to the input Packet.\r
-\r
- @param[in] Packet Pointer to Net buffer containing the sending IKE packet.\r
- @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local\r
- address information.\r
- @param[in] IoStatus The Status of the related UDP_TX_TOKEN.\r
- @param[in] Context Pointer to data passed from the caller.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ikev2OnPacketSent (\r
- IN NET_BUF *Packet,\r
- IN UDP_END_POINT *EndPoint,\r
- IN EFI_STATUS IoStatus,\r
- IN VOID *Context\r
- )\r
-{\r
- IKE_PACKET *IkePacket;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- UINT8 Value;\r
- IPSEC_PRIVATE_DATA *Private;\r
- EFI_STATUS Status;\r
-\r
- IkePacket = (IKE_PACKET *) Context;\r
- Private = NULL;\r
-\r
- if (EFI_ERROR (IoStatus)) {\r
- DEBUG ((DEBUG_ERROR, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus));\r
- }\r
-\r
- NetbufFree (Packet);\r
-\r
- if (IkePacket->IsDeleteInfo) {\r
- //\r
- // For each RemotePeerIP, there are only one IKESA.\r
- //\r
- IkeSaSession = Ikev2SaSessionLookup (\r
- &IkePacket->Private->Ikev2EstablishedList,\r
- &IkePacket->RemotePeerIp\r
- );\r
- if (IkeSaSession == NULL) {\r
- IkePacketFree (IkePacket);\r
- return;\r
- }\r
-\r
- Private = IkePacket->Private;\r
- if (IkePacket->Spi != 0 ) {\r
- //\r
- // At that time, the established Child SA still in eht ChildSaEstablishSessionList.\r
- // And meanwhile, if the Child SA is in the the ChildSa in Delete list,\r
- // remove it from delete list and delete it direclty.\r
- //\r
- ChildSaSession = Ikev2ChildSaSessionLookupBySpi (\r
- &IkeSaSession->ChildSaEstablishSessionList,\r
- IkePacket->Spi\r
- );\r
- if (ChildSaSession != NULL) {\r
- Ikev2ChildSaSessionRemove (\r
- &IkeSaSession->DeleteSaList,\r
- ChildSaSession->LocalPeerSpi,\r
- IKEV2_DELET_CHILDSA_LIST\r
- );\r
-\r
- //\r
- // Delete the Child SA.\r
- //\r
- Ikev2ChildSaSilentDelete (\r
- IkeSaSession,\r
- IkePacket->Spi\r
- );\r
- }\r
-\r
- } else {\r
- //\r
- // Delete the IKE SA\r
- //\r
- DEBUG (\r
- (DEBUG_INFO,\r
- "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",\r
- IkeSaSession->InitiatorCookie,\r
- IkeSaSession->ResponderCookie)\r
- );\r
-\r
- RemoveEntryList (&IkeSaSession->BySessionTable);\r
- Ikev2SaSessionFree (IkeSaSession);\r
- }\r
- }\r
- IkePacketFree (IkePacket);\r
-\r
- //\r
- // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status\r
- // should be changed.\r
- //\r
- if (Private != NULL && Private->IsIPsecDisabling) {\r
- //\r
- // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in\r
- // IPsec status variable.\r
- //\r
- if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {\r
- Value = IPSEC_STATUS_DISABLED;\r
- Status = gRT->SetVariable (\r
- IPSECCONFIG_STATUS_NAME,\r
- &gEfiIpSecConfigProtocolGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- sizeof (Value),\r
- &Value\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Set the DisabledFlag in Private data.\r
- //\r
- Private->IpSec.DisabledFlag = TRUE;\r
- Private->IsIPsecDisabling = FALSE;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Send out IKEV2 packet.\r
-\r
- @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.\r
- @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.\r
- @param[in] IkePacket Pointer to IKE_PACKET to be sent out.\r
- @param[in] IkeType The type of IKE to point what's kind of the IKE\r
- packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE\r
- and IKE_CHILD_TYPE are supportted.\r
-\r
- @retval EFI_SUCCESS The operation complete successfully.\r
- @retval Otherwise The operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2SendIkePacket (\r
- IN IKE_UDP_SERVICE *IkeUdpService,\r
- IN UINT8 *SessionCommon,\r
- IN IKE_PACKET *IkePacket,\r
- IN UINTN IkeType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- NET_BUF *IkePacketNetbuf;\r
- UDP_END_POINT EndPoint;\r
- IKEV2_SESSION_COMMON *Common;\r
-\r
- Common = (IKEV2_SESSION_COMMON *) SessionCommon;\r
-\r
- //\r
- // Set the resend interval\r
- //\r
- if (Common->TimeoutInterval == 0) {\r
- Common->TimeoutInterval = IKE_DEFAULT_TIMEOUT_INTERVAL;\r
- }\r
-\r
- //\r
- // Retransfer the packet if it is initial packet.\r
- //\r
- if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {\r
- //\r
- // Set timer for next retry, this will cancel previous timer\r
- //\r
- Status = gBS->SetTimer (\r
- Common->TimeoutEvent,\r
- TimerRelative,\r
- MultU64x32 (Common->TimeoutInterval, 10000) // ms->100ns\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- IKE_PACKET_REF (IkePacket);\r
- //\r
- // If the last sent packet is same with this round packet, the packet is resent packet.\r
- //\r
- if (IkePacket != Common->LastSentPacket && Common->LastSentPacket != NULL) {\r
- IkePacketFree (Common->LastSentPacket);\r
- }\r
-\r
- Common->LastSentPacket = IkePacket;\r
-\r
- //\r
- // Transform IkePacke to NetBuf\r
- //\r
- IkePacketNetbuf = IkeNetbufFromPacket ((UINT8 *) SessionCommon, IkePacket, IkeType);\r
- if (IkePacketNetbuf == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- ZeroMem (&EndPoint, sizeof (UDP_END_POINT));\r
- EndPoint.RemotePort = IKE_DEFAULT_PORT;\r
- CopyMem (&IkePacket->RemotePeerIp, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&EndPoint.RemoteAddr, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&EndPoint.LocalAddr, &Common->LocalPeerIp, sizeof (EFI_IP_ADDRESS));\r
-\r
- IPSEC_DUMP_PACKET (IkePacket, EfiIPsecOutBound, IkeUdpService->IpVersion);\r
-\r
- if (IkeUdpService->IpVersion == IP_VERSION_4) {\r
- EndPoint.RemoteAddr.Addr[0] = HTONL (EndPoint.RemoteAddr.Addr[0]);\r
- EndPoint.LocalAddr.Addr[0] = HTONL (EndPoint.LocalAddr.Addr[0]);\r
- }\r
-\r
- //\r
- // Call UDPIO to send out the IKE packet.\r
- //\r
- Status = UdpIoSendDatagram (\r
- IkeUdpService->Output,\r
- IkePacketNetbuf,\r
- &EndPoint,\r
- NULL,\r
- Ikev2OnPacketSent,\r
- (VOID*)IkePacket\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Error send packet with %r\n", Status));\r
- }\r
-\r
- return Status;\r
-}\r
-\r