+/** @file\r
+ HMAC-SHA256 KDF Wrapper Implementation over OpenSSL.\r
+\r
+Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseCryptLib.h>\r
+#include <openssl/evp.h>\r
+#include <openssl/kdf.h>\r
+\r
+/**\r
+ Derive HMAC-based Extract-and-Expand Key Derivation Function (HKDF).\r
+\r
+ @param[in] Key Pointer to the user-supplied key.\r
+ @param[in] KeySize Key size in bytes.\r
+ @param[in] Salt Pointer to the salt(non-secret) value.\r
+ @param[in] SaltSize Salt size in bytes.\r
+ @param[in] Info Pointer to the application specific info.\r
+ @param[in] InfoSize Info size in bytes.\r
+ @param[Out] Out Pointer to buffer to receive hkdf value.\r
+ @param[in] OutSize Size of hkdf bytes to generate.\r
+\r
+ @retval TRUE Hkdf generated successfully.\r
+ @retval FALSE Hkdf generation failed.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HkdfSha256ExtractAndExpand (\r
+ IN CONST UINT8 *Key,\r
+ IN UINTN KeySize,\r
+ IN CONST UINT8 *Salt,\r
+ IN UINTN SaltSize,\r
+ IN CONST UINT8 *Info,\r
+ IN UINTN InfoSize,\r
+ OUT UINT8 *Out,\r
+ IN UINTN OutSize\r
+ )\r
+{\r
+ EVP_PKEY_CTX *pHkdfCtx;\r
+ BOOLEAN Result;\r
+\r
+ if (Key == NULL || Salt == NULL || Info == NULL || Out == NULL ||\r
+ KeySize > INT_MAX || SaltSize > INT_MAX || InfoSize > INT_MAX || OutSize > INT_MAX ) {\r
+ return FALSE;\r
+ }\r
+\r
+ pHkdfCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);\r
+ if (pHkdfCtx == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ Result = EVP_PKEY_derive_init(pHkdfCtx) > 0;\r
+ if (Result) {\r
+ Result = EVP_PKEY_CTX_set_hkdf_md(pHkdfCtx, EVP_sha256()) > 0;\r
+ }\r
+ if (Result) {\r
+ Result = EVP_PKEY_CTX_set1_hkdf_salt(pHkdfCtx, Salt, (UINT32)SaltSize) > 0;\r
+ }\r
+ if (Result) {\r
+ Result = EVP_PKEY_CTX_set1_hkdf_key(pHkdfCtx, Key, (UINT32)KeySize) > 0;\r
+ }\r
+ if (Result) {\r
+ Result = EVP_PKEY_CTX_add1_hkdf_info(pHkdfCtx, Info, (UINT32)InfoSize) > 0;\r
+ }\r
+ if (Result) {\r
+ Result = EVP_PKEY_derive(pHkdfCtx, Out, &OutSize) > 0;\r
+ }\r
+\r
+ EVP_PKEY_CTX_free(pHkdfCtx);\r
+ pHkdfCtx = NULL;\r
+ return Result;\r
+}\r