+ return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize);\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get index of the specified encryption alogrithm from the mIpsecEncryptAlgorithemList.\r
+\r
+ @param[in] AlgorithmId The encryption algorithm ID.\r
+\r
+ @return the index.\r
+ \r
+**/\r
+UINTN\r
+IpSecGetIndexFromEncList (\r
+ IN UINT8 AlgorithmId\r
+ )\r
+{\r
+ UINT8 Index;\r
+ \r
+ for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {\r
+ if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {\r
+ return Index;\r
+ }\r
+ }\r
+ \r
+ return (UINTN) -1;\r
+}\r
+\r
+/**\r
+ Get index of the specified encryption alogrithm from the mIpsecAuthAlgorithemList.\r
+\r
+ @param[in] AlgorithmId The encryption algorithm ID.\r
+\r
+ @return the index.\r
+ \r
+**/\r
+UINTN\r
+IpSecGetIndexFromAuthList (\r
+ IN UINT8 AlgorithmId\r
+ )\r
+{\r
+ UINT8 Index;\r
+ \r
+ for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {\r
+ if (AlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {\r
+ //\r
+ // The BlockSize is same with IvSize.\r
+ //\r
+ return Index;\r
+ }\r
+ }\r
+ \r
+ return (UINTN) -1;\r
+}\r
+\r
+/**\r
+ Encrypt the buffer.\r
+\r
+ This function calls relevant encryption interface from CryptoLib according to\r
+ the input alogrithm ID. The InData should be multiple of block size. This function\r
+ doesn't perform the padding. If it has the Ivec data, the length of it should be\r
+ same with the block size. The block size is different from the different algorithm.\r
+\r
+ @param[in] AlgorithmId The Alogrithem identification defined in RFC.\r
+ @param[in] Key Pointer to the buffer containing encrypting key.\r
+ @param[in] KeyBits The length of the key in bits.\r
+ @param[in] Ivec Point to the buffer containning the Initializeion\r
+ Vector (IV) data.\r
+ @param[in] InData Point to the buffer containing the data to be\r
+ encrypted.\r
+ @param[in] InDataLength The length of InData in Bytes.\r
+ @param[out] OutData Point to the buffer that receives the encryption\r
+ output.\r
+\r
+ @retval EFI_UNSUPPORTED The input Algorithm is not supported.\r
+ @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecCryptoIoEncrypt (\r
+ IN CONST UINT8 AlgorithmId,\r
+ IN CONST UINT8 *Key,\r
+ IN CONST UINTN KeyBits,\r
+ IN CONST UINT8 *Ivec, OPTIONAL\r
+ IN UINT8 *InData,\r
+ IN UINTN InDataLength,\r
+ OUT UINT8 *OutData\r
+ )\r
+{ \r
+ UINTN Index;\r
+ UINTN ContextSize;\r
+ UINT8 *Context;\r
+ EFI_STATUS Status;\r
+ \r
+ Status = EFI_UNSUPPORTED;\r
+ \r
+ switch (AlgorithmId) {\r
+\r
+ case IKE_EALG_NULL:\r
+ case IKE_EALG_NONE:\r
+ CopyMem (OutData, InData, InDataLength);\r
+ return EFI_SUCCESS;\r
+\r
+ case IKE_EALG_3DESCBC:\r
+ case IKE_EALG_AESCBC:\r
+ Index = IpSecGetIndexFromEncList (AlgorithmId);\r
+ if (Index == -1) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Get Context Size\r
+ //\r
+ ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize ();\r
+ Context = AllocateZeroPool (ContextSize);\r
+\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Initiate Context\r
+ //\r
+ if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {\r
+ if (mIpsecEncryptAlgorithmList[Index].CipherEncrypt (Context, InData, InDataLength, Ivec, OutData)) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return Status;\r
+\r
+ }\r
+\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Decrypts the buffer.\r
+\r
+ This function calls relevant Decryption interface from CryptoLib according to\r
+ the input alogrithm ID. The InData should be multiple of block size. This function\r
+ doesn't perform the padding. If it has the Ivec data, the length of it should be\r
+ same with the block size. The block size is different from the different algorithm.\r
+\r
+ @param[in] AlgorithmId The Alogrithem identification defined in RFC.\r
+ @param[in] Key Pointer to the buffer containing encrypting key.\r
+ @param[in] KeyBits The length of the key in bits.\r
+ @param[in] Ivec Point to the buffer containning the Initializeion\r
+ Vector (IV) data.\r
+ @param[in] InData Point to the buffer containing the data to be\r
+ decrypted.\r
+ @param[in] InDataLength The length of InData in Bytes.\r
+ @param[out] OutData Pointer to the buffer that receives the decryption\r
+ output.\r
+\r
+ @retval EFI_UNSUPPORTED The input Algorithm is not supported.\r
+ @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecCryptoIoDecrypt (\r
+ IN CONST UINT8 AlgorithmId,\r
+ IN CONST UINT8 *Key,\r
+ IN CONST UINTN KeyBits,\r
+ IN CONST UINT8 *Ivec, OPTIONAL\r
+ IN UINT8 *InData,\r
+ IN UINTN InDataLength,\r
+ OUT UINT8 *OutData\r
+ )\r
+{ \r
+ UINTN Index;\r
+ UINTN ContextSize;\r
+ UINT8 *Context;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ switch (AlgorithmId) {\r
+\r
+ case IKE_EALG_NULL:\r
+ case IKE_EALG_NONE:\r
+ CopyMem (OutData, InData, InDataLength);\r
+ return EFI_SUCCESS;\r
+\r
+ case IKE_EALG_3DESCBC:\r
+ case IKE_EALG_AESCBC:\r
+ Index = IpSecGetIndexFromEncList(AlgorithmId);\r
+ if (Index == -1) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get Context Size\r
+ //\r
+ ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize();\r
+ Context = AllocateZeroPool (ContextSize);\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initiate Context\r
+ //\r
+ if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {\r
+ if (mIpsecEncryptAlgorithmList[Index].CipherDecrypt (Context, InData, InDataLength, Ivec, OutData)) {\r
+ Status = EFI_SUCCESS; \r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return Status;\r
+ }\r
+\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Digests the Payload with key and store the result into the OutData.\r
+\r
+ This function calls relevant Hmac interface from CryptoLib according to\r
+ the input alogrithm ID. It computes all datas from InDataFragment and output\r
+ the result into the OutData buffer. If the OutDataSize is larger than the related\r
+ HMAC alogrithm output size, return EFI_INVALID_PARAMETER.\r
+ \r
+ @param[in] AlgorithmId The authentication Identification.\r
+ @param[in] Key Pointer of the authentication key.\r
+ @param[in] KeyLength The length of the Key in bytes.\r
+ @param[in] InDataFragment The list contains all data to be authenticated.\r
+ @param[in] FragmentCount The size of the InDataFragment.\r
+ @param[out] OutData For in, the buffer to receive the output data.\r
+ For out, the buffer contains the authenticated data.\r
+ @param[in] OutDataSize The size of the buffer of OutData.\r
+\r
+ @retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.\r
+ @retval EFI_INVALID_PARAMETER The OutData buffer size is larger than algorithm digest size.\r
+ @retval EFI_SUCCESS Authenticate the payload successfully.\r
+ @retval otherwise Authentication of the payload fails.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecCryptoIoHmac (\r
+ IN CONST UINT8 AlgorithmId,\r
+ IN CONST UINT8 *Key,\r
+ IN UINTN KeyLength,\r
+ IN HASH_DATA_FRAGMENT *InDataFragment,\r
+ IN UINTN FragmentCount,\r
+ OUT UINT8 *OutData,\r
+ IN UINTN OutDataSize\r
+ )\r
+{\r
+ UINTN ContextSize;\r
+ UINTN Index;\r
+ UINT8 FragmentIndex;\r
+ UINT8 *HashContext;\r
+ EFI_STATUS Status;\r
+ UINT8 *OutHashData;\r
+ UINTN OutHashSize;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ OutHashData = NULL;\r
+\r
+ OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);\r
+ //\r
+ // If the expected hash data size is larger than the related Hash algorithm\r
+ // output length, return EFI_INVALID_PARAMETER.\r
+ //\r
+ if (OutDataSize > OutHashSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ OutHashData = AllocatePool (OutHashSize);\r
+\r
+ if (OutHashData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ switch (AlgorithmId) {\r
+\r
+ case IKE_AALG_NONE :\r
+ case IKE_AALG_NULL :\r
+ return EFI_SUCCESS;\r
+\r
+ case IKE_AALG_SHA1HMAC:\r
+ Index = IpSecGetIndexFromAuthList (AlgorithmId);\r
+ if (Index == -1) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get Context Size\r