]> git.proxmox.com Git - mirror_edk2.git/commitdiff
CryptoPkg: Add EC support
authorYi Li <yi1.li@intel.com>
Sun, 25 Sep 2022 09:26:18 +0000 (17:26 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 26 Sep 2022 07:03:56 +0000 (07:03 +0000)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828

This patch is used to add CryptEc library, which is wrapped
over OpenSSL.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
CryptoPkg/Include/Library/BaseCryptLib.h
CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c [new file with mode: 0644]
CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c [new file with mode: 0644]
CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c [new file with mode: 0644]

index 3026299e2953057d00c991e16bc26a17cc7fa921..63c6228368c631d3a048183d84451dd27b98b3f1 100644 (file)
@@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 \r
 #include <Uefi/UefiBaseType.h>\r
 \r
+#define CRYPTO_NID_NULL  0x0000\r
+\r
+// Key Exchange\r
+#define CRYPTO_NID_SECP256R1  0x0204\r
+#define CRYPTO_NID_SECP384R1  0x0205\r
+#define CRYPTO_NID_SECP521R1  0x0206\r
+\r
 ///\r
 /// MD5 digest size in bytes\r
 ///\r
@@ -3254,4 +3261,421 @@ BigNumAddMod (
   OUT VOID       *BnRes\r
   );\r
 \r
+// =====================================================================================\r
+//    Basic Elliptic Curve Primitives\r
+// =====================================================================================\r
+\r
+/**\r
+  Initialize new opaque EcGroup object. This object represents an EC curve and\r
+  and is used for calculation within this group. This object should be freed\r
+  using EcGroupFree() function.\r
+\r
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in\r
+                          BaseCryptLib.h).\r
+\r
+  @retval EcGroup object  On success.\r
+  @retval NULL            On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcGroupInit (\r
+  IN UINTN  CryptoNid\r
+  );\r
+\r
+/**\r
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.\r
+  This function will set the provided Big Number objects  to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[out] BnPrime    Group prime number.\r
+  @param[out] BnA        A coefficient.\r
+  @param[out] BnB        B coefficient.\r
+  @param[in]  BnCtx      BN context.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *BnPrime,\r
+  OUT VOID       *BnA,\r
+  OUT VOID       *BnB,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Get EC group order.\r
+  This function will set the provided Big Number object to the corresponding\r
+  value. The caller needs to make sure that the "out" BigNumber parameter\r
+  is properly initialized.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[out] BnOrder   Group prime number.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetOrder (\r
+  IN VOID   *EcGroup,\r
+  OUT VOID  *BnOrder\r
+  );\r
+\r
+/**\r
+  Free previously allocated EC group object using EcGroupInit().\r
+\r
+  @param[in]  EcGroup   EC group object to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcGroupFree (\r
+  IN VOID  *EcGroup\r
+  );\r
+\r
+/**\r
+  Initialize new opaque EC Point object. This object represents an EC point\r
+  within the given EC group (curve).\r
+\r
+  @param[in]  EC Group, properly initialized using EcGroupInit().\r
+\r
+  @retval EC Point object  On success.\r
+  @retval NULL             On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcPointInit (\r
+  IN CONST VOID  *EcGroup\r
+  );\r
+\r
+/**\r
+  Free previously allocated EC Point object using EcPointInit().\r
+\r
+  @param[in]  EcPoint   EC Point to free.\r
+  @param[in]  Clear     TRUE iff the memory should be cleared.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcPointDeInit (\r
+  IN VOID     *EcPoint,\r
+  IN BOOLEAN  Clear\r
+  );\r
+\r
+/**\r
+  Get EC point affine (x,y) coordinates.\r
+  This function will set the provided Big Number objects to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[out] BnX        X coordinate.\r
+  @param[out] BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointGetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  OUT VOID       *BnX,\r
+  OUT VOID       *BnY,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Set EC point affine (x,y) coordinates.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN CONST VOID  *BnY,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  EC Point addition. EcPointResult = EcPointA + EcPointB.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPointA         EC Point.\r
+  @param[in]  EcPointB         EC Point.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointAdd (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPoint          EC Point.\r
+  @param[in]  BnPScalar        P Scalar.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointMul (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPoint,\r
+  IN CONST VOID  *BnPScalar,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Calculate the inverse of the supplied EC point.\r
+\r
+  @param[in]     EcGroup   EC group object.\r
+  @param[in,out] EcPoint   EC point to invert.\r
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointInvert (\r
+  IN CONST VOID  *EcGroup,\r
+  IN OUT VOID    *EcPoint,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Check if the supplied point is on EC curve.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On curve.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsOnCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Check if the supplied point is at infinity.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+\r
+  @retval TRUE          At infinity.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsAtInfinity (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint\r
+  );\r
+\r
+/**\r
+  Check if EC points are equal.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPointA  EC point A.\r
+  @param[in]  EcPointB  EC point B.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          A == B.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointEqual (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+/**\r
+  Set EC point compressed coordinates. Points can be described in terms of\r
+  their compressed coordinates. For a point (x, y), for any given value for x\r
+  such that the point is on the curve there will only ever be two possible\r
+  values for y. Therefore, a point can be set using this function where BnX is\r
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two\r
+  possible values for y should be used.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC Point.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  YBit       0 or 1 to identify which Y value is used.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetCompressedCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN UINT8       YBit,\r
+  IN VOID        *BnCtx\r
+  );\r
+\r
+// =====================================================================================\r
+//    Elliptic Curve Diffie Hellman Primitives\r
+// =====================================================================================\r
+\r
+/**\r
+  Allocates and Initializes one Elliptic Curve Context for subsequent use\r
+  with the NID.\r
+\r
+  @param[in]  Nid cipher NID\r
+  @return     Pointer to the Elliptic Curve Context that has been initialized.\r
+              If the allocations fails, EcNewByNid() returns NULL.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcNewByNid (\r
+  IN UINTN  Nid\r
+  );\r
+\r
+/**\r
+  Release the specified EC context.\r
+\r
+  @param[in]  EcContext  Pointer to the EC context to be released.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcFree (\r
+  IN  VOID  *EcContext\r
+  );\r
+\r
+/**\r
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses\r
+  pseudo random number generator. The caller must make sure RandomSeed()\r
+  function was properly called before.\r
+  The Ec context should be correctly initialized by EcNewByNid.\r
+  This function generates random secret, and computes the public key (X, Y), which is\r
+  returned via parameter Public, PublicSize.\r
+  X is the first half of Public with size being PublicSize / 2,\r
+  Y is the second half of Public with size being PublicSize / 2.\r
+  EC context is updated accordingly.\r
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and\r
+  PublicSize is set to the required buffer size to obtain the public X, Y.\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PublicSize is NULL, then return FALSE.\r
+  If PublicSize is large enough but Public is NULL, then return FALSE.\r
+  @param[in, out]  EcContext      Pointer to the EC context.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval TRUE   EC public X,Y generation succeeded.\r
+  @retval FALSE  EC public X,Y generation failed.\r
+  @retval FALSE  PublicKeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGenerateKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  );\r
+\r
+/**\r
+  Gets the public key component from the established EC context.\r
+  The Ec context should be correctly initialized by EcNewByNid, and successfully\r
+  generate key pair from EcGenerateKey().\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext      Pointer to EC context being set.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval  TRUE   EC key component was retrieved successfully.\r
+  @retval  FALSE  Invalid EC key component.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPubKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  );\r
+\r
+/**\r
+  Computes exchanged common key.\r
+  Given peer's public key (X, Y), this function computes the exchanged common key,\r
+  based on its own context including value of curve parameter and random secret.\r
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,\r
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PeerPublic is NULL, then return FALSE.\r
+  If PeerPublicSize is 0, then return FALSE.\r
+  If Key is NULL, then return FALSE.\r
+  If KeySize is not large enough, then return FALSE.\r
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext          Pointer to the EC context.\r
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.\r
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.\r
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.\r
+  @param[out]      Key                Pointer to the buffer to receive generated key.\r
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.\r
+                                      On output, the size of data returned in Key buffer in bytes.\r
+  @retval TRUE   EC exchanged key generation succeeded.\r
+  @retval FALSE  EC exchanged key generation failed.\r
+  @retval FALSE  KeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDhComputeKey (\r
+  IN OUT  VOID         *EcContext,\r
+  IN      CONST UINT8  *PeerPublic,\r
+  IN      UINTN        PeerPublicSize,\r
+  IN      CONST INT32  *CompressFlag,\r
+  OUT     UINT8        *Key,\r
+  IN OUT  UINTN        *KeySize\r
+  );\r
+\r
 #endif // __BASE_CRYPT_LIB_H__\r
index 0208d706b8737135ce08210821dfce76bbd15261..9634bd5fea258291d0f0bf2fa54d7cc5d1d99a82 100644 (file)
@@ -53,6 +53,8 @@
   Pk/CryptTs.c\r
   Pk/CryptRsaPss.c\r
   Pk/CryptRsaPssSign.c\r
+  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled\r
+  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled\r
   Pem/CryptPem.c\r
   Bn/CryptBn.c\r
 \r
index 82b97bc6d3055361969c27b5a4ab91711c1f25c5..3799780c9f521ae606d6947bae6acc6d9bc3af9c 100644 (file)
@@ -59,6 +59,7 @@
   Pk/CryptTsNull.c\r
   Pk/CryptRsaPss.c\r
   Pk/CryptRsaPssSignNull.c\r
+  Pk/CryptEcNull.c\r
   Pem/CryptPemNull.c\r
   Rand/CryptRandNull.c\r
   Bn/CryptBnNull.c\r
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
new file mode 100644 (file)
index 0000000..396c819
--- /dev/null
@@ -0,0 +1,765 @@
+/** @file\r
+  Elliptic Curve and ECDH API implementation based on OpenSSL\r
+\r
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "InternalCryptLib.h"\r
+#include <openssl/objects.h>\r
+#include <openssl/bn.h>\r
+#include <openssl/ec.h>\r
+\r
+// =====================================================================================\r
+//    Basic Elliptic Curve Primitives\r
+// =====================================================================================\r
+\r
+/**\r
+  Return the Nid of certain ECC curve.\r
+\r
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in\r
+                          BaseCryptLib.h).\r
+\r
+  @retval !=-1    On success.\r
+  @retval -1      ECC curve not supported.\r
+**/\r
+STATIC\r
+INT32\r
+CryptoNidToOpensslNid (\r
+  IN UINTN  CryptoNid\r
+  )\r
+{\r
+  INT32  Nid;\r
+\r
+  switch (CryptoNid) {\r
+    case CRYPTO_NID_SECP256R1:\r
+      Nid = NID_X9_62_prime256v1;\r
+      break;\r
+    case CRYPTO_NID_SECP384R1:\r
+      Nid = NID_secp384r1;\r
+      break;\r
+    case CRYPTO_NID_SECP521R1:\r
+      Nid = NID_secp521r1;\r
+      break;\r
+    default:\r
+      return -1;\r
+  }\r
+\r
+  return Nid;\r
+}\r
+\r
+/**\r
+  Initialize new opaque EcGroup object. This object represents an EC curve and\r
+  and is used for calculation within this group. This object should be freed\r
+  using EcGroupFree() function.\r
+\r
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in\r
+                          BaseCryptLib.h).\r
+\r
+  @retval EcGroup object  On success.\r
+  @retval NULL            On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcGroupInit (\r
+  IN UINTN  CryptoNid\r
+  )\r
+{\r
+  INT32  Nid;\r
+\r
+  Nid = CryptoNidToOpensslNid (CryptoNid);\r
+\r
+  if (Nid < 0) {\r
+    return NULL;\r
+  }\r
+\r
+  return EC_GROUP_new_by_curve_name (Nid);\r
+}\r
+\r
+/**\r
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.\r
+  This function will set the provided Big Number objects  to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[out] BnPrime    Group prime number.\r
+  @param[out] BnA        A coefficient.\r
+  @param[out] BnB        B coefficient..\r
+  @param[in]  BnCtx      BN context.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *BnPrime,\r
+  OUT VOID       *BnA,\r
+  OUT VOID       *BnB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);\r
+}\r
+\r
+/**\r
+  Get EC group order.\r
+  This function will set the provided Big Number object to the corresponding\r
+  value. The caller needs to make sure that the "out" BigNumber parameter\r
+  is properly initialized.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[out] BnOrder   Group prime number.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetOrder (\r
+  IN VOID   *EcGroup,\r
+  OUT VOID  *BnOrder\r
+  )\r
+{\r
+  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);\r
+}\r
+\r
+/**\r
+  Free previously allocated EC group object using EcGroupInit().\r
+\r
+  @param[in]  EcGroup   EC group object to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcGroupFree (\r
+  IN VOID  *EcGroup\r
+  )\r
+{\r
+  EC_GROUP_free (EcGroup);\r
+}\r
+\r
+/**\r
+  Initialize new opaque EC Point object. This object represents an EC point\r
+  within the given EC group (curve).\r
+\r
+  @param[in]  EC Group, properly initialized using EcGroupInit().\r
+\r
+  @retval EC Point object  On success.\r
+  @retval NULL             On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcPointInit (\r
+  IN CONST VOID  *EcGroup\r
+  )\r
+{\r
+  return EC_POINT_new (EcGroup);\r
+}\r
+\r
+/**\r
+  Free previously allocated EC Point object using EcPointInit().\r
+\r
+  @param[in]  EcPoint   EC Point to free.\r
+  @param[in]  Clear     TRUE iff the memory should be cleared.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcPointDeInit (\r
+  IN VOID     *EcPoint,\r
+  IN BOOLEAN  Clear\r
+  )\r
+{\r
+  if (Clear) {\r
+    EC_POINT_clear_free (EcPoint);\r
+  } else {\r
+    EC_POINT_free (EcPoint);\r
+  }\r
+}\r
+\r
+/**\r
+  Get EC point affine (x,y) coordinates.\r
+  This function will set the provided Big Number objects to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[out] BnX        X coordinate.\r
+  @param[out] BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointGetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  OUT VOID       *BnX,\r
+  OUT VOID       *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);\r
+}\r
+\r
+/**\r
+  Set EC point affine (x,y) coordinates.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN CONST VOID  *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);\r
+}\r
+\r
+/**\r
+  EC Point addition. EcPointResult = EcPointA + EcPointB.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPointA         EC Point.\r
+  @param[in]  EcPointB         EC Point.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointAdd (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);\r
+}\r
+\r
+/**\r
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPoint          EC Point.\r
+  @param[in]  BnPScalar        P Scalar.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointMul (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPoint,\r
+  IN CONST VOID  *BnPScalar,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);\r
+}\r
+\r
+/**\r
+  Calculate the inverse of the supplied EC point.\r
+\r
+  @param[in]     EcGroup   EC group object.\r
+  @param[in,out] EcPoint   EC point to invert.\r
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointInvert (\r
+  IN CONST VOID  *EcGroup,\r
+  IN OUT VOID    *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);\r
+}\r
+\r
+/**\r
+  Check if the supplied point is on EC curve.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On curve.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsOnCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;\r
+}\r
+\r
+/**\r
+  Check if the supplied point is at infinity.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+\r
+  @retval TRUE          At infinity.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsAtInfinity (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint\r
+  )\r
+{\r
+  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;\r
+}\r
+\r
+/**\r
+  Check if EC points are equal.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPointA  EC point A.\r
+  @param[in]  EcPointB  EC point B.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          A == B.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointEqual (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;\r
+}\r
+\r
+/**\r
+  Set EC point compressed coordinates. Points can be described in terms of\r
+  their compressed coordinates. For a point (x, y), for any given value for x\r
+  such that the point is on the curve there will only ever be two possible\r
+  values for y. Therefore, a point can be set using this function where BnX is\r
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two\r
+  possible values for y should be used.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC Point.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  YBit       0 or 1 to identify which Y value is used.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetCompressedCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN UINT8       YBit,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);\r
+}\r
+\r
+// =====================================================================================\r
+//    Elliptic Curve Diffie Hellman Primitives\r
+// =====================================================================================\r
+\r
+/**\r
+  Allocates and Initializes one Elliptic Curve Context for subsequent use\r
+  with the NID.\r
+\r
+  @param[in]  Nid   Identifying number for the ECC curve (Defined in\r
+                    BaseCryptLib.h).\r
+  @return     Pointer to the Elliptic Curve Context that has been initialized.\r
+              If the allocations fails, EcNewByNid() returns NULL.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcNewByNid (\r
+  IN UINTN  Nid\r
+  )\r
+{\r
+  INT32  OpenSslNid;\r
+\r
+  OpenSslNid = CryptoNidToOpensslNid (Nid);\r
+  if (OpenSslNid < 0) {\r
+    return NULL;\r
+  }\r
+\r
+  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);\r
+}\r
+\r
+/**\r
+  Release the specified EC context.\r
+\r
+  @param[in]  EcContext  Pointer to the EC context to be released.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcFree (\r
+  IN  VOID  *EcContext\r
+  )\r
+{\r
+  EC_KEY_free ((EC_KEY *)EcContext);\r
+}\r
+\r
+/**\r
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses\r
+  pseudo random number generator. The caller must make sure RandomSeed()\r
+  function was properly called before.\r
+  The Ec context should be correctly initialized by EcNewByNid.\r
+  This function generates random secret, and computes the public key (X, Y), which is\r
+  returned via parameter Public, PublicSize.\r
+  X is the first half of Public with size being PublicSize / 2,\r
+  Y is the second half of Public with size being PublicSize / 2.\r
+  EC context is updated accordingly.\r
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and\r
+  PublicSize is set to the required buffer size to obtain the public X, Y.\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PublicSize is NULL, then return FALSE.\r
+  If PublicSize is large enough but Public is NULL, then return FALSE.\r
+  @param[in, out]  EcContext      Pointer to the EC context.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval TRUE   EC public X,Y generation succeeded.\r
+  @retval FALSE  EC public X,Y generation failed.\r
+  @retval FALSE  PublicKeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGenerateKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  EC_KEY          *EcKey;\r
+  CONST EC_GROUP  *Group;\r
+  CONST EC_POINT  *EcPoint;\r
+  BOOLEAN         RetVal;\r
+  BIGNUM          *BnX;\r
+  BIGNUM          *BnY;\r
+  UINTN           HalfSize;\r
+  INTN            XSize;\r
+  INTN            YSize;\r
+\r
+  if ((EcContext == NULL) || (PublicKeySize == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  EcKey    = (EC_KEY *)EcContext;\r
+  Group    = EC_KEY_get0_group (EcKey);\r
+  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;\r
+\r
+  // Assume RAND_seed was called\r
+  if (EC_KEY_generate_key (EcKey) != 1) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (*PublicKeySize < HalfSize * 2) {\r
+    *PublicKeySize = HalfSize * 2;\r
+    return FALSE;\r
+  }\r
+\r
+  *PublicKeySize = HalfSize * 2;\r
+\r
+  EcPoint = EC_KEY_get0_public_key (EcKey);\r
+  if (EcPoint == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  RetVal = FALSE;\r
+  BnX    = BN_new ();\r
+  BnY    = BN_new ();\r
+  if ((BnX == NULL) || (BnY == NULL)) {\r
+    goto fail;\r
+  }\r
+\r
+  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {\r
+    goto fail;\r
+  }\r
+\r
+  XSize = BN_num_bytes (BnX);\r
+  YSize = BN_num_bytes (BnY);\r
+  if ((XSize <= 0) || (YSize <= 0)) {\r
+    goto fail;\r
+  }\r
+\r
+  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);\r
+\r
+  ZeroMem (PublicKey, *PublicKeySize);\r
+  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);\r
+  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);\r
+\r
+  RetVal = TRUE;\r
+\r
+fail:\r
+  BN_free (BnX);\r
+  BN_free (BnY);\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Gets the public key component from the established EC context.\r
+  The Ec context should be correctly initialized by EcNewByNid, and successfully\r
+  generate key pair from EcGenerateKey().\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext      Pointer to EC context being set.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval  TRUE   EC key component was retrieved successfully.\r
+  @retval  FALSE  Invalid EC key component.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPubKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  EC_KEY          *EcKey;\r
+  CONST EC_GROUP  *Group;\r
+  CONST EC_POINT  *EcPoint;\r
+  BIGNUM          *BnX;\r
+  BIGNUM          *BnY;\r
+  UINTN           HalfSize;\r
+  INTN            XSize;\r
+  INTN            YSize;\r
+  BOOLEAN         RetVal;\r
+\r
+  if ((EcContext == NULL) || (PublicKeySize == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  EcKey    = (EC_KEY *)EcContext;\r
+  Group    = EC_KEY_get0_group (EcKey);\r
+  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;\r
+  if (*PublicKeySize < HalfSize * 2) {\r
+    *PublicKeySize = HalfSize * 2;\r
+    return FALSE;\r
+  }\r
+\r
+  *PublicKeySize = HalfSize * 2;\r
+\r
+  EcPoint = EC_KEY_get0_public_key (EcKey);\r
+  if (EcPoint == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  RetVal = FALSE;\r
+  BnX    = BN_new ();\r
+  BnY    = BN_new ();\r
+  if ((BnX == NULL) || (BnY == NULL)) {\r
+    goto fail;\r
+  }\r
+\r
+  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {\r
+    goto fail;\r
+  }\r
+\r
+  XSize = BN_num_bytes (BnX);\r
+  YSize = BN_num_bytes (BnY);\r
+  if ((XSize <= 0) || (YSize <= 0)) {\r
+    goto fail;\r
+  }\r
+\r
+  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);\r
+\r
+  if (PublicKey != NULL) {\r
+    ZeroMem (PublicKey, *PublicKeySize);\r
+    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);\r
+    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);\r
+  }\r
+\r
+  RetVal = TRUE;\r
+\r
+fail:\r
+  BN_free (BnX);\r
+  BN_free (BnY);\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Computes exchanged common key.\r
+  Given peer's public key (X, Y), this function computes the exchanged common key,\r
+  based on its own context including value of curve parameter and random secret.\r
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,\r
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.\r
+  If public key is compressed, the PeerPublic will only contain half key (X).\r
+  If EcContext is NULL, then return FALSE.\r
+  If PeerPublic is NULL, then return FALSE.\r
+  If PeerPublicSize is 0, then return FALSE.\r
+  If Key is NULL, then return FALSE.\r
+  If KeySize is not large enough, then return FALSE.\r
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext          Pointer to the EC context.\r
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.\r
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.\r
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.\r
+  @param[out]      Key                Pointer to the buffer to receive generated key.\r
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.\r
+                                      On output, the size of data returned in Key buffer in bytes.\r
+  @retval TRUE   EC exchanged key generation succeeded.\r
+  @retval FALSE  EC exchanged key generation failed.\r
+  @retval FALSE  KeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDhComputeKey (\r
+  IN OUT  VOID         *EcContext,\r
+  IN      CONST UINT8  *PeerPublic,\r
+  IN      UINTN        PeerPublicSize,\r
+  IN      CONST INT32  *CompressFlag,\r
+  OUT     UINT8        *Key,\r
+  IN OUT  UINTN        *KeySize\r
+  )\r
+{\r
+  EC_KEY          *EcKey;\r
+  EC_KEY          *PeerEcKey;\r
+  CONST EC_GROUP  *Group;\r
+  BOOLEAN         RetVal;\r
+  BIGNUM          *BnX;\r
+  BIGNUM          *BnY;\r
+  EC_POINT        *Point;\r
+  INT32           OpenSslNid;\r
+  UINTN           HalfSize;\r
+\r
+  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((Key == NULL) && (*KeySize != 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (PeerPublicSize > INT_MAX) {\r
+    return FALSE;\r
+  }\r
+\r
+  EcKey    = (EC_KEY *)EcContext;\r
+  Group    = EC_KEY_get0_group (EcKey);\r
+  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;\r
+  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (*KeySize < HalfSize) {\r
+    *KeySize = HalfSize;\r
+    return FALSE;\r
+  }\r
+\r
+  *KeySize = HalfSize;\r
+\r
+  RetVal    = FALSE;\r
+  Point     = NULL;\r
+  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);\r
+  BnY       = NULL;\r
+  Point     = EC_POINT_new (Group);\r
+  PeerEcKey = NULL;\r
+  if ((BnX == NULL) || (Point == NULL)) {\r
+    goto fail;\r
+  }\r
+\r
+  if (CompressFlag == NULL) {\r
+    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);\r
+    if (BnY == NULL) {\r
+      goto fail;\r
+    }\r
+\r
+    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {\r
+      goto fail;\r
+    }\r
+  } else {\r
+    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {\r
+      goto fail;\r
+    }\r
+  }\r
+\r
+  // Validate NIST ECDH public key\r
+  OpenSslNid = EC_GROUP_get_curve_name (Group);\r
+  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);\r
+  if (PeerEcKey == NULL) {\r
+    goto fail;\r
+  }\r
+\r
+  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {\r
+    goto fail;\r
+  }\r
+\r
+  if (EC_KEY_check_key (PeerEcKey) != 1) {\r
+    goto fail;\r
+  }\r
+\r
+  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {\r
+    goto fail;\r
+  }\r
+\r
+  RetVal = TRUE;\r
+\r
+fail:\r
+  BN_free (BnX);\r
+  BN_free (BnY);\r
+  EC_POINT_free (Point);\r
+  EC_KEY_free (PeerEcKey);\r
+  return RetVal;\r
+}\r
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
new file mode 100644 (file)
index 0000000..d9f1004
--- /dev/null
@@ -0,0 +1,496 @@
+/** @file\r
+  Elliptic Curve and ECDH API implementation based on OpenSSL\r
+\r
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+/**\r
+  Initialize new opaque EcGroup object. This object represents an EC curve and\r
+  and is used for calculation within this group. This object should be freed\r
+  using EcGroupFree() function.\r
+\r
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in\r
+                          BaseCryptLib.h).\r
+\r
+  @retval EcGroup object  On success.\r
+  @retval NULL            On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcGroupInit (\r
+  IN UINTN  CryptoNid\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.\r
+  This function will set the provided Big Number objects  to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[out] BnPrime    Group prime number.\r
+  @param[out] BnA        A coefficient.\r
+  @param[out] BnB        B coefficient..\r
+  @param[in]  BnCtx      BN context.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *BnPrime,\r
+  OUT VOID       *BnA,\r
+  OUT VOID       *BnB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get EC group order.\r
+  This function will set the provided Big Number object to the corresponding\r
+  value. The caller needs to make sure that the "out" BigNumber parameter\r
+  is properly initialized.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[out] BnOrder   Group prime number.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetOrder (\r
+  IN VOID   *EcGroup,\r
+  OUT VOID  *BnOrder\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Free previously allocated EC group object using EcGroupInit().\r
+\r
+  @param[in]  EcGroup   EC group object to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcGroupFree (\r
+  IN VOID  *EcGroup\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Initialize new opaque EC Point object. This object represents an EC point\r
+  within the given EC group (curve).\r
+\r
+  @param[in]  EC Group, properly initialized using EcGroupInit().\r
+\r
+  @retval EC Point object  On success.\r
+  @retval NULL             On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcPointInit (\r
+  IN CONST VOID  *EcGroup\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Free previously allocated EC Point object using EcPointInit().\r
+\r
+  @param[in]  EcPoint   EC Point to free.\r
+  @param[in]  Clear     TRUE iff the memory should be cleared.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcPointDeInit (\r
+  IN VOID     *EcPoint,\r
+  IN BOOLEAN  Clear\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Get EC point affine (x,y) coordinates.\r
+  This function will set the provided Big Number objects to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[out] BnX        X coordinate.\r
+  @param[out] BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointGetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  OUT VOID       *BnX,\r
+  OUT VOID       *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Set EC point affine (x,y) coordinates.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN CONST VOID  *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  EC Point addition. EcPointResult = EcPointA + EcPointB.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPointA         EC Point.\r
+  @param[in]  EcPointB         EC Point.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointAdd (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPoint          EC Point.\r
+  @param[in]  BnPScalar        P Scalar.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointMul (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPoint,\r
+  IN CONST VOID  *BnPScalar,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Calculate the inverse of the supplied EC point.\r
+\r
+  @param[in]     EcGroup   EC group object.\r
+  @param[in,out] EcPoint   EC point to invert.\r
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointInvert (\r
+  IN CONST VOID  *EcGroup,\r
+  IN OUT VOID    *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if the supplied point is on EC curve.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On curve.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsOnCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if the supplied point is at infinity.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+\r
+  @retval TRUE          At infinity.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsAtInfinity (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if EC points are equal.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPointA  EC point A.\r
+  @param[in]  EcPointB  EC point B.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          A == B.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointEqual (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Set EC point compressed coordinates. Points can be described in terms of\r
+  their compressed coordinates. For a point (x, y), for any given value for x\r
+  such that the point is on the curve there will only ever be two possible\r
+  values for y. Therefore, a point can be set using this function where BnX is\r
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two\r
+  possible values for y should be used.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC Point.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  YBit       0 or 1 to identify which Y value is used.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetCompressedCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN UINT8       YBit,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Allocates and Initializes one Elliptic Curve Context for subsequent use\r
+  with the NID.\r
+\r
+  @param[in]  Nid cipher NID\r
+  @return     Pointer to the Elliptic Curve Context that has been initialized.\r
+              If the allocations fails, EcNewByNid() returns NULL.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcNewByNid (\r
+  IN UINTN  Nid\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Release the specified EC context.\r
+\r
+  @param[in]  EcContext  Pointer to the EC context to be released.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcFree (\r
+  IN  VOID  *EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses\r
+  pseudo random number generator. The caller must make sure RandomSeed()\r
+  function was properly called before.\r
+  The Ec context should be correctly initialized by EcNewByNid.\r
+  This function generates random secret, and computes the public key (X, Y), which is\r
+  returned via parameter Public, PublicSize.\r
+  X is the first half of Public with size being PublicSize / 2,\r
+  Y is the second half of Public with size being PublicSize / 2.\r
+  EC context is updated accordingly.\r
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and\r
+  PublicSize is set to the required buffer size to obtain the public X, Y.\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PublicSize is NULL, then return FALSE.\r
+  If PublicSize is large enough but Public is NULL, then return FALSE.\r
+  @param[in, out]  EcContext      Pointer to the EC context.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval TRUE   EC public X,Y generation succeeded.\r
+  @retval FALSE  EC public X,Y generation failed.\r
+  @retval FALSE  PublicKeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGenerateKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Gets the public key component from the established EC context.\r
+  The Ec context should be correctly initialized by EcNewByNid, and successfully\r
+  generate key pair from EcGenerateKey().\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext      Pointer to EC context being set.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval  TRUE   EC key component was retrieved successfully.\r
+  @retval  FALSE  Invalid EC key component.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPubKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Computes exchanged common key.\r
+  Given peer's public key (X, Y), this function computes the exchanged common key,\r
+  based on its own context including value of curve parameter and random secret.\r
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,\r
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PeerPublic is NULL, then return FALSE.\r
+  If PeerPublicSize is 0, then return FALSE.\r
+  If Key is NULL, then return FALSE.\r
+  If KeySize is not large enough, then return FALSE.\r
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext          Pointer to the EC context.\r
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.\r
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.\r
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.\r
+  @param[out]      Key                Pointer to the buffer to receive generated key.\r
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.\r
+                                      On output, the size of data returned in Key buffer in bytes.\r
+  @retval TRUE   EC exchanged key generation succeeded.\r
+  @retval FALSE  EC exchanged key generation failed.\r
+  @retval FALSE  KeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDhComputeKey (\r
+  IN OUT  VOID         *EcContext,\r
+  IN      CONST UINT8  *PeerPublic,\r
+  IN      UINTN        PeerPublicSize,\r
+  IN      CONST INT32  *CompressFlag,\r
+  OUT     UINT8        *Key,\r
+  IN OUT  UINTN        *KeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index 986581319c867bc1f73da0e2be8b61e038a1bf43..9318052a51c54becc5eebb85efc399e18e8d9ac7 100644 (file)
@@ -60,6 +60,7 @@
   Pk/CryptTsNull.c\r
   Pk/CryptRsaPss.c\r
   Pk/CryptRsaPssSignNull.c\r
+  Pk/CryptEcNull.c\r
   Pem/CryptPem.c\r
   Bn/CryptBnNull.c\r
 \r
index 88ada0430d44c7d6edd4ea0433b52bbecc70f87b..9cb8d42ff45f20001915a6d7b377ac42e32c19e2 100644 (file)
@@ -50,6 +50,7 @@
   Pk/CryptX509Null.c\r
   Pk/CryptAuthenticodeNull.c\r
   Pk/CryptTsNull.c\r
+  Pk/CryptEcNull.c\r
   Pem/CryptPemNull.c\r
   Rand/CryptRandNull.c\r
   Pk/CryptRsaPssNull.c\r
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
new file mode 100644 (file)
index 0000000..d9f1004
--- /dev/null
@@ -0,0 +1,496 @@
+/** @file\r
+  Elliptic Curve and ECDH API implementation based on OpenSSL\r
+\r
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+/**\r
+  Initialize new opaque EcGroup object. This object represents an EC curve and\r
+  and is used for calculation within this group. This object should be freed\r
+  using EcGroupFree() function.\r
+\r
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in\r
+                          BaseCryptLib.h).\r
+\r
+  @retval EcGroup object  On success.\r
+  @retval NULL            On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcGroupInit (\r
+  IN UINTN  CryptoNid\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.\r
+  This function will set the provided Big Number objects  to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[out] BnPrime    Group prime number.\r
+  @param[out] BnA        A coefficient.\r
+  @param[out] BnB        B coefficient..\r
+  @param[in]  BnCtx      BN context.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *BnPrime,\r
+  OUT VOID       *BnA,\r
+  OUT VOID       *BnB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get EC group order.\r
+  This function will set the provided Big Number object to the corresponding\r
+  value. The caller needs to make sure that the "out" BigNumber parameter\r
+  is properly initialized.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[out] BnOrder   Group prime number.\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGroupGetOrder (\r
+  IN VOID   *EcGroup,\r
+  OUT VOID  *BnOrder\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Free previously allocated EC group object using EcGroupInit().\r
+\r
+  @param[in]  EcGroup   EC group object to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcGroupFree (\r
+  IN VOID  *EcGroup\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Initialize new opaque EC Point object. This object represents an EC point\r
+  within the given EC group (curve).\r
+\r
+  @param[in]  EC Group, properly initialized using EcGroupInit().\r
+\r
+  @retval EC Point object  On success.\r
+  @retval NULL             On failure.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcPointInit (\r
+  IN CONST VOID  *EcGroup\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Free previously allocated EC Point object using EcPointInit().\r
+\r
+  @param[in]  EcPoint   EC Point to free.\r
+  @param[in]  Clear     TRUE iff the memory should be cleared.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcPointDeInit (\r
+  IN VOID     *EcPoint,\r
+  IN BOOLEAN  Clear\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Get EC point affine (x,y) coordinates.\r
+  This function will set the provided Big Number objects to the corresponding\r
+  values. The caller needs to make sure all the "out" BigNumber parameters\r
+  are properly initialized.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[out] BnX        X coordinate.\r
+  @param[out] BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointGetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  OUT VOID       *BnX,\r
+  OUT VOID       *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Set EC point affine (x,y) coordinates.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC point object.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  BnY        Y coordinate.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetAffineCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN CONST VOID  *BnY,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  EC Point addition. EcPointResult = EcPointA + EcPointB.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPointA         EC Point.\r
+  @param[in]  EcPointB         EC Point.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointAdd (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.\r
+\r
+  @param[in]  EcGroup          EC group object.\r
+  @param[out] EcPointResult    EC point to hold the result. The point should\r
+                               be properly initialized.\r
+  @param[in]  EcPoint          EC Point.\r
+  @param[in]  BnPScalar        P Scalar.\r
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointMul (\r
+  IN CONST VOID  *EcGroup,\r
+  OUT VOID       *EcPointResult,\r
+  IN CONST VOID  *EcPoint,\r
+  IN CONST VOID  *BnPScalar,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Calculate the inverse of the supplied EC point.\r
+\r
+  @param[in]     EcGroup   EC group object.\r
+  @param[in,out] EcPoint   EC point to invert.\r
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointInvert (\r
+  IN CONST VOID  *EcGroup,\r
+  IN OUT VOID    *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if the supplied point is on EC curve.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On curve.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsOnCurve (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if the supplied point is at infinity.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPoint   EC point to check.\r
+\r
+  @retval TRUE          At infinity.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointIsAtInfinity (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPoint\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check if EC points are equal.\r
+\r
+  @param[in]  EcGroup   EC group object.\r
+  @param[in]  EcPointA  EC point A.\r
+  @param[in]  EcPointB  EC point B.\r
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          A == B.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointEqual (\r
+  IN CONST VOID  *EcGroup,\r
+  IN CONST VOID  *EcPointA,\r
+  IN CONST VOID  *EcPointB,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Set EC point compressed coordinates. Points can be described in terms of\r
+  their compressed coordinates. For a point (x, y), for any given value for x\r
+  such that the point is on the curve there will only ever be two possible\r
+  values for y. Therefore, a point can be set using this function where BnX is\r
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two\r
+  possible values for y should be used.\r
+\r
+  @param[in]  EcGroup    EC group object.\r
+  @param[in]  EcPoint    EC Point.\r
+  @param[in]  BnX        X coordinate.\r
+  @param[in]  YBit       0 or 1 to identify which Y value is used.\r
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().\r
+\r
+  @retval TRUE          On success.\r
+  @retval FALSE         Otherwise.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcPointSetCompressedCoordinates (\r
+  IN CONST VOID  *EcGroup,\r
+  IN VOID        *EcPoint,\r
+  IN CONST VOID  *BnX,\r
+  IN UINT8       YBit,\r
+  IN VOID        *BnCtx\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Allocates and Initializes one Elliptic Curve Context for subsequent use\r
+  with the NID.\r
+\r
+  @param[in]  Nid cipher NID\r
+  @return     Pointer to the Elliptic Curve Context that has been initialized.\r
+              If the allocations fails, EcNewByNid() returns NULL.\r
+**/\r
+VOID *\r
+EFIAPI\r
+EcNewByNid (\r
+  IN UINTN  Nid\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Release the specified EC context.\r
+\r
+  @param[in]  EcContext  Pointer to the EC context to be released.\r
+**/\r
+VOID\r
+EFIAPI\r
+EcFree (\r
+  IN  VOID  *EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses\r
+  pseudo random number generator. The caller must make sure RandomSeed()\r
+  function was properly called before.\r
+  The Ec context should be correctly initialized by EcNewByNid.\r
+  This function generates random secret, and computes the public key (X, Y), which is\r
+  returned via parameter Public, PublicSize.\r
+  X is the first half of Public with size being PublicSize / 2,\r
+  Y is the second half of Public with size being PublicSize / 2.\r
+  EC context is updated accordingly.\r
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and\r
+  PublicSize is set to the required buffer size to obtain the public X, Y.\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PublicSize is NULL, then return FALSE.\r
+  If PublicSize is large enough but Public is NULL, then return FALSE.\r
+  @param[in, out]  EcContext      Pointer to the EC context.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval TRUE   EC public X,Y generation succeeded.\r
+  @retval FALSE  EC public X,Y generation failed.\r
+  @retval FALSE  PublicKeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGenerateKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Gets the public key component from the established EC context.\r
+  The Ec context should be correctly initialized by EcNewByNid, and successfully\r
+  generate key pair from EcGenerateKey().\r
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext      Pointer to EC context being set.\r
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.\r
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.\r
+                                  On output, the size of data returned in Public buffer in bytes.\r
+  @retval  TRUE   EC key component was retrieved successfully.\r
+  @retval  FALSE  Invalid EC key component.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPubKey (\r
+  IN OUT  VOID   *EcContext,\r
+  OUT     UINT8  *PublicKey,\r
+  IN OUT  UINTN  *PublicKeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Computes exchanged common key.\r
+  Given peer's public key (X, Y), this function computes the exchanged common key,\r
+  based on its own context including value of curve parameter and random secret.\r
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,\r
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.\r
+  If EcContext is NULL, then return FALSE.\r
+  If PeerPublic is NULL, then return FALSE.\r
+  If PeerPublicSize is 0, then return FALSE.\r
+  If Key is NULL, then return FALSE.\r
+  If KeySize is not large enough, then return FALSE.\r
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.\r
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.\r
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.\r
+  @param[in, out]  EcContext          Pointer to the EC context.\r
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.\r
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.\r
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.\r
+  @param[out]      Key                Pointer to the buffer to receive generated key.\r
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.\r
+                                      On output, the size of data returned in Key buffer in bytes.\r
+  @retval TRUE   EC exchanged key generation succeeded.\r
+  @retval FALSE  EC exchanged key generation failed.\r
+  @retval FALSE  KeySize is not large enough.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDhComputeKey (\r
+  IN OUT  VOID         *EcContext,\r
+  IN      CONST UINT8  *PeerPublic,\r
+  IN      UINTN        PeerPublicSize,\r
+  IN      CONST INT32  *CompressFlag,\r
+  OUT     UINT8        *Key,\r
+  IN OUT  UINTN        *KeySize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r