public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2 1/3] CryptoPkg: Add EC support
       [not found] <cover.1663735439.git.yi1.li@intel.com>
@ 2022-09-21  4:54 ` yi1 li
  2022-09-21 16:21   ` [edk2-devel] " Michael D Kinney
  2022-09-21  4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
  2022-09-21  4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
  2 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-21  4:54 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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>
---
 CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
 .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
 .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
 .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
 .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
 .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
 .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
 8 files changed, 2186 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol
       [not found] <cover.1663735439.git.yi1.li@intel.com>
  2022-09-21  4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
@ 2022-09-21  4:54 ` yi1 li
  2022-09-21  4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
  2 siblings, 0 replies; 17+ messages in thread
From: yi1 li @ 2022-09-21  4:54 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828

The implementation provides CryptEc library functions
for EFI Driveer and EFI BaseCrypt Protocol.

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>
---
 CryptoPkg/CryptoPkg.dsc                       |   1 +
 CryptoPkg/Driver/Crypto.c                     | 496 +++++++++++
 .../Pcd/PcdCryptoServiceFamilyEnable.h        |  25 +
 .../BaseCryptLibOnProtocolPpi/CryptLib.c      | 469 ++++++++++
 CryptoPkg/Private/Protocol/Crypto.h           | 801 ++++++++++++++----
 5 files changed, 1607 insertions(+), 185 deletions(-)

diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index a766851728..4f6cece6ee 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -169,6 +169,7 @@
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsSet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsGet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Bn.Family                                | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
+  gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Ec.Family                                | 0
 !endif
 
 !if $(CRYPTO_SERVICES) == MIN_PEI
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index 07150ad2f2..9682a46778 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -5074,6 +5074,481 @@ CryptoServiceBigNumAddMod (
   return CALL_BASECRYPTLIB (Bn.Services.AddMod, BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
 }
 
+// =====================================================================================
+//    Basic Elliptic Curve Primitives
+// =====================================================================================
+
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success.
+  @retval NULL            On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcGroupInit (
+  IN UINTN  CryptoNid
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupInit, EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetCurve (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *BnPrime,
+  OUT VOID       *BnA,
+  OUT VOID       *BnB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupGetCurve, EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object.
+  @param[out] BnOrder   Group prime number.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetOrder (
+  IN VOID   *EcGroup,
+  OUT VOID  *BnOrder
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupGetOrder, EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+  Free previously allocated EC group object using EcGroupInit().
+
+  @param[in]  EcGroup   EC group object to free.
+**/
+VOID
+EFIAPI
+CryptoServiceEcGroupFree (
+  IN VOID  *EcGroup
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.GroupFree, EcGroupFree, (EcGroup));
+}
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit().
+
+  @retval EC Point object  On success.
+  @retval NULL             On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcPointInit (
+  IN CONST VOID  *EcGroup
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointInit, EcPointInit, (EcGroup), NULL);
+}
+
+/**
+  Free previously allocated EC Point object using EcPointInit().
+
+  @param[in]  EcPoint   EC Point to free.
+  @param[in]  Clear     TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+CryptoServiceEcPointDeInit (
+  IN VOID     *EcPoint,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.PointDeInit, EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[out] BnX        X coordinate.
+  @param[out] BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointGetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  OUT VOID       *BnX,
+  OUT VOID       *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointGetAffineCoordinates, EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[in]  BnX        X coordinate.
+  @param[in]  BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN CONST VOID  *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointSetAffineCoordinates, EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB.
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point.
+  @param[in]  EcPointB         EC Point.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointAdd (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointAdd, EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point.
+  @param[in]  BnPScalar        P Scalar.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointMul (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPoint,
+  IN CONST VOID  *BnPScalar,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointMul, EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object.
+  @param[in,out] EcPoint   EC point to invert.
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointInvert (
+  IN CONST VOID  *EcGroup,
+  IN OUT VOID    *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointInvert, EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is on EC curve.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On curve.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsOnCurve (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointIsOnCurve, EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is at infinity.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+
+  @retval TRUE          At infinity.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsAtInfinity (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointIsAtInfinity, EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+  Check if EC points are equal.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPointA  EC point A.
+  @param[in]  EcPointB  EC point B.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          A == B.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointEqual (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointEqual, EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC Point.
+  @param[in]  BnX        X coordinate.
+  @param[in]  YBit       0 or 1 to identify which Y value is used.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetCompressedCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN UINT8       YBit,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointSetCompressedCoordinates, EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+// =====================================================================================
+//    Elliptic Curve Diffie Hellman Primitives
+// =====================================================================================
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcNewByNid (
+  IN UINTN  Nid
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.NewByNid, EcNewByNid, (Nid), NULL);
+}
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+CryptoServiceEcFree (
+  IN  VOID  *EcContext
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.Free, EcFree, (EcContext));
+}
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGenerateKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GenerateKey, EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGetPubKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GetPubKey, EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcDhComputeKey (
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
+}
+
 const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   /// Version
   CryptoServiceGetCryptoVersion,
@@ -5306,4 +5781,25 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   CryptoServiceBigNumContextFree,
   CryptoServiceBigNumSetUint,
   CryptoServiceBigNumAddMod,
+  /// EC
+  CryptoServiceEcGroupInit,
+  CryptoServiceEcGroupGetCurve,
+  CryptoServiceEcGroupGetOrder,
+  CryptoServiceEcGroupFree,
+  CryptoServiceEcPointInit,
+  CryptoServiceEcPointDeInit,
+  CryptoServiceEcPointGetAffineCoordinates,
+  CryptoServiceEcPointSetAffineCoordinates,
+  CryptoServiceEcPointAdd,
+  CryptoServiceEcPointMul,
+  CryptoServiceEcPointInvert,
+  CryptoServiceEcPointIsOnCurve,
+  CryptoServiceEcPointIsAtInfinity,
+  CryptoServiceEcPointEqual,
+  CryptoServiceEcPointSetCompressedCoordinates,
+  CryptoServiceEcNewByNid,
+  CryptoServiceEcFree,
+  CryptoServiceEcGenerateKey,
+  CryptoServiceEcGetPubKey,
+  CryptoServiceEcDhComputeKey,
 };
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 1b3c9d8f52..65ea7807dc 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -331,6 +331,31 @@ typedef struct {
     } Services;
     UINT32    Family;
   } Bn;
+  union {
+    struct {
+      UINT8    GroupInit                     : 1;
+      UINT8    GroupGetCurve                 : 1;
+      UINT8    GroupGetOrder                 : 1;
+      UINT8    GroupFree                     : 1;
+      UINT8    PointInit                     : 1;
+      UINT8    PointDeInit                   : 1;
+      UINT8    PointGetAffineCoordinates     : 1;
+      UINT8    PointSetAffineCoordinates     : 1;
+      UINT8    PointAdd                      : 1;
+      UINT8    PointMul                      : 1;
+      UINT8    PointInvert                   : 1;
+      UINT8    PointIsOnCurve                : 1;
+      UINT8    PointIsAtInfinity             : 1;
+      UINT8    PointEqual                    : 1;
+      UINT8    PointSetCompressedCoordinates : 1;
+      UINT8    NewByNid                      : 1;
+      UINT8    Free                          : 1;
+      UINT8    GenerateKey                   : 1;
+      UINT8    GetPubKey                     : 1;
+      UINT8    DhComputeKey                  : 1;
+    } Services;
+    UINT32    Family;
+  } Ec;
 } PCD_CRYPTO_SERVICE_FAMILY_ENABLE;
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index c5d71b5269..3746c823d9 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -4104,3 +4104,472 @@ BigNumAddMod (
 {
   CALL_CRYPTO_SERVICE (BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
 }
+
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success.
+  @retval NULL            On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+  IN UINTN  CryptoNid
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *BnPrime,
+  OUT VOID       *BnA,
+  OUT VOID       *BnB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object.
+  @param[out] BnOrder   Group prime number.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+  IN VOID   *EcGroup,
+  OUT VOID  *BnOrder
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+  Free previously allocated EC group object using EcGroupInit().
+
+  @param[in]  EcGroup   EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+  IN VOID  *EcGroup
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcGroupFree, (EcGroup));
+}
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit().
+
+  @retval EC Point object  On success.
+  @retval NULL             On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+  IN CONST VOID  *EcGroup
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointInit, (EcGroup), NULL);
+}
+
+/**
+  Free previously allocated EC Point object using EcPointInit().
+
+  @param[in]  EcPoint   EC Point to free.
+  @param[in]  Clear     TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+  IN VOID     *EcPoint,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[out] BnX        X coordinate.
+  @param[out] BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  OUT VOID       *BnX,
+  OUT VOID       *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[in]  BnX        X coordinate.
+  @param[in]  BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN CONST VOID  *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point.
+  @param[in]  EcPointB         EC Point.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point.
+  @param[in]  BnPScalar        P Scalar.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPoint,
+  IN CONST VOID  *BnPScalar,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object.
+  @param[in,out] EcPoint   EC point to invert.
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+  IN CONST VOID  *EcGroup,
+  IN OUT VOID    *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is on EC curve.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On curve.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is at infinity.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+
+  @retval TRUE          At infinity.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+  Check if EC points are equal.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPointA  EC point A.
+  @param[in]  EcPointB  EC point B.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          A == B.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC Point.
+  @param[in]  BnX        X coordinate.
+  @param[in]  YBit       0 or 1 to identify which Y value is used.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN UINT8       YBit,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+  IN UINTN  Nid
+  )
+{
+  CALL_CRYPTO_SERVICE (EcNewByNid, (Nid), NULL);
+}
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+  IN  VOID  *EcContext
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcFree, (EcContext));
+}
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to the buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
+}
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index 9812568cc7..aa4bfefdd2 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -21,7 +21,7 @@
 /// the EDK II Crypto Protocol is extended, this version define must be
 /// increased.
 ///
-#define EDKII_CRYPTO_VERSION  9
+#define EDKII_CRYPTO_VERSION  10
 
 ///
 /// EDK II Crypto Protocol forward declaration
@@ -3887,221 +3887,652 @@ BOOLEAN
   OUT VOID *BnRes
   );
 
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success
+  @retval NULL            On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_INIT)(
+  IN UINTN  CryptoNid
+  );
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_CURVE)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *BnPrime,
+  OUT VOID *BnA,
+  OUT VOID *BnB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object
+  @param[out] BnOrder   Group prime number
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_ORDER)(
+  IN VOID *EcGroup,
+  OUT VOID *BnOrder
+  );
+
+/**
+  Free previously allocated EC group object using EcGroupInit()
+
+  @param[in]  EcGroup   EC group object to free
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_FREE)(
+  IN VOID *EcGroup
+  );
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit()
+
+  @retval EC Point object  On success
+  @retval NULL             On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INIT)(
+  IN CONST VOID *EcGroup
+  );
+
+/**
+  Free previously allocated EC Point object using EcPointInit()
+
+  @param[in]  EcPoint   EC Point to free
+  @param[in]  Clear     TRUE iff the memory should be cleared
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_POINT_DE_INIT)(
+  IN VOID *EcPoint,
+  IN BOOLEAN Clear
+  );
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC point object
+  @param[out] BnX        X coordinate
+  @param[out] BnY        Y coordinate
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint,
+  OUT VOID *BnX,
+  OUT VOID *BnY,
+  IN VOID *BnCtx
+  );
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC point object
+  @param[in]  BnX        X coordinate
+  @param[in]  BnY        Y coordinate
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN VOID *EcPoint,
+  IN CONST VOID *BnX,
+  IN CONST VOID *BnY,
+  IN VOID *BnCtx
+  );
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB
+
+  @param[in]  EcGroup          EC group object
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point
+  @param[in]  EcPointB         EC Point
+  @param[in]  BnCtx            BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_ADD)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *EcPointResult,
+  IN CONST VOID *EcPointA,
+  IN CONST VOID *EcPointB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar
+
+  @param[in]  EcGroup          EC group object
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point
+  @param[in]  BnPScalar        P Scalar
+  @param[in]  BnCtx            BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_MUL)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *EcPointResult,
+  IN CONST VOID *EcPoint,
+  IN CONST VOID *BnPScalar,
+  IN VOID *BnCtx
+  );
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object
+  @param[in,out] EcPoint   EC point to invert
+  @param[in]     BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INVERT)(
+  IN CONST VOID *EcGroup,
+  IN OUT VOID *EcPoint,
+  IN VOID *BnCtx
+  );
+
+/**
+  Check if the supplied point is on EC curve
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPoint   EC point to check
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE           On curve
+  @retval FALSE          Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_ON_CURVE)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint,
+  IN VOID *BnCtx
+  );
+
+/**
+  Check if the supplied point is at infinity
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPoint   EC point to check
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          At infinity
+  @retval FALSE         Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint
+  );
+
+/**
+  Check if EC points are equal
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPointA  EC point A
+  @param[in]  EcPointB  EC point B
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          A == B
+  @retval FALSE         Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_EQUAL)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPointA,
+  IN CONST VOID *EcPointB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC Point
+  @param[in]  BnX        X coordinate
+  @param[in]  YBit       0 or 1 to identify which Y value is used
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN VOID *EcPoint,
+  IN CONST VOID *BnX,
+  IN UINT8 YBit,
+  IN VOID *BnCtx
+  );
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_NEW_BY_NID)(
+  IN UINTN  Nid
+  );
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_FREE)(
+  IN  VOID  *EcContext
+  );
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GENERATE_KEY)(
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  );
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GET_PUB_KEY)(
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  );
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_DH_COMPUTE_KEY)(
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  );
+
 ///
 /// EDK II Crypto Protocol
 ///
 struct _EDKII_CRYPTO_PROTOCOL {
   /// Version
-  EDKII_CRYPTO_GET_VERSION                           GetVersion;
+  EDKII_CRYPTO_GET_VERSION                            GetVersion;
   /// HMAC MD5 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW               DeprecatedHmacMd5New;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE              DeprecatedHmacMd5Free;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY           DeprecatedHmacMd5SetKey;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE         DeprecatedHmacMd5Duplicate;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE            DeprecatedHmacMd5Update;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL             DeprecatedHmacMd5Final;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW                DeprecatedHmacMd5New;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE               DeprecatedHmacMd5Free;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY            DeprecatedHmacMd5SetKey;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE          DeprecatedHmacMd5Duplicate;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE             DeprecatedHmacMd5Update;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL              DeprecatedHmacMd5Final;
   /// HMAC SHA1 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW              DeprecatedHmacSha1New;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE             DeprecatedHmacSha1Free;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY          DeprecatedHmacSha1SetKey;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE        DeprecatedHmacSha1Duplicate;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE           DeprecatedHmacSha1Update;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL            DeprecatedHmacSha1Final;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW               DeprecatedHmacSha1New;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE              DeprecatedHmacSha1Free;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY           DeprecatedHmacSha1SetKey;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE         DeprecatedHmacSha1Duplicate;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE            DeprecatedHmacSha1Update;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL             DeprecatedHmacSha1Final;
   /// HMAC SHA256
-  EDKII_CRYPTO_HMAC_SHA256_NEW                       HmacSha256New;
-  EDKII_CRYPTO_HMAC_SHA256_FREE                      HmacSha256Free;
-  EDKII_CRYPTO_HMAC_SHA256_SET_KEY                   HmacSha256SetKey;
-  EDKII_CRYPTO_HMAC_SHA256_DUPLICATE                 HmacSha256Duplicate;
-  EDKII_CRYPTO_HMAC_SHA256_UPDATE                    HmacSha256Update;
-  EDKII_CRYPTO_HMAC_SHA256_FINAL                     HmacSha256Final;
+  EDKII_CRYPTO_HMAC_SHA256_NEW                        HmacSha256New;
+  EDKII_CRYPTO_HMAC_SHA256_FREE                       HmacSha256Free;
+  EDKII_CRYPTO_HMAC_SHA256_SET_KEY                    HmacSha256SetKey;
+  EDKII_CRYPTO_HMAC_SHA256_DUPLICATE                  HmacSha256Duplicate;
+  EDKII_CRYPTO_HMAC_SHA256_UPDATE                     HmacSha256Update;
+  EDKII_CRYPTO_HMAC_SHA256_FINAL                      HmacSha256Final;
   /// Md4 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE       DeprecatedMd4GetContextSize;
-  DEPRECATED_EDKII_CRYPTO_MD4_INIT                   DeprecatedMd4Init;
-  DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE              DeprecatedMd4Duplicate;
-  DEPRECATED_EDKII_CRYPTO_MD4_UPDATE                 DeprecatedMd4Update;
-  DEPRECATED_EDKII_CRYPTO_MD4_FINAL                  DeprecatedMd4Final;
-  DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL               DeprecatedMd4HashAll;
+  DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE        DeprecatedMd4GetContextSize;
+  DEPRECATED_EDKII_CRYPTO_MD4_INIT                    DeprecatedMd4Init;
+  DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE               DeprecatedMd4Duplicate;
+  DEPRECATED_EDKII_CRYPTO_MD4_UPDATE                  DeprecatedMd4Update;
+  DEPRECATED_EDKII_CRYPTO_MD4_FINAL                   DeprecatedMd4Final;
+  DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL                DeprecatedMd4HashAll;
   /// Md5
-  EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE                  Md5GetContextSize;
-  EDKII_CRYPTO_MD5_INIT                              Md5Init;
-  EDKII_CRYPTO_MD5_DUPLICATE                         Md5Duplicate;
-  EDKII_CRYPTO_MD5_UPDATE                            Md5Update;
-  EDKII_CRYPTO_MD5_FINAL                             Md5Final;
-  EDKII_CRYPTO_MD5_HASH_ALL                          Md5HashAll;
+  EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE                   Md5GetContextSize;
+  EDKII_CRYPTO_MD5_INIT                               Md5Init;
+  EDKII_CRYPTO_MD5_DUPLICATE                          Md5Duplicate;
+  EDKII_CRYPTO_MD5_UPDATE                             Md5Update;
+  EDKII_CRYPTO_MD5_FINAL                              Md5Final;
+  EDKII_CRYPTO_MD5_HASH_ALL                           Md5HashAll;
   /// Pkcs
-  EDKII_CRYPTO_PKCS1_ENCRYPT_V2                      Pkcs1v2Encrypt;
-  EDKII_CRYPTO_PKCS5_PW_HASH                         Pkcs5HashPassword;
-  EDKII_CRYPTO_PKCS7_VERIFY                          Pkcs7Verify;
-  EDKII_CRYPTO_PKCS7_VERIFY_EKU                      VerifyEKUsInPkcs7Signature;
-  EDKII_CRYPTO_PKCS7_GET_SIGNERS                     Pkcs7GetSigners;
-  EDKII_CRYPTO_PKCS7_FREE_SIGNERS                    Pkcs7FreeSigners;
-  EDKII_CRYPTO_PKCS7_SIGN                            Pkcs7Sign;
-  EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT            Pkcs7GetAttachedContent;
-  EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST           Pkcs7GetCertificatesList;
-  EDKII_CRYPTO_AUTHENTICODE_VERIFY                   AuthenticodeVerify;
-  EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY                ImageTimestampVerify;
+  EDKII_CRYPTO_PKCS1_ENCRYPT_V2                       Pkcs1v2Encrypt;
+  EDKII_CRYPTO_PKCS5_PW_HASH                          Pkcs5HashPassword;
+  EDKII_CRYPTO_PKCS7_VERIFY                           Pkcs7Verify;
+  EDKII_CRYPTO_PKCS7_VERIFY_EKU                       VerifyEKUsInPkcs7Signature;
+  EDKII_CRYPTO_PKCS7_GET_SIGNERS                      Pkcs7GetSigners;
+  EDKII_CRYPTO_PKCS7_FREE_SIGNERS                     Pkcs7FreeSigners;
+  EDKII_CRYPTO_PKCS7_SIGN                             Pkcs7Sign;
+  EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT             Pkcs7GetAttachedContent;
+  EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST            Pkcs7GetCertificatesList;
+  EDKII_CRYPTO_AUTHENTICODE_VERIFY                    AuthenticodeVerify;
+  EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY                 ImageTimestampVerify;
   /// DH
-  EDKII_CRYPTO_DH_NEW                                DhNew;
-  EDKII_CRYPTO_DH_FREE                               DhFree;
-  EDKII_CRYPTO_DH_GENERATE_PARAMETER                 DhGenerateParameter;
-  EDKII_CRYPTO_DH_SET_PARAMETER                      DhSetParameter;
-  EDKII_CRYPTO_DH_GENERATE_KEY                       DhGenerateKey;
-  EDKII_CRYPTO_DH_COMPUTE_KEY                        DhComputeKey;
+  EDKII_CRYPTO_DH_NEW                                 DhNew;
+  EDKII_CRYPTO_DH_FREE                                DhFree;
+  EDKII_CRYPTO_DH_GENERATE_PARAMETER                  DhGenerateParameter;
+  EDKII_CRYPTO_DH_SET_PARAMETER                       DhSetParameter;
+  EDKII_CRYPTO_DH_GENERATE_KEY                        DhGenerateKey;
+  EDKII_CRYPTO_DH_COMPUTE_KEY                         DhComputeKey;
   /// Random
-  EDKII_CRYPTO_RANDOM_SEED                           RandomSeed;
-  EDKII_CRYPTO_RANDOM_BYTES                          RandomBytes;
+  EDKII_CRYPTO_RANDOM_SEED                            RandomSeed;
+  EDKII_CRYPTO_RANDOM_BYTES                           RandomBytes;
   /// RSA
-  EDKII_CRYPTO_RSA_VERIFY_PKCS1                      RsaVerifyPkcs1;
-  EDKII_CRYPTO_RSA_NEW                               RsaNew;
-  EDKII_CRYPTO_RSA_FREE                              RsaFree;
-  EDKII_CRYPTO_RSA_SET_KEY                           RsaSetKey;
-  EDKII_CRYPTO_RSA_GET_KEY                           RsaGetKey;
-  EDKII_CRYPTO_RSA_GENERATE_KEY                      RsaGenerateKey;
-  EDKII_CRYPTO_RSA_CHECK_KEY                         RsaCheckKey;
-  EDKII_CRYPTO_RSA_PKCS1_SIGN                        RsaPkcs1Sign;
-  EDKII_CRYPTO_RSA_PKCS1_VERIFY                      RsaPkcs1Verify;
-  EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM          RsaGetPrivateKeyFromPem;
-  EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509          RsaGetPublicKeyFromX509;
+  EDKII_CRYPTO_RSA_VERIFY_PKCS1                       RsaVerifyPkcs1;
+  EDKII_CRYPTO_RSA_NEW                                RsaNew;
+  EDKII_CRYPTO_RSA_FREE                               RsaFree;
+  EDKII_CRYPTO_RSA_SET_KEY                            RsaSetKey;
+  EDKII_CRYPTO_RSA_GET_KEY                            RsaGetKey;
+  EDKII_CRYPTO_RSA_GENERATE_KEY                       RsaGenerateKey;
+  EDKII_CRYPTO_RSA_CHECK_KEY                          RsaCheckKey;
+  EDKII_CRYPTO_RSA_PKCS1_SIGN                         RsaPkcs1Sign;
+  EDKII_CRYPTO_RSA_PKCS1_VERIFY                       RsaPkcs1Verify;
+  EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM           RsaGetPrivateKeyFromPem;
+  EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509           RsaGetPublicKeyFromX509;
   /// Sha1
-  EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE                 Sha1GetContextSize;
-  EDKII_CRYPTO_SHA1_INIT                             Sha1Init;
-  EDKII_CRYPTO_SHA1_DUPLICATE                        Sha1Duplicate;
-  EDKII_CRYPTO_SHA1_UPDATE                           Sha1Update;
-  EDKII_CRYPTO_SHA1_FINAL                            Sha1Final;
-  EDKII_CRYPTO_SHA1_HASH_ALL                         Sha1HashAll;
+  EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE                  Sha1GetContextSize;
+  EDKII_CRYPTO_SHA1_INIT                              Sha1Init;
+  EDKII_CRYPTO_SHA1_DUPLICATE                         Sha1Duplicate;
+  EDKII_CRYPTO_SHA1_UPDATE                            Sha1Update;
+  EDKII_CRYPTO_SHA1_FINAL                             Sha1Final;
+  EDKII_CRYPTO_SHA1_HASH_ALL                          Sha1HashAll;
   /// Sha256
-  EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE               Sha256GetContextSize;
-  EDKII_CRYPTO_SHA256_INIT                           Sha256Init;
-  EDKII_CRYPTO_SHA256_DUPLICATE                      Sha256Duplicate;
-  EDKII_CRYPTO_SHA256_UPDATE                         Sha256Update;
-  EDKII_CRYPTO_SHA256_FINAL                          Sha256Final;
-  EDKII_CRYPTO_SHA256_HASH_ALL                       Sha256HashAll;
+  EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE                Sha256GetContextSize;
+  EDKII_CRYPTO_SHA256_INIT                            Sha256Init;
+  EDKII_CRYPTO_SHA256_DUPLICATE                       Sha256Duplicate;
+  EDKII_CRYPTO_SHA256_UPDATE                          Sha256Update;
+  EDKII_CRYPTO_SHA256_FINAL                           Sha256Final;
+  EDKII_CRYPTO_SHA256_HASH_ALL                        Sha256HashAll;
   /// Sha384
-  EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE               Sha384GetContextSize;
-  EDKII_CRYPTO_SHA384_INIT                           Sha384Init;
-  EDKII_CRYPTO_SHA384_DUPLICATE                      Sha384Duplicate;
-  EDKII_CRYPTO_SHA384_UPDATE                         Sha384Update;
-  EDKII_CRYPTO_SHA384_FINAL                          Sha384Final;
-  EDKII_CRYPTO_SHA384_HASH_ALL                       Sha384HashAll;
+  EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE                Sha384GetContextSize;
+  EDKII_CRYPTO_SHA384_INIT                            Sha384Init;
+  EDKII_CRYPTO_SHA384_DUPLICATE                       Sha384Duplicate;
+  EDKII_CRYPTO_SHA384_UPDATE                          Sha384Update;
+  EDKII_CRYPTO_SHA384_FINAL                           Sha384Final;
+  EDKII_CRYPTO_SHA384_HASH_ALL                        Sha384HashAll;
   /// Sha512
-  EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE               Sha512GetContextSize;
-  EDKII_CRYPTO_SHA512_INIT                           Sha512Init;
-  EDKII_CRYPTO_SHA512_DUPLICATE                      Sha512Duplicate;
-  EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
-  EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
-  EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
+  EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE                Sha512GetContextSize;
+  EDKII_CRYPTO_SHA512_INIT                            Sha512Init;
+  EDKII_CRYPTO_SHA512_DUPLICATE                       Sha512Duplicate;
+  EDKII_CRYPTO_SHA512_UPDATE                          Sha512Update;
+  EDKII_CRYPTO_SHA512_FINAL                           Sha512Final;
+  EDKII_CRYPTO_SHA512_HASH_ALL                        Sha512HashAll;
   /// X509
-  EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
-  EDKII_CRYPTO_X509_GET_COMMON_NAME                  X509GetCommonName;
-  EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME            X509GetOrganizationName;
-  EDKII_CRYPTO_X509_VERIFY_CERT                      X509VerifyCert;
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE            X509ConstructCertificate;
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK      X509ConstructCertificateStack;
-  EDKII_CRYPTO_X509_FREE                             X509Free;
-  EDKII_CRYPTO_X509_STACK_FREE                       X509StackFree;
-  EDKII_CRYPTO_X509_GET_TBS_CERT                     X509GetTBSCert;
+  EDKII_CRYPTO_X509_GET_SUBJECT_NAME                  X509GetSubjectName;
+  EDKII_CRYPTO_X509_GET_COMMON_NAME                   X509GetCommonName;
+  EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME             X509GetOrganizationName;
+  EDKII_CRYPTO_X509_VERIFY_CERT                       X509VerifyCert;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE             X509ConstructCertificate;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK       X509ConstructCertificateStack;
+  EDKII_CRYPTO_X509_FREE                              X509Free;
+  EDKII_CRYPTO_X509_STACK_FREE                        X509StackFree;
+  EDKII_CRYPTO_X509_GET_TBS_CERT                      X509GetTBSCert;
   /// TDES - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE      DeprecatedTdesGetContextSize;
-  DEPRECATED_EDKII_CRYPTO_TDES_INIT                  DeprecatedTdesInit;
-  DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT           DeprecatedTdesEcbEncrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT           DeprecatedTdesEcbDecrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT           DeprecatedTdesCbcEncrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT           DeprecatedTdesCbcDecrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE       DeprecatedTdesGetContextSize;
+  DEPRECATED_EDKII_CRYPTO_TDES_INIT                   DeprecatedTdesInit;
+  DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT            DeprecatedTdesEcbEncrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT            DeprecatedTdesEcbDecrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT            DeprecatedTdesCbcEncrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT            DeprecatedTdesCbcDecrypt;
   /// AES - ECB Mode is deprecated and unsupported
-  EDKII_CRYPTO_AES_GET_CONTEXT_SIZE                  AesGetContextSize;
-  EDKII_CRYPTO_AES_INIT                              AesInit;
-  DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT            DeprecatedAesEcbEncrypt;
-  DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT            DeprecatedAesEcbDecrypt;
-  EDKII_CRYPTO_AES_CBC_ENCRYPT                       AesCbcEncrypt;
-  EDKII_CRYPTO_AES_CBC_DECRYPT                       AesCbcDecrypt;
+  EDKII_CRYPTO_AES_GET_CONTEXT_SIZE                   AesGetContextSize;
+  EDKII_CRYPTO_AES_INIT                               AesInit;
+  DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT             DeprecatedAesEcbEncrypt;
+  DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT             DeprecatedAesEcbDecrypt;
+  EDKII_CRYPTO_AES_CBC_ENCRYPT                        AesCbcEncrypt;
+  EDKII_CRYPTO_AES_CBC_DECRYPT                        AesCbcDecrypt;
   /// Arc4 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE      DeprecatedArc4GetContextSize;
-  DEPRECATED_EDKII_CRYPTO_ARC4_INIT                  DeprecatedArc4Init;
-  DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT               DeprecatedArc4Encrypt;
-  DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT               DeprecatedArc4Decrypt;
-  DEPRECATED_EDKII_CRYPTO_ARC4_RESET                 DeprecatedArc4Reset;
+  DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE       DeprecatedArc4GetContextSize;
+  DEPRECATED_EDKII_CRYPTO_ARC4_INIT                   DeprecatedArc4Init;
+  DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT                DeprecatedArc4Encrypt;
+  DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT                DeprecatedArc4Decrypt;
+  DEPRECATED_EDKII_CRYPTO_ARC4_RESET                  DeprecatedArc4Reset;
   /// SM3
-  EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE                  Sm3GetContextSize;
-  EDKII_CRYPTO_SM3_INIT                              Sm3Init;
-  EDKII_CRYPTO_SM3_DUPLICATE                         Sm3Duplicate;
-  EDKII_CRYPTO_SM3_UPDATE                            Sm3Update;
-  EDKII_CRYPTO_SM3_FINAL                             Sm3Final;
-  EDKII_CRYPTO_SM3_HASH_ALL                          Sm3HashAll;
+  EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE                   Sm3GetContextSize;
+  EDKII_CRYPTO_SM3_INIT                               Sm3Init;
+  EDKII_CRYPTO_SM3_DUPLICATE                          Sm3Duplicate;
+  EDKII_CRYPTO_SM3_UPDATE                             Sm3Update;
+  EDKII_CRYPTO_SM3_FINAL                              Sm3Final;
+  EDKII_CRYPTO_SM3_HASH_ALL                           Sm3HashAll;
   /// HKDF
-  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND       HkdfSha256ExtractAndExpand;
+  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND        HkdfSha256ExtractAndExpand;
   /// X509 (Continued)
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V    X509ConstructCertificateStackV;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V     X509ConstructCertificateStackV;
   /// TLS
-  EDKII_CRYPTO_TLS_INITIALIZE                        TlsInitialize;
-  EDKII_CRYPTO_TLS_CTX_FREE                          TlsCtxFree;
-  EDKII_CRYPTO_TLS_CTX_NEW                           TlsCtxNew;
-  EDKII_CRYPTO_TLS_FREE                              TlsFree;
-  EDKII_CRYPTO_TLS_NEW                               TlsNew;
-  EDKII_CRYPTO_TLS_IN_HANDSHAKE                      TlsInHandshake;
-  EDKII_CRYPTO_TLS_DO_HANDSHAKE                      TlsDoHandshake;
-  EDKII_CRYPTO_TLS_HANDLE_ALERT                      TlsHandleAlert;
-  EDKII_CRYPTO_TLS_CLOSE_NOTIFY                      TlsCloseNotify;
-  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT                  TlsCtrlTrafficOut;
-  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN                   TlsCtrlTrafficIn;
-  EDKII_CRYPTO_TLS_READ                              TlsRead;
-  EDKII_CRYPTO_TLS_WRITE                             TlsWrite;
+  EDKII_CRYPTO_TLS_INITIALIZE                         TlsInitialize;
+  EDKII_CRYPTO_TLS_CTX_FREE                           TlsCtxFree;
+  EDKII_CRYPTO_TLS_CTX_NEW                            TlsCtxNew;
+  EDKII_CRYPTO_TLS_FREE                               TlsFree;
+  EDKII_CRYPTO_TLS_NEW                                TlsNew;
+  EDKII_CRYPTO_TLS_IN_HANDSHAKE                       TlsInHandshake;
+  EDKII_CRYPTO_TLS_DO_HANDSHAKE                       TlsDoHandshake;
+  EDKII_CRYPTO_TLS_HANDLE_ALERT                       TlsHandleAlert;
+  EDKII_CRYPTO_TLS_CLOSE_NOTIFY                       TlsCloseNotify;
+  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT                   TlsCtrlTrafficOut;
+  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN                    TlsCtrlTrafficIn;
+  EDKII_CRYPTO_TLS_READ                               TlsRead;
+  EDKII_CRYPTO_TLS_WRITE                              TlsWrite;
   /// TLS Set
-  EDKII_CRYPTO_TLS_SET_VERSION                       TlsSetVersion;
-  EDKII_CRYPTO_TLS_SET_CONNECTION_END                TlsSetConnectionEnd;
-  EDKII_CRYPTO_TLS_SET_CIPHER_LIST                   TlsSetCipherList;
-  EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD            TlsSetCompressionMethod;
-  EDKII_CRYPTO_TLS_SET_VERIFY                        TlsSetVerify;
-  EDKII_CRYPTO_TLS_SET_VERIFY_HOST                   TlsSetVerifyHost;
-  EDKII_CRYPTO_TLS_SET_SESSIONID                     TlsSetSessionId;
-  EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE                TlsSetCaCertificate;
-  EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT              TlsSetHostPublicCert;
-  EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY              TlsSetHostPrivateKey;
-  EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST          TlsSetCertRevocationList;
+  EDKII_CRYPTO_TLS_SET_VERSION                        TlsSetVersion;
+  EDKII_CRYPTO_TLS_SET_CONNECTION_END                 TlsSetConnectionEnd;
+  EDKII_CRYPTO_TLS_SET_CIPHER_LIST                    TlsSetCipherList;
+  EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD             TlsSetCompressionMethod;
+  EDKII_CRYPTO_TLS_SET_VERIFY                         TlsSetVerify;
+  EDKII_CRYPTO_TLS_SET_VERIFY_HOST                    TlsSetVerifyHost;
+  EDKII_CRYPTO_TLS_SET_SESSIONID                      TlsSetSessionId;
+  EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE                 TlsSetCaCertificate;
+  EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT               TlsSetHostPublicCert;
+  EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY               TlsSetHostPrivateKey;
+  EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST           TlsSetCertRevocationList;
   /// TLS Get
-  EDKII_CRYPTO_TLS_GET_VERSION                       TlsGetVersion;
-  EDKII_CRYPTO_TLS_GET_CONNECTION_END                TlsGetConnectionEnd;
-  EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER                TlsGetCurrentCipher;
-  EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID        TlsGetCurrentCompressionId;
-  EDKII_CRYPTO_TLS_GET_VERIFY                        TlsGetVerify;
-  EDKII_CRYPTO_TLS_GET_SESSION_ID                    TlsGetSessionId;
-  EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM                 TlsGetClientRandom;
-  EDKII_CRYPTO_TLS_GET_SERVER_RANDOM                 TlsGetServerRandom;
-  EDKII_CRYPTO_TLS_GET_KEY_MATERIAL                  TlsGetKeyMaterial;
-  EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE                TlsGetCaCertificate;
-  EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT              TlsGetHostPublicCert;
-  EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY              TlsGetHostPrivateKey;
-  EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST          TlsGetCertRevocationList;
+  EDKII_CRYPTO_TLS_GET_VERSION                        TlsGetVersion;
+  EDKII_CRYPTO_TLS_GET_CONNECTION_END                 TlsGetConnectionEnd;
+  EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER                 TlsGetCurrentCipher;
+  EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID         TlsGetCurrentCompressionId;
+  EDKII_CRYPTO_TLS_GET_VERIFY                         TlsGetVerify;
+  EDKII_CRYPTO_TLS_GET_SESSION_ID                     TlsGetSessionId;
+  EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM                  TlsGetClientRandom;
+  EDKII_CRYPTO_TLS_GET_SERVER_RANDOM                  TlsGetServerRandom;
+  EDKII_CRYPTO_TLS_GET_KEY_MATERIAL                   TlsGetKeyMaterial;
+  EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE                 TlsGetCaCertificate;
+  EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT               TlsGetHostPublicCert;
+  EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY               TlsGetHostPrivateKey;
+  EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST           TlsGetCertRevocationList;
   /// RSA PSS
-  EDKII_CRYPTO_RSA_PSS_SIGN                          RsaPssSign;
-  EDKII_CRYPTO_RSA_PSS_VERIFY                        RsaPssVerify;
+  EDKII_CRYPTO_RSA_PSS_SIGN                           RsaPssSign;
+  EDKII_CRYPTO_RSA_PSS_VERIFY                         RsaPssVerify;
   /// Parallel hash
-  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
+  EDKII_CRYPTO_PARALLEL_HASH_ALL                      ParallelHash256HashAll;
   /// Big Number
-  EDKII_CRYPTO_BIGNUM_INIT                           BigNumInit;
-  EDKII_CRYPTO_BIGNUM_FROM_BIN                       BigNumFromBin;
-  EDKII_CRYPTO_BIGNUM_TO_BIN                         BigNumToBin;
-  EDKII_CRYPTO_BIGNUM_FREE                           BigNumFree;
-  EDKII_CRYPTO_BIGNUM_ADD                            BigNumAdd;
-  EDKII_CRYPTO_BIGNUM_SUB                            BigNumSub;
-  EDKII_CRYPTO_BIGNUM_MOD                            BigNumMod;
-  EDKII_CRYPTO_BIGNUM_EXP_MOD                        BigNumExpMod;
-  EDKII_CRYPTO_BIGNUM_INVERSE_MOD                    BigNumInverseMod;
-  EDKII_CRYPTO_BIGNUM_DIV                            BigNumDiv;
-  EDKII_CRYPTO_BIGNUM_MUL_MOD                        BigNumMulMod;
-  EDKII_CRYPTO_BIGNUM_CMP                            BigNumCmp;
-  EDKII_CRYPTO_BIGNUM_BITS                           BigNumBits;
-  EDKII_CRYPTO_BIGNUM_BYTES                          BigNumBytes;
-  EDKII_CRYPTO_BIGNUM_IS_WORD                        BigNumIsWord;
-  EDKII_CRYPTO_BIGNUM_IS_ODD                         BigNumIsOdd;
-  EDKII_CRYPTO_BIGNUM_COPY                           BigNumCopy;
-  EDKII_CRYPTO_BIGNUM_VALUE_ONE                      BigNumValueOne;
-  EDKII_CRYPTO_BIGNUM_R_SHIFT                        BigNumRShift;
-  EDKII_CRYPTO_BIGNUM_CONST_TIME                     BigNumConstTime;
-  EDKII_CRYPTO_BIGNUM_SQR_MOD                        BigNumSqrMod;
-  EDKII_CRYPTO_BIGNUM_NEW_CONTEXT                    BigNumNewContext;
-  EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                   BigNumContextFree;
-  EDKII_CRYPTO_BIGNUM_SET_UINT                       BigNumSetUint;
-  EDKII_CRYPTO_BIGNUM_ADD_MOD                        BigNumAddMod;
+  EDKII_CRYPTO_BIGNUM_INIT                            BigNumInit;
+  EDKII_CRYPTO_BIGNUM_FROM_BIN                        BigNumFromBin;
+  EDKII_CRYPTO_BIGNUM_TO_BIN                          BigNumToBin;
+  EDKII_CRYPTO_BIGNUM_FREE                            BigNumFree;
+  EDKII_CRYPTO_BIGNUM_ADD                             BigNumAdd;
+  EDKII_CRYPTO_BIGNUM_SUB                             BigNumSub;
+  EDKII_CRYPTO_BIGNUM_MOD                             BigNumMod;
+  EDKII_CRYPTO_BIGNUM_EXP_MOD                         BigNumExpMod;
+  EDKII_CRYPTO_BIGNUM_INVERSE_MOD                     BigNumInverseMod;
+  EDKII_CRYPTO_BIGNUM_DIV                             BigNumDiv;
+  EDKII_CRYPTO_BIGNUM_MUL_MOD                         BigNumMulMod;
+  EDKII_CRYPTO_BIGNUM_CMP                             BigNumCmp;
+  EDKII_CRYPTO_BIGNUM_BITS                            BigNumBits;
+  EDKII_CRYPTO_BIGNUM_BYTES                           BigNumBytes;
+  EDKII_CRYPTO_BIGNUM_IS_WORD                         BigNumIsWord;
+  EDKII_CRYPTO_BIGNUM_IS_ODD                          BigNumIsOdd;
+  EDKII_CRYPTO_BIGNUM_COPY                            BigNumCopy;
+  EDKII_CRYPTO_BIGNUM_VALUE_ONE                       BigNumValueOne;
+  EDKII_CRYPTO_BIGNUM_R_SHIFT                         BigNumRShift;
+  EDKII_CRYPTO_BIGNUM_CONST_TIME                      BigNumConstTime;
+  EDKII_CRYPTO_BIGNUM_SQR_MOD                         BigNumSqrMod;
+  EDKII_CRYPTO_BIGNUM_NEW_CONTEXT                     BigNumNewContext;
+  EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                    BigNumContextFree;
+  EDKII_CRYPTO_BIGNUM_SET_UINT                        BigNumSetUint;
+  EDKII_CRYPTO_BIGNUM_ADD_MOD                         BigNumAddMod;
+  /// EC
+  EDKII_CRYPTO_EC_GROUP_INIT                          EcGroupInit;
+  EDKII_CRYPTO_EC_GROUP_GET_CURVE                     EcGroupGetCurve;
+  EDKII_CRYPTO_EC_GROUP_GET_ORDER                     EcGroupGetOrder;
+  EDKII_CRYPTO_EC_GROUP_FREE                          EcGroupFree;
+  EDKII_CRYPTO_EC_POINT_INIT                          EcPointInit;
+  EDKII_CRYPTO_EC_POINT_DE_INIT                       EcPointDeInit;
+  EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES        EcPointGetAffineCoordinates;
+  EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES        EcPointSetAffineCoordinates;
+  EDKII_CRYPTO_EC_POINT_ADD                           EcPointAdd;
+  EDKII_CRYPTO_EC_POINT_MUL                           EcPointMul;
+  EDKII_CRYPTO_EC_POINT_INVERT                        EcPointInvert;
+  EDKII_CRYPTO_EC_POINT_IS_ON_CURVE                   EcPointIsOnCurve;
+  EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY                EcPointIsAtInfinity;
+  EDKII_CRYPTO_EC_POINT_EQUAL                         EcPointEqual;
+  EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES    EcPointSetCompressedCoordinates;
+  EDKII_CRYPTO_EC_NEW_BY_NID                          EcNewByNid;
+  EDKII_CRYPTO_EC_FREE                                EcFree;
+  EDKII_CRYPTO_EC_GENERATE_KEY                        EcGenerateKey;
+  EDKII_CRYPTO_EC_GET_PUB_KEY                         EcGetPubKey;
+  EDKII_CRYPTO_EC_DH_COMPUTE_KEY                      EcDhComputeKey;
 };
 
 extern GUID  gEdkiiCryptoProtocolGuid;
-- 
2.31.1.windows.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc
       [not found] <cover.1663735439.git.yi1.li@intel.com>
  2022-09-21  4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
  2022-09-21  4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
@ 2022-09-21  4:54 ` yi1 li
  2 siblings, 0 replies; 17+ messages in thread
From: yi1 li @ 2022-09-21  4:54 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

Add unit test for CryptoEc.

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>
---
 .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |   2 +
 CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |   3 +
 .../BaseCryptLib/BaseCryptLibUnitTests.c      |   1 +
 .../UnitTest/Library/BaseCryptLib/EcTests.c   | 290 ++++++++++++++++++
 .../Library/BaseCryptLib/TestBaseCryptLib.h   |   2 +
 .../BaseCryptLib/TestBaseCryptLibHost.inf     |   1 +
 .../BaseCryptLib/TestBaseCryptLibShell.inf    |   1 +
 7 files changed, 300 insertions(+)
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c

diff --git a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
index cf8810e598..33df93c73c 100644
--- a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
@@ -47,6 +47,8 @@
   Pk/CryptRsaPss.c
   Pk/CryptRsaPssSign.c
   Bn/CryptBn.c
+  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
+  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
 
   SysCall/UnitTestHostCrtWrapper.c
 
diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
index 16478f4a57..b6e1a66198 100644
--- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
+++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
@@ -19,6 +19,9 @@
 
 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
 
+[PcdsFixedAtBuild]
+  gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled|TRUE
+
 [LibraryClasses]
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
index 792006a194..359921fd5f 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
@@ -26,6 +26,7 @@ SUITE_DESC  mSuiteDesc[] = {
   { "PRNG verify tests",           "CryptoPkg.BaseCryptLib", NULL, NULL, &mPrngTestNum,           mPrngTest           },
   { "OAEP encrypt verify tests",   "CryptoPkg.BaseCryptLib", NULL, NULL, &mOaepTestNum,           mOaepTest           },
   { "Bn verify tests",             "CryptoPkg.BaseCryptLib", NULL, NULL, &mBnTestNum,             mBnTest             },
+  { "EC verify tests",             "CryptoPkg.BaseCryptLib", NULL, NULL, &mEcTestNum,             mEcTest             },
 };
 
 EFI_STATUS
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
new file mode 100644
index 0000000000..54ce0b22df
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
@@ -0,0 +1,290 @@
+/** @file
+  Application for Diffie-Hellman Primitives Validation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#define EC_CURVE_NUM_SUPPORTED  3
+UINTN  EcCurveList[EC_CURVE_NUM_SUPPORTED]   = { CRYPTO_NID_SECP256R1, CRYPTO_NID_SECP384R1, CRYPTO_NID_SECP521R1 };
+UINTN  EcKeyHalfSize[EC_CURVE_NUM_SUPPORTED] = { 32, 48, 66 };
+
+struct Generator {
+  UINT8    X[66];
+  UINT8    Y[66];
+};
+
+// Generator points of all ec curve
+struct Generator  EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
+{
+  // CRYPTO_NID_SECP256R1
+  {
+    { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+      0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+      0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 },
+
+    { 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
+      0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+      0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 }
+  },
+  // CRYPTO_NID_SECP384R1
+  {
+    { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+      0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+      0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+      0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 },
+
+    { 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+      0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+      0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+      0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f }
+  },
+  // CRYPTO_NID_SECP521R1
+  {
+    { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+      0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+      0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+      0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+      0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+      0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 },
+
+    { 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
+      0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+      0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
+      0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+      0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+      0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 }
+  }
+};
+
+VOID  *Ec1;
+VOID  *Ec2;
+VOID  *Group;
+VOID  *Point1;
+VOID  *Point2;
+VOID  *PointRes;
+VOID  *BnX;
+VOID  *BnY;
+VOID  *BnP;
+VOID  *BnOrder;
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcPreReq (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  Ec1      = NULL;
+  Ec2      = NULL;
+  Group    = NULL;
+  Point1   = NULL;
+  Point2   = NULL;
+  PointRes = NULL;
+  BnX      = NULL;
+  BnY      = NULL;
+  BnP      = BigNumInit ();
+  BnOrder  = BigNumInit ();
+  if ((BnP == NULL) || (BnOrder == NULL)) {
+    return UNIT_TEST_ERROR_TEST_FAILED;
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyEcCleanUp (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  BigNumFree (BnX, TRUE);
+  BigNumFree (BnY, TRUE);
+  BigNumFree (BnP, TRUE);
+  BigNumFree (BnOrder, TRUE);
+  EcGroupFree (Group);
+  EcPointDeInit (Point1, TRUE);
+  EcPointDeInit (Point2, TRUE);
+  EcPointDeInit (PointRes, TRUE);
+  EcFree (Ec1);
+  EcFree (Ec2);
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcBasic (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  UINTN    CurveCount;
+  BOOLEAN  Status;
+
+  //
+  // Initialize BigNumbers
+  //
+  for (CurveCount = 0; CurveCount < EC_CURVE_NUM_SUPPORTED; CurveCount++) {
+    //
+    // Basic EC functions unit test
+    //
+    Group = EcGroupInit (EcCurveList[CurveCount]);
+    if (Group == NULL) {
+      return UNIT_TEST_ERROR_TEST_FAILED;
+    }
+
+    Point1   = EcPointInit (Group);
+    Point2   = EcPointInit (Group);
+    PointRes = EcPointInit (Group);
+    BnX      = BigNumFromBin (EcCurveGenerator[CurveCount].X, EcKeyHalfSize[CurveCount]);
+    BnY      = BigNumFromBin (EcCurveGenerator[CurveCount].Y, EcKeyHalfSize[CurveCount]);
+    if ((Point1 == NULL) || (Point2 == NULL) || (PointRes == NULL) || (BnX == NULL) || (BnY == NULL)) {
+      return UNIT_TEST_ERROR_TEST_FAILED;
+    }
+
+    Status = EcGroupGetCurve (Group, BnP, NULL, NULL, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcGroupGetOrder (Group, BnOrder);
+    UT_ASSERT_TRUE (Status);
+
+    // Point G should on curve
+    Status = EcPointSetAffineCoordinates (Group, Point1, BnX, BnY, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointSetAffineCoordinates (Group, Point2, BnX, BnY, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointEqual (Group, Point1, Point2, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointIsOnCurve (Group, Point1, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointIsAtInfinity (Group, Point1);
+    UT_ASSERT_FALSE (Status);
+
+    // Point 2G should on curve
+    Status = EcPointAdd (Group, PointRes, Point1, Point1, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointIsOnCurve (Group, PointRes, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    // Point Order * G should at infinity
+    Status = EcPointMul (Group, PointRes, Point1, BnOrder, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointIsAtInfinity (Group, PointRes);
+    UT_ASSERT_TRUE (Status);
+
+    // -(-G) == G
+    Status = EcPointInvert (Group, Point2, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointEqual (Group, Point2, Point1, NULL);
+    UT_ASSERT_FALSE (Status);
+
+    Status = EcPointInvert (Group, Point2, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointEqual (Group, Point2, Point1, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    // Compress point test
+    Status = EcPointSetCompressedCoordinates (Group, Point1, BnX, 0, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointSetCompressedCoordinates (Group, Point2, BnX, 1, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointEqual (Group, Point2, Point1, NULL);
+    UT_ASSERT_FALSE (Status);
+
+    Status = EcPointInvert (Group, Point2, NULL);
+    UT_ASSERT_TRUE (Status);
+
+    Status = EcPointEqual (Group, Point2, Point1, NULL);
+    UT_ASSERT_TRUE (Status);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcDh (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  UINT8    Public1[66 * 2];
+  UINTN    Public1Length;
+  UINT8    Public2[66 * 2];
+  UINTN    Public2Length;
+  UINT8    Key1[66];
+  UINTN    Key1Length;
+  UINT8    Key2[66];
+  UINTN    Key2Length;
+  UINTN    CurveCount;
+  BOOLEAN  Status;
+
+  for (CurveCount = 0; CurveCount < EC_CURVE_NUM_SUPPORTED; CurveCount++) {
+    //
+    // Initial key length
+    //
+    Public1Length = sizeof (Public1);
+    Public2Length = sizeof (Public2);
+    Key1Length    = sizeof (Key1);
+    Key2Length    = sizeof (Key2);
+    //
+    // ECDH functions unit test
+    //
+    Ec1 = EcNewByNid (EcCurveList[CurveCount]);
+    if (Ec1 == NULL) {
+      return UNIT_TEST_ERROR_TEST_FAILED;
+    }
+
+    Ec2 = EcNewByNid (EcCurveList[CurveCount]);
+    if (Ec2 == NULL) {
+      return UNIT_TEST_ERROR_TEST_FAILED;
+    }
+
+    Status = EcGenerateKey (Ec1, Public1, &Public1Length);
+    UT_ASSERT_TRUE (Status);
+    UT_ASSERT_EQUAL (Public1Length, EcKeyHalfSize[CurveCount] * 2);
+
+    Status = EcGenerateKey (Ec2, Public2, &Public2Length);
+    UT_ASSERT_TRUE (Status);
+    UT_ASSERT_EQUAL (Public2Length, EcKeyHalfSize[CurveCount] * 2);
+
+    Status = EcDhComputeKey (Ec1, Public2, Public2Length, NULL, Key1, &Key1Length);
+    UT_ASSERT_TRUE (Status);
+    UT_ASSERT_EQUAL (Key1Length, EcKeyHalfSize[CurveCount]);
+
+    Status = EcDhComputeKey (Ec2, Public1, Public1Length, NULL, Key2, &Key2Length);
+    UT_ASSERT_TRUE (Status);
+    UT_ASSERT_EQUAL (Key2Length, EcKeyHalfSize[CurveCount]);
+
+    UT_ASSERT_EQUAL (Key1Length, Key2Length);
+    UT_ASSERT_MEM_EQUAL (Key1, Key2, Key1Length);
+
+    Status = EcGetPubKey (Ec1, Public2, &Public2Length);
+    UT_ASSERT_TRUE (Status);
+    UT_ASSERT_EQUAL (Public2Length, EcKeyHalfSize[CurveCount] * 2);
+
+    UT_ASSERT_EQUAL (Public1Length, Public2Length);
+    UT_ASSERT_MEM_EQUAL (Public1, Public2, Public1Length);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+TEST_DESC  mEcTest[] = {
+  //
+  // -----Description-----------------Class------------------Function----Pre----Post----Context
+  //
+  { "TestVerifyEcBasic()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcBasic, TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
+  { "TestVerifyEcDh()",    "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcDh,    TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
+};
+
+UINTN  mEcTestNum = ARRAY_SIZE (mEcTest);
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
index b8f0fdfd89..6b198d43b6 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -89,6 +89,8 @@ extern TEST_DESC  mRsaPssTest[];
 extern UINTN      mBnTestNum;
 extern TEST_DESC  mBnTest[];
 
+extern UINTN      mEcTestNum;
+extern TEST_DESC  mEcTest[];
 /** Creates a framework you can use */
 EFI_STATUS
 EFIAPI
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
index 1301345a13..8f96cf6c4a 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -38,6 +38,7 @@
   RsaPssTests.c
   ParallelhashTests.c
   BnTests.c
+  EcTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
index 9a41dbc317..c9a86dab98 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -37,6 +37,7 @@
   OaepEncryptTests.c
   RsaPssTests.c
   BnTests.c
+  EcTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.31.1.windows.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-21  4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
@ 2022-09-21 16:21   ` Michael D Kinney
  2022-09-22  2:15     ` yi1 li
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-21 16:21 UTC (permalink / raw)
  To: devel@edk2.groups.io, Li, Yi1, Kinney, Michael D
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Comments embedded below.

Mike

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> Sent: Tuesday, September 20, 2022 9:55 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> 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>
> ---
>  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
>  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
>  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
>  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
>  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
>  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
>  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
>  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
>  8 files changed, 2186 insertions(+)
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> 
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> index b253923dd8..d74fc21c1e 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #include <Uefi/UefiBaseType.h>
> 
> +#define CRYPTO_NID_NULL  0x0000
> +
> +// Key Exchange
> +#define CRYPTO_NID_SECP256R1  0x0204
> +#define CRYPTO_NID_SECP384R1  0x0205
> +#define CRYPTO_NID_SECP521R1  0x0206
> +
>  ///
>  /// MD5 digest size in bytes
>  ///
> @@ -2850,4 +2857,421 @@ BigNumAddMod (
>    OUT VOID       *BnRes
>    );
> 
> +// =====================================================================================
> +//    Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> +  Initialize new opaque EcGroup object. This object represents an EC curve and
> +  and is used for calculation within this group. This object should be freed
> +  using EcGroupFree() function.
> +
> +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> +                          BaseCryptLib.h).
> +
> +  @retval EcGroup object  On success.
> +  @retval NULL            On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> +  IN UINTN  CryptoNid
> +  );
> +
> +/**
> +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> +  This function will set the provided Big Number objects  to the corresponding
> +  values. The caller needs to make sure all the "out" BigNumber parameters
> +  are properly initialized.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[out] BnPrime    Group prime number.
> +  @param[out] BnA        A coefficient.
> +  @param[out] BnB        B coefficient.
> +  @param[in]  BnCtx      BN context.
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *BnPrime,
> +  OUT VOID       *BnA,
> +  OUT VOID       *BnB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Get EC group order.
> +  This function will set the provided Big Number object to the corresponding
> +  value. The caller needs to make sure that the "out" BigNumber parameter
> +  is properly initialized.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[out] BnOrder   Group prime number.
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> +  IN VOID   *EcGroup,
> +  OUT VOID  *BnOrder
> +  );
> +
> +/**
> +  Free previously allocated EC group object using EcGroupInit().
> +
> +  @param[in]  EcGroup   EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> +  IN VOID  *EcGroup
> +  );
> +
> +/**
> +  Initialize new opaque EC Point object. This object represents an EC point
> +  within the given EC group (curve).
> +
> +  @param[in]  EC Group, properly initialized using EcGroupInit().
> +
> +  @retval EC Point object  On success.
> +  @retval NULL             On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> +  IN CONST VOID  *EcGroup
> +  );
> +
> +/**
> +  Free previously allocated EC Point object using EcPointInit().
> +
> +  @param[in]  EcPoint   EC Point to free.
> +  @param[in]  Clear     TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> +  IN VOID     *EcPoint,
> +  IN BOOLEAN  Clear
> +  );
> +
> +/**
> +  Get EC point affine (x,y) coordinates.
> +  This function will set the provided Big Number objects to the corresponding
> +  values. The caller needs to make sure all the "out" BigNumber parameters
> +  are properly initialized.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC point object.
> +  @param[out] BnX        X coordinate.
> +  @param[out] BnY        Y coordinate.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint,
> +  OUT VOID       *BnX,
> +  OUT VOID       *BnY,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Set EC point affine (x,y) coordinates.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC point object.
> +  @param[in]  BnX        X coordinate.
> +  @param[in]  BnY        Y coordinate.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN VOID        *EcPoint,
> +  IN CONST VOID  *BnX,
> +  IN CONST VOID  *BnY,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> +  @param[in]  EcGroup          EC group object.
> +  @param[out] EcPointResult    EC point to hold the result. The point should
> +                               be properly initialized.
> +  @param[in]  EcPointA         EC Point.
> +  @param[in]  EcPointB         EC Point.
> +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *EcPointResult,
> +  IN CONST VOID  *EcPointA,
> +  IN CONST VOID  *EcPointB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> +  @param[in]  EcGroup          EC group object.
> +  @param[out] EcPointResult    EC point to hold the result. The point should
> +                               be properly initialized.
> +  @param[in]  EcPoint          EC Point.
> +  @param[in]  BnPScalar        P Scalar.
> +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *EcPointResult,
> +  IN CONST VOID  *EcPoint,
> +  IN CONST VOID  *BnPScalar,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Calculate the inverse of the supplied EC point.
> +
> +  @param[in]     EcGroup   EC group object.
> +  @param[in,out] EcPoint   EC point to invert.
> +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> +  IN CONST VOID  *EcGroup,
> +  IN OUT VOID    *EcPoint,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Check if the supplied point is on EC curve.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPoint   EC point to check.
> +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On curve.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Check if the supplied point is at infinity.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPoint   EC point to check.
> +
> +  @retval TRUE          At infinity.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint
> +  );
> +
> +/**
> +  Check if EC points are equal.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPointA  EC point A.
> +  @param[in]  EcPointB  EC point B.
> +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          A == B.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPointA,
> +  IN CONST VOID  *EcPointB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Set EC point compressed coordinates. Points can be described in terms of
> +  their compressed coordinates. For a point (x, y), for any given value for x
> +  such that the point is on the curve there will only ever be two possible
> +  values for y. Therefore, a point can be set using this function where BnX is
> +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> +  possible values for y should be used.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC Point.
> +  @param[in]  BnX        X coordinate.
> +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN VOID        *EcPoint,
> +  IN CONST VOID  *BnX,
> +  IN UINT8       YBit,
> +  IN VOID        *BnCtx
> +  );
> +
> +// =====================================================================================
> +//    Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> +  with the NID.
> +
> +  @param[in]  Nid cipher NID
> +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> +              If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> +  IN UINTN  Nid
> +  );
> +
> +/**
> +  Release the specified EC context.
> +
> +  @param[in]  EcContext  Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> +  IN  VOID  *EcContext
> +  );
> +
> +/**
> +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> +  pseudo random number generator. The caller must make sure RandomSeed()
> +  function was properly called before.
> +  The Ec context should be correctly initialized by EcNewByNid.
> +  This function generates random secret, and computes the public key (X, Y), which is
> +  returned via parameter Public, PublicSize.
> +  X is the first half of Public with size being PublicSize / 2,
> +  Y is the second half of Public with size being PublicSize / 2.
> +  EC context is updated accordingly.
> +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> +  PublicSize is set to the required buffer size to obtain the public X, Y.
> +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  If EcContext is NULL, then return FALSE.
> +  If PublicSize is NULL, then return FALSE.
> +  If PublicSize is large enough but Public is NULL, then return FALSE.
> +  @param[in, out]  EcContext      Pointer to the EC context.
> +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> +                                  On output, the size of data returned in Public buffer in bytes.
> +  @retval TRUE   EC public X,Y generation succeeded.
> +  @retval FALSE  EC public X,Y generation failed.
> +  @retval FALSE  PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> +  IN OUT  VOID   *EcContext,
> +  OUT     UINT8  *PublicKey,
> +  IN OUT  UINTN  *PublicKeySize
> +  );
> +
> +/**
> +  Gets the public key component from the established EC context.
> +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> +  generate key pair from EcGenerateKey().
> +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  @param[in, out]  EcContext      Pointer to EC context being set.
> +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> +                                  On output, the size of data returned in Public buffer in bytes.
> +  @retval  TRUE   EC key component was retrieved successfully.
> +  @retval  FALSE  Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> +  IN OUT  VOID   *EcContext,
> +  OUT     UINT8  *PublicKey,
> +  IN OUT  UINTN  *PublicKeySize
> +  );
> +
> +/**
> +  Computes exchanged common key.
> +  Given peer's public key (X, Y), this function computes the exchanged common key,
> +  based on its own context including value of curve parameter and random secret.
> +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> +  If EcContext is NULL, then return FALSE.
> +  If PeerPublic is NULL, then return FALSE.
> +  If PeerPublicSize is 0, then return FALSE.
> +  If Key is NULL, then return FALSE.
> +  If KeySize is not large enough, then return FALSE.
> +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  @param[in, out]  EcContext          Pointer to the EC context.
> +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> +  @param[out]      Key                Pointer to the buffer to receive generated key.
> +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> +                                      On output, the size of data returned in Key buffer in bytes.
> +  @retval TRUE   EC exchanged key generation succeeded.
> +  @retval FALSE  EC exchanged key generation failed.
> +  @retval FALSE  KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> +  IN OUT  VOID         *EcContext,
> +  IN      CONST UINT8  *PeerPublic,
> +  IN      UINTN        PeerPublicSize,
> +  IN      CONST INT32  *CompressFlag,
> +  OUT     UINT8        *Key,
> +  IN OUT  UINTN        *KeySize
> +  );
> +
>  #endif // __BASE_CRYPT_LIB_H__
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 9e4be2fb0d..ade6ee3fdd 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -52,6 +52,8 @@
>    Pk/CryptTs.c
>    Pk/CryptRsaPss.c
>    Pk/CryptRsaPssSign.c
> +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

The use of the PCD to select the file should not be needed here.  The 
Ec Family and individual service enable/disable fields in the 
PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
disable the Ec services.

The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed 
completely as part of this patch series.

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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-21 16:21   ` [edk2-devel] " Michael D Kinney
@ 2022-09-22  2:15     ` yi1 li
  2022-09-22  3:56       ` Michael D Kinney
  0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-22  2:15 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Mike,
Thanks for review.

Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:

d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as an error
        1 file(s) copied.
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name' undefined; assuming extern returning int
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in levels of indirection from 'int'
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined; assuming extern returning int

I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L202-L238
 if PcdOpensslEcEnabled not true, all ec files will not be compiled.
This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.

So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are welcome.

Thanks,
Yi

-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com> 
Sent: Thursday, September 22, 2022 12:22 AM
To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Comments embedded below.

Mike

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> Sent: Tuesday, September 20, 2022 9:55 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> 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>
> ---
>  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
>  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
>  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
>  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
>  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
>  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
>  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
>  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
>  8 files changed, 2186 insertions(+)
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> 
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> index b253923dd8..d74fc21c1e 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #include <Uefi/UefiBaseType.h>
> 
> +#define CRYPTO_NID_NULL  0x0000
> +
> +// Key Exchange
> +#define CRYPTO_NID_SECP256R1  0x0204
> +#define CRYPTO_NID_SECP384R1  0x0205
> +#define CRYPTO_NID_SECP521R1  0x0206
> +
>  ///
>  /// MD5 digest size in bytes
>  ///
> @@ -2850,4 +2857,421 @@ BigNumAddMod (
>    OUT VOID       *BnRes
>    );
> 
> +// =====================================================================================
> +//    Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> +  Initialize new opaque EcGroup object. This object represents an EC curve and
> +  and is used for calculation within this group. This object should be freed
> +  using EcGroupFree() function.
> +
> +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> +                          BaseCryptLib.h).
> +
> +  @retval EcGroup object  On success.
> +  @retval NULL            On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> +  IN UINTN  CryptoNid
> +  );
> +
> +/**
> +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> +  This function will set the provided Big Number objects  to the corresponding
> +  values. The caller needs to make sure all the "out" BigNumber parameters
> +  are properly initialized.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[out] BnPrime    Group prime number.
> +  @param[out] BnA        A coefficient.
> +  @param[out] BnB        B coefficient.
> +  @param[in]  BnCtx      BN context.
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *BnPrime,
> +  OUT VOID       *BnA,
> +  OUT VOID       *BnB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Get EC group order.
> +  This function will set the provided Big Number object to the corresponding
> +  value. The caller needs to make sure that the "out" BigNumber parameter
> +  is properly initialized.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[out] BnOrder   Group prime number.
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> +  IN VOID   *EcGroup,
> +  OUT VOID  *BnOrder
> +  );
> +
> +/**
> +  Free previously allocated EC group object using EcGroupInit().
> +
> +  @param[in]  EcGroup   EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> +  IN VOID  *EcGroup
> +  );
> +
> +/**
> +  Initialize new opaque EC Point object. This object represents an EC point
> +  within the given EC group (curve).
> +
> +  @param[in]  EC Group, properly initialized using EcGroupInit().
> +
> +  @retval EC Point object  On success.
> +  @retval NULL             On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> +  IN CONST VOID  *EcGroup
> +  );
> +
> +/**
> +  Free previously allocated EC Point object using EcPointInit().
> +
> +  @param[in]  EcPoint   EC Point to free.
> +  @param[in]  Clear     TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> +  IN VOID     *EcPoint,
> +  IN BOOLEAN  Clear
> +  );
> +
> +/**
> +  Get EC point affine (x,y) coordinates.
> +  This function will set the provided Big Number objects to the corresponding
> +  values. The caller needs to make sure all the "out" BigNumber parameters
> +  are properly initialized.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC point object.
> +  @param[out] BnX        X coordinate.
> +  @param[out] BnY        Y coordinate.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint,
> +  OUT VOID       *BnX,
> +  OUT VOID       *BnY,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Set EC point affine (x,y) coordinates.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC point object.
> +  @param[in]  BnX        X coordinate.
> +  @param[in]  BnY        Y coordinate.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN VOID        *EcPoint,
> +  IN CONST VOID  *BnX,
> +  IN CONST VOID  *BnY,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> +  @param[in]  EcGroup          EC group object.
> +  @param[out] EcPointResult    EC point to hold the result. The point should
> +                               be properly initialized.
> +  @param[in]  EcPointA         EC Point.
> +  @param[in]  EcPointB         EC Point.
> +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *EcPointResult,
> +  IN CONST VOID  *EcPointA,
> +  IN CONST VOID  *EcPointB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> +  @param[in]  EcGroup          EC group object.
> +  @param[out] EcPointResult    EC point to hold the result. The point should
> +                               be properly initialized.
> +  @param[in]  EcPoint          EC Point.
> +  @param[in]  BnPScalar        P Scalar.
> +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> +  IN CONST VOID  *EcGroup,
> +  OUT VOID       *EcPointResult,
> +  IN CONST VOID  *EcPoint,
> +  IN CONST VOID  *BnPScalar,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Calculate the inverse of the supplied EC point.
> +
> +  @param[in]     EcGroup   EC group object.
> +  @param[in,out] EcPoint   EC point to invert.
> +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> +  IN CONST VOID  *EcGroup,
> +  IN OUT VOID    *EcPoint,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Check if the supplied point is on EC curve.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPoint   EC point to check.
> +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On curve.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Check if the supplied point is at infinity.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPoint   EC point to check.
> +
> +  @retval TRUE          At infinity.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPoint
> +  );
> +
> +/**
> +  Check if EC points are equal.
> +
> +  @param[in]  EcGroup   EC group object.
> +  @param[in]  EcPointA  EC point A.
> +  @param[in]  EcPointB  EC point B.
> +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          A == B.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> +  IN CONST VOID  *EcGroup,
> +  IN CONST VOID  *EcPointA,
> +  IN CONST VOID  *EcPointB,
> +  IN VOID        *BnCtx
> +  );
> +
> +/**
> +  Set EC point compressed coordinates. Points can be described in terms of
> +  their compressed coordinates. For a point (x, y), for any given value for x
> +  such that the point is on the curve there will only ever be two possible
> +  values for y. Therefore, a point can be set using this function where BnX is
> +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> +  possible values for y should be used.
> +
> +  @param[in]  EcGroup    EC group object.
> +  @param[in]  EcPoint    EC Point.
> +  @param[in]  BnX        X coordinate.
> +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> +
> +  @retval TRUE          On success.
> +  @retval FALSE         Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> +  IN CONST VOID  *EcGroup,
> +  IN VOID        *EcPoint,
> +  IN CONST VOID  *BnX,
> +  IN UINT8       YBit,
> +  IN VOID        *BnCtx
> +  );
> +
> +// =====================================================================================
> +//    Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> +  with the NID.
> +
> +  @param[in]  Nid cipher NID
> +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> +              If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> +  IN UINTN  Nid
> +  );
> +
> +/**
> +  Release the specified EC context.
> +
> +  @param[in]  EcContext  Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> +  IN  VOID  *EcContext
> +  );
> +
> +/**
> +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> +  pseudo random number generator. The caller must make sure RandomSeed()
> +  function was properly called before.
> +  The Ec context should be correctly initialized by EcNewByNid.
> +  This function generates random secret, and computes the public key (X, Y), which is
> +  returned via parameter Public, PublicSize.
> +  X is the first half of Public with size being PublicSize / 2,
> +  Y is the second half of Public with size being PublicSize / 2.
> +  EC context is updated accordingly.
> +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> +  PublicSize is set to the required buffer size to obtain the public X, Y.
> +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  If EcContext is NULL, then return FALSE.
> +  If PublicSize is NULL, then return FALSE.
> +  If PublicSize is large enough but Public is NULL, then return FALSE.
> +  @param[in, out]  EcContext      Pointer to the EC context.
> +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> +                                  On output, the size of data returned in Public buffer in bytes.
> +  @retval TRUE   EC public X,Y generation succeeded.
> +  @retval FALSE  EC public X,Y generation failed.
> +  @retval FALSE  PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> +  IN OUT  VOID   *EcContext,
> +  OUT     UINT8  *PublicKey,
> +  IN OUT  UINTN  *PublicKeySize
> +  );
> +
> +/**
> +  Gets the public key component from the established EC context.
> +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> +  generate key pair from EcGenerateKey().
> +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  @param[in, out]  EcContext      Pointer to EC context being set.
> +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> +                                  On output, the size of data returned in Public buffer in bytes.
> +  @retval  TRUE   EC key component was retrieved successfully.
> +  @retval  FALSE  Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> +  IN OUT  VOID   *EcContext,
> +  OUT     UINT8  *PublicKey,
> +  IN OUT  UINTN  *PublicKeySize
> +  );
> +
> +/**
> +  Computes exchanged common key.
> +  Given peer's public key (X, Y), this function computes the exchanged common key,
> +  based on its own context including value of curve parameter and random secret.
> +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> +  If EcContext is NULL, then return FALSE.
> +  If PeerPublic is NULL, then return FALSE.
> +  If PeerPublicSize is 0, then return FALSE.
> +  If Key is NULL, then return FALSE.
> +  If KeySize is not large enough, then return FALSE.
> +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> +  @param[in, out]  EcContext          Pointer to the EC context.
> +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> +  @param[out]      Key                Pointer to the buffer to receive generated key.
> +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> +                                      On output, the size of data returned in Key buffer in bytes.
> +  @retval TRUE   EC exchanged key generation succeeded.
> +  @retval FALSE  EC exchanged key generation failed.
> +  @retval FALSE  KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> +  IN OUT  VOID         *EcContext,
> +  IN      CONST UINT8  *PeerPublic,
> +  IN      UINTN        PeerPublicSize,
> +  IN      CONST INT32  *CompressFlag,
> +  OUT     UINT8        *Key,
> +  IN OUT  UINTN        *KeySize
> +  );
> +
>  #endif // __BASE_CRYPT_LIB_H__
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 9e4be2fb0d..ade6ee3fdd 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -52,6 +52,8 @@
>    Pk/CryptTs.c
>    Pk/CryptRsaPss.c
>    Pk/CryptRsaPssSign.c
> +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

The use of the PCD to select the file should not be needed here.  The 
Ec Family and individual service enable/disable fields in the 
PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
disable the Ec services.

The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed 
completely as part of this patch series.

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


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-22  2:15     ` yi1 li
@ 2022-09-22  3:56       ` Michael D Kinney
  2022-09-22 12:54         ` yi1 li
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-22  3:56 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io, Kishore, Shelly
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

That change to OpensslLib.inf should not have been done either.

Looks like this EC feature needs more evaluation to fit into the
structured PCD control of the lib sizes.

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 21, 2022 7:16 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> Thanks for review.
> 
> Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> 
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as
> an error
>         1 file(s) copied.
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> undefined; assuming extern returning int
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> levels of indirection from 'int'
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> assuming extern returning int
> 
> I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> 02-L238
>  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> 
> So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> welcome.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 12:22 AM
> To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Comments embedded below.
> 
> Mike
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > Sent: Tuesday, September 20, 2022 9:55 PM
> > To: devel@edk2.groups.io
> > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > 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>
> > ---
> >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> >  8 files changed, 2186 insertions(+)
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index b253923dd8..d74fc21c1e 100644
> > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #include <Uefi/UefiBaseType.h>
> >
> > +#define CRYPTO_NID_NULL  0x0000
> > +
> > +// Key Exchange
> > +#define CRYPTO_NID_SECP256R1  0x0204
> > +#define CRYPTO_NID_SECP384R1  0x0205
> > +#define CRYPTO_NID_SECP521R1  0x0206
> > +
> >  ///
> >  /// MD5 digest size in bytes
> >  ///
> > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> >    OUT VOID       *BnRes
> >    );
> >
> > +// =====================================================================================
> > +//    Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  );
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient.
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  );
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  );
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  );
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  );
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  );
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +// =====================================================================================
> > +//    Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  );
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  );
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  );
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  );
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  );
> > +
> >  #endif // __BASE_CRYPT_LIB_H__
> > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > index 9e4be2fb0d..ade6ee3fdd 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > @@ -52,6 +52,8 @@
> >    Pk/CryptTs.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSign.c
> > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> 
> The use of the PCD to select the file should not be needed here.  The
> Ec Family and individual service enable/disable fields in the
> PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> disable the Ec services.
> 
> The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> completely as part of this patch series.
> 
> >    Pem/CryptPem.c
> >    Bn/CryptBn.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > index 65ad23fb81..383df2b23c 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > @@ -58,6 +58,7 @@
> >    Pk/CryptTsNull.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSignNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPemNull.c
> >    Rand/CryptRandNull.c
> >    Bn/CryptBnNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > new file mode 100644
> > index 0000000000..396c819834
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > @@ -0,0 +1,765 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "InternalCryptLib.h"
> > +#include <openssl/objects.h>
> > +#include <openssl/bn.h>
> > +#include <openssl/ec.h>
> > +
> > +// =====================================================================================
> > +//    Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Return the Nid of certain ECC curve.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval !=-1    On success.
> > +  @retval -1      ECC curve not supported.
> > +**/
> > +STATIC
> > +INT32
> > +CryptoNidToOpensslNid (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  INT32  Nid;
> > +
> > +  switch (CryptoNid) {
> > +    case CRYPTO_NID_SECP256R1:
> > +      Nid = NID_X9_62_prime256v1;
> > +      break;
> > +    case CRYPTO_NID_SECP384R1:
> > +      Nid = NID_secp384r1;
> > +      break;
> > +    case CRYPTO_NID_SECP521R1:
> > +      Nid = NID_secp521r1;
> > +      break;
> > +    default:
> > +      return -1;
> > +  }
> > +
> > +  return Nid;
> > +}
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  INT32  Nid;
> > +
> > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > +
> > +  if (Nid < 0) {
> > +    return NULL;
> > +  }
> > +
> > +  return EC_GROUP_new_by_curve_name (Nid);
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  EC_GROUP_free (EcGroup);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  return EC_POINT_new (EcGroup);
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  if (Clear) {
> > +    EC_POINT_clear_free (EcPoint);
> > +  } else {
> > +    EC_POINT_free (EcPoint);
> > +  }
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > +}
> > +
> > +// =====================================================================================
> > +//    Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > +                    BaseCryptLib.h).
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  INT32  OpenSslNid;
> > +
> > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > +  if (OpenSslNid < 0) {
> > +    return NULL;
> > +  }
> > +
> > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  EC_KEY_free ((EC_KEY *)EcContext);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  CONST EC_GROUP  *Group;
> > +  CONST EC_POINT  *EcPoint;
> > +  BOOLEAN         RetVal;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  UINTN           HalfSize;
> > +  INTN            XSize;
> > +  INTN            YSize;
> > +
> > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +
> > +  // Assume RAND_seed was called
> > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (*PublicKeySize < HalfSize * 2) {
> > +    *PublicKeySize = HalfSize * 2;
> > +    return FALSE;
> > +  }
> > +
> > +  *PublicKeySize = HalfSize * 2;
> > +
> > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > +  if (EcPoint == NULL) {
> > +    return FALSE;
> > +  }
> > +
> > +  RetVal = FALSE;
> > +  BnX    = BN_new ();
> > +  BnY    = BN_new ();
> > +  if ((BnX == NULL) || (BnY == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  XSize = BN_num_bytes (BnX);
> > +  YSize = BN_num_bytes (BnY);
> > +  if ((XSize <= 0) || (YSize <= 0)) {
> > +    goto fail;
> > +  }
> > +
> > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > +  ZeroMem (PublicKey, *PublicKeySize);
> > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  return RetVal;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  CONST EC_GROUP  *Group;
> > +  CONST EC_POINT  *EcPoint;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  UINTN           HalfSize;
> > +  INTN            XSize;
> > +  INTN            YSize;
> > +  BOOLEAN         RetVal;
> > +
> > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +  if (*PublicKeySize < HalfSize * 2) {
> > +    *PublicKeySize = HalfSize * 2;
> > +    return FALSE;
> > +  }
> > +
> > +  *PublicKeySize = HalfSize * 2;
> > +
> > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > +  if (EcPoint == NULL) {
> > +    return FALSE;
> > +  }
> > +
> > +  RetVal = FALSE;
> > +  BnX    = BN_new ();
> > +  BnY    = BN_new ();
> > +  if ((BnX == NULL) || (BnY == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  XSize = BN_num_bytes (BnX);
> > +  YSize = BN_num_bytes (BnY);
> > +  if ((XSize <= 0) || (YSize <= 0)) {
> > +    goto fail;
> > +  }
> > +
> > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > +  if (PublicKey != NULL) {
> > +    ZeroMem (PublicKey, *PublicKeySize);
> > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +  }
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  return RetVal;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  EC_KEY          *PeerEcKey;
> > +  CONST EC_GROUP  *Group;
> > +  BOOLEAN         RetVal;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  EC_POINT        *Point;
> > +  INT32           OpenSslNid;
> > +  UINTN           HalfSize;
> > +
> > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((Key == NULL) && (*KeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (PeerPublicSize > INT_MAX) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (*KeySize < HalfSize) {
> > +    *KeySize = HalfSize;
> > +    return FALSE;
> > +  }
> > +
> > +  *KeySize = HalfSize;
> > +
> > +  RetVal    = FALSE;
> > +  Point     = NULL;
> > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > +  BnY       = NULL;
> > +  Point     = EC_POINT_new (Group);
> > +  PeerEcKey = NULL;
> > +  if ((BnX == NULL) || (Point == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (CompressFlag == NULL) {
> > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > +    if (BnY == NULL) {
> > +      goto fail;
> > +    }
> > +
> > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > +      goto fail;
> > +    }
> > +  } else {
> > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > +      goto fail;
> > +    }
> > +  }
> > +
> > +  // Validate NIST ECDH public key
> > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > +  if (PeerEcKey == NULL) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > +    goto fail;
> > +  }
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  EC_POINT_free (Point);
> > +  EC_KEY_free (PeerEcKey);
> > +  return RetVal;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index ce6a789dfd..4bc3063485 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > @@ -59,6 +59,7 @@
> >    Pk/CryptTsNull.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSignNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPem.c
> >    Bn/CryptBnNull.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > index 354f3d80aa..e1a57ef09f 100644
> > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > @@ -49,6 +49,7 @@
> >    Pk/CryptX509Null.c
> >    Pk/CryptAuthenticodeNull.c
> >    Pk/CryptTsNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPemNull.c
> >    Rand/CryptRandNull.c
> >    Pk/CryptRsaPssNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > --
> > 2.31.1.windows.1
> >
> >
> >
> > 
> >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-22  3:56       ` Michael D Kinney
@ 2022-09-22 12:54         ` yi1 li
  2022-09-22 22:46           ` Michael D Kinney
  0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-22 12:54 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io, Kishore, Shelly
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Mike,
I have did some POC that seems existed structured PCD is hard to control binary size, 
Here is the previous discussion for reference.
https://bugzilla.tianocore.org/show_bug.cgi?id=3679
https://edk2.groups.io/g/devel/topic/86257810#81814
https://bugzilla.tianocore.org/show_bug.cgi?id=1446

Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.

Thanks,
Yi

-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com> 
Sent: Thursday, September 22, 2022 11:56 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

That change to OpensslLib.inf should not have been done either.

Looks like this EC feature needs more evaluation to fit into the
structured PCD control of the lib sizes.

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 21, 2022 7:16 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> Thanks for review.
> 
> Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> 
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as
> an error
>         1 file(s) copied.
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> undefined; assuming extern returning int
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> levels of indirection from 'int'
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> assuming extern returning int
> 
> I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> 02-L238
>  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> 
> So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> welcome.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 12:22 AM
> To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Comments embedded below.
> 
> Mike
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > Sent: Tuesday, September 20, 2022 9:55 PM
> > To: devel@edk2.groups.io
> > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > 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>
> > ---
> >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> >  8 files changed, 2186 insertions(+)
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index b253923dd8..d74fc21c1e 100644
> > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #include <Uefi/UefiBaseType.h>
> >
> > +#define CRYPTO_NID_NULL  0x0000
> > +
> > +// Key Exchange
> > +#define CRYPTO_NID_SECP256R1  0x0204
> > +#define CRYPTO_NID_SECP384R1  0x0205
> > +#define CRYPTO_NID_SECP521R1  0x0206
> > +
> >  ///
> >  /// MD5 digest size in bytes
> >  ///
> > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> >    OUT VOID       *BnRes
> >    );
> >
> > +// =====================================================================================
> > +//    Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  );
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient.
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  );
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  );
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  );
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  );
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  );
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  );
> > +
> > +// =====================================================================================
> > +//    Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  );
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  );
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  );
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  );
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  );
> > +
> >  #endif // __BASE_CRYPT_LIB_H__
> > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > index 9e4be2fb0d..ade6ee3fdd 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > @@ -52,6 +52,8 @@
> >    Pk/CryptTs.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSign.c
> > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> 
> The use of the PCD to select the file should not be needed here.  The
> Ec Family and individual service enable/disable fields in the
> PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> disable the Ec services.
> 
> The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> completely as part of this patch series.
> 
> >    Pem/CryptPem.c
> >    Bn/CryptBn.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > index 65ad23fb81..383df2b23c 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > @@ -58,6 +58,7 @@
> >    Pk/CryptTsNull.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSignNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPemNull.c
> >    Rand/CryptRandNull.c
> >    Bn/CryptBnNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > new file mode 100644
> > index 0000000000..396c819834
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > @@ -0,0 +1,765 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "InternalCryptLib.h"
> > +#include <openssl/objects.h>
> > +#include <openssl/bn.h>
> > +#include <openssl/ec.h>
> > +
> > +// =====================================================================================
> > +//    Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Return the Nid of certain ECC curve.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval !=-1    On success.
> > +  @retval -1      ECC curve not supported.
> > +**/
> > +STATIC
> > +INT32
> > +CryptoNidToOpensslNid (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  INT32  Nid;
> > +
> > +  switch (CryptoNid) {
> > +    case CRYPTO_NID_SECP256R1:
> > +      Nid = NID_X9_62_prime256v1;
> > +      break;
> > +    case CRYPTO_NID_SECP384R1:
> > +      Nid = NID_secp384r1;
> > +      break;
> > +    case CRYPTO_NID_SECP521R1:
> > +      Nid = NID_secp521r1;
> > +      break;
> > +    default:
> > +      return -1;
> > +  }
> > +
> > +  return Nid;
> > +}
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  INT32  Nid;
> > +
> > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > +
> > +  if (Nid < 0) {
> > +    return NULL;
> > +  }
> > +
> > +  return EC_GROUP_new_by_curve_name (Nid);
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  EC_GROUP_free (EcGroup);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  return EC_POINT_new (EcGroup);
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  if (Clear) {
> > +    EC_POINT_clear_free (EcPoint);
> > +  } else {
> > +    EC_POINT_free (EcPoint);
> > +  }
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > +}
> > +
> > +// =====================================================================================
> > +//    Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > +                    BaseCryptLib.h).
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  INT32  OpenSslNid;
> > +
> > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > +  if (OpenSslNid < 0) {
> > +    return NULL;
> > +  }
> > +
> > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  EC_KEY_free ((EC_KEY *)EcContext);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  CONST EC_GROUP  *Group;
> > +  CONST EC_POINT  *EcPoint;
> > +  BOOLEAN         RetVal;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  UINTN           HalfSize;
> > +  INTN            XSize;
> > +  INTN            YSize;
> > +
> > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +
> > +  // Assume RAND_seed was called
> > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (*PublicKeySize < HalfSize * 2) {
> > +    *PublicKeySize = HalfSize * 2;
> > +    return FALSE;
> > +  }
> > +
> > +  *PublicKeySize = HalfSize * 2;
> > +
> > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > +  if (EcPoint == NULL) {
> > +    return FALSE;
> > +  }
> > +
> > +  RetVal = FALSE;
> > +  BnX    = BN_new ();
> > +  BnY    = BN_new ();
> > +  if ((BnX == NULL) || (BnY == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  XSize = BN_num_bytes (BnX);
> > +  YSize = BN_num_bytes (BnY);
> > +  if ((XSize <= 0) || (YSize <= 0)) {
> > +    goto fail;
> > +  }
> > +
> > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > +  ZeroMem (PublicKey, *PublicKeySize);
> > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  return RetVal;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  CONST EC_GROUP  *Group;
> > +  CONST EC_POINT  *EcPoint;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  UINTN           HalfSize;
> > +  INTN            XSize;
> > +  INTN            YSize;
> > +  BOOLEAN         RetVal;
> > +
> > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +  if (*PublicKeySize < HalfSize * 2) {
> > +    *PublicKeySize = HalfSize * 2;
> > +    return FALSE;
> > +  }
> > +
> > +  *PublicKeySize = HalfSize * 2;
> > +
> > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > +  if (EcPoint == NULL) {
> > +    return FALSE;
> > +  }
> > +
> > +  RetVal = FALSE;
> > +  BnX    = BN_new ();
> > +  BnY    = BN_new ();
> > +  if ((BnX == NULL) || (BnY == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  XSize = BN_num_bytes (BnX);
> > +  YSize = BN_num_bytes (BnY);
> > +  if ((XSize <= 0) || (YSize <= 0)) {
> > +    goto fail;
> > +  }
> > +
> > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > +  if (PublicKey != NULL) {
> > +    ZeroMem (PublicKey, *PublicKeySize);
> > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +  }
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  return RetVal;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  EC_KEY          *EcKey;
> > +  EC_KEY          *PeerEcKey;
> > +  CONST EC_GROUP  *Group;
> > +  BOOLEAN         RetVal;
> > +  BIGNUM          *BnX;
> > +  BIGNUM          *BnY;
> > +  EC_POINT        *Point;
> > +  INT32           OpenSslNid;
> > +  UINTN           HalfSize;
> > +
> > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((Key == NULL) && (*KeySize != 0)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (PeerPublicSize > INT_MAX) {
> > +    return FALSE;
> > +  }
> > +
> > +  EcKey    = (EC_KEY *)EcContext;
> > +  Group    = EC_KEY_get0_group (EcKey);
> > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > +    return FALSE;
> > +  }
> > +
> > +  if (*KeySize < HalfSize) {
> > +    *KeySize = HalfSize;
> > +    return FALSE;
> > +  }
> > +
> > +  *KeySize = HalfSize;
> > +
> > +  RetVal    = FALSE;
> > +  Point     = NULL;
> > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > +  BnY       = NULL;
> > +  Point     = EC_POINT_new (Group);
> > +  PeerEcKey = NULL;
> > +  if ((BnX == NULL) || (Point == NULL)) {
> > +    goto fail;
> > +  }
> > +
> > +  if (CompressFlag == NULL) {
> > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > +    if (BnY == NULL) {
> > +      goto fail;
> > +    }
> > +
> > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > +      goto fail;
> > +    }
> > +  } else {
> > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > +      goto fail;
> > +    }
> > +  }
> > +
> > +  // Validate NIST ECDH public key
> > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > +  if (PeerEcKey == NULL) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > +    goto fail;
> > +  }
> > +
> > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > +    goto fail;
> > +  }
> > +
> > +  RetVal = TRUE;
> > +
> > +fail:
> > +  BN_free (BnX);
> > +  BN_free (BnY);
> > +  EC_POINT_free (Point);
> > +  EC_KEY_free (PeerEcKey);
> > +  return RetVal;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index ce6a789dfd..4bc3063485 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > @@ -59,6 +59,7 @@
> >    Pk/CryptTsNull.c
> >    Pk/CryptRsaPss.c
> >    Pk/CryptRsaPssSignNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPem.c
> >    Bn/CryptBnNull.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > index 354f3d80aa..e1a57ef09f 100644
> > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > @@ -49,6 +49,7 @@
> >    Pk/CryptX509Null.c
> >    Pk/CryptAuthenticodeNull.c
> >    Pk/CryptTsNull.c
> > +  Pk/CryptEcNull.c
> >    Pem/CryptPemNull.c
> >    Rand/CryptRandNull.c
> >    Pk/CryptRsaPssNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > +  and is used for calculation within this group. This object should be freed
> > +  using EcGroupFree() function.
> > +
> > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > +                          BaseCryptLib.h).
> > +
> > +  @retval EcGroup object  On success.
> > +  @retval NULL            On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > +  IN UINTN  CryptoNid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > +  This function will set the provided Big Number objects  to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[out] BnPrime    Group prime number.
> > +  @param[out] BnA        A coefficient.
> > +  @param[out] BnB        B coefficient..
> > +  @param[in]  BnCtx      BN context.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *BnPrime,
> > +  OUT VOID       *BnA,
> > +  OUT VOID       *BnB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Get EC group order.
> > +  This function will set the provided Big Number object to the corresponding
> > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > +  is properly initialized.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[out] BnOrder   Group prime number.
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > +  IN VOID   *EcGroup,
> > +  OUT VOID  *BnOrder
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC group object using EcGroupInit().
> > +
> > +  @param[in]  EcGroup   EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > +  IN VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Initialize new opaque EC Point object. This object represents an EC point
> > +  within the given EC group (curve).
> > +
> > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > +
> > +  @retval EC Point object  On success.
> > +  @retval NULL             On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > +  IN CONST VOID  *EcGroup
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Free previously allocated EC Point object using EcPointInit().
> > +
> > +  @param[in]  EcPoint   EC Point to free.
> > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > +  IN VOID     *EcPoint,
> > +  IN BOOLEAN  Clear
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Get EC point affine (x,y) coordinates.
> > +  This function will set the provided Big Number objects to the corresponding
> > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > +  are properly initialized.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[out] BnX        X coordinate.
> > +  @param[out] BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  OUT VOID       *BnX,
> > +  OUT VOID       *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point affine (x,y) coordinates.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC point object.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  BnY        Y coordinate.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN CONST VOID  *BnY,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPointA         EC Point.
> > +  @param[in]  EcPointB         EC Point.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > +  @param[in]  EcGroup          EC group object.
> > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > +                               be properly initialized.
> > +  @param[in]  EcPoint          EC Point.
> > +  @param[in]  BnPScalar        P Scalar.
> > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > +  IN CONST VOID  *EcGroup,
> > +  OUT VOID       *EcPointResult,
> > +  IN CONST VOID  *EcPoint,
> > +  IN CONST VOID  *BnPScalar,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Calculate the inverse of the supplied EC point.
> > +
> > +  @param[in]     EcGroup   EC group object.
> > +  @param[in,out] EcPoint   EC point to invert.
> > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > +  IN CONST VOID  *EcGroup,
> > +  IN OUT VOID    *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is on EC curve.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On curve.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if the supplied point is at infinity.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPoint   EC point to check.
> > +
> > +  @retval TRUE          At infinity.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPoint
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Check if EC points are equal.
> > +
> > +  @param[in]  EcGroup   EC group object.
> > +  @param[in]  EcPointA  EC point A.
> > +  @param[in]  EcPointB  EC point B.
> > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          A == B.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > +  IN CONST VOID  *EcGroup,
> > +  IN CONST VOID  *EcPointA,
> > +  IN CONST VOID  *EcPointB,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Set EC point compressed coordinates. Points can be described in terms of
> > +  their compressed coordinates. For a point (x, y), for any given value for x
> > +  such that the point is on the curve there will only ever be two possible
> > +  values for y. Therefore, a point can be set using this function where BnX is
> > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > +  possible values for y should be used.
> > +
> > +  @param[in]  EcGroup    EC group object.
> > +  @param[in]  EcPoint    EC Point.
> > +  @param[in]  BnX        X coordinate.
> > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > +
> > +  @retval TRUE          On success.
> > +  @retval FALSE         Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > +  IN CONST VOID  *EcGroup,
> > +  IN VOID        *EcPoint,
> > +  IN CONST VOID  *BnX,
> > +  IN UINT8       YBit,
> > +  IN VOID        *BnCtx
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > +  with the NID.
> > +
> > +  @param[in]  Nid cipher NID
> > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > +              If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > +  IN UINTN  Nid
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Release the specified EC context.
> > +
> > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > +  IN  VOID  *EcContext
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +}
> > +
> > +/**
> > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > +  pseudo random number generator. The caller must make sure RandomSeed()
> > +  function was properly called before.
> > +  The Ec context should be correctly initialized by EcNewByNid.
> > +  This function generates random secret, and computes the public key (X, Y), which is
> > +  returned via parameter Public, PublicSize.
> > +  X is the first half of Public with size being PublicSize / 2,
> > +  Y is the second half of Public with size being PublicSize / 2.
> > +  EC context is updated accordingly.
> > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PublicSize is NULL, then return FALSE.
> > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > +  @param[in, out]  EcContext      Pointer to the EC context.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval TRUE   EC public X,Y generation succeeded.
> > +  @retval FALSE  EC public X,Y generation failed.
> > +  @retval FALSE  PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Gets the public key component from the established EC context.
> > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > +  generate key pair from EcGenerateKey().
> > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > +                                  On output, the size of data returned in Public buffer in bytes.
> > +  @retval  TRUE   EC key component was retrieved successfully.
> > +  @retval  FALSE  Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > +  IN OUT  VOID   *EcContext,
> > +  OUT     UINT8  *PublicKey,
> > +  IN OUT  UINTN  *PublicKeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Computes exchanged common key.
> > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > +  based on its own context including value of curve parameter and random secret.
> > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > +  If EcContext is NULL, then return FALSE.
> > +  If PeerPublic is NULL, then return FALSE.
> > +  If PeerPublicSize is 0, then return FALSE.
> > +  If Key is NULL, then return FALSE.
> > +  If KeySize is not large enough, then return FALSE.
> > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > +  @param[in, out]  EcContext          Pointer to the EC context.
> > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > +                                      On output, the size of data returned in Key buffer in bytes.
> > +  @retval TRUE   EC exchanged key generation succeeded.
> > +  @retval FALSE  EC exchanged key generation failed.
> > +  @retval FALSE  KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > +  IN OUT  VOID         *EcContext,
> > +  IN      CONST UINT8  *PeerPublic,
> > +  IN      UINTN        PeerPublicSize,
> > +  IN      CONST INT32  *CompressFlag,
> > +  OUT     UINT8        *Key,
> > +  IN OUT  UINTN        *KeySize
> > +  )
> > +{
> > +  ASSERT (FALSE);
> > +  return FALSE;
> > +}
> > --
> > 2.31.1.windows.1
> >
> >
> >
> > 
> >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-22 12:54         ` yi1 li
@ 2022-09-22 22:46           ` Michael D Kinney
  2022-09-23  3:01             ` yi1 li
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-22 22:46 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io, Kinney, Michael D
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Yi,

I agree EC is an important feature.

I did some analysis of the size impact to the CryptoPkg modules on current trunk
with EC on and off. Uncompressed size is important for PEI Phase.  For DXE and
SMM phase, the Crypto services can always be compressed.  From the table below,
building all the EC services in the OpensslLib has no size impact to the NONE 
profile and the MIN_PEI profile.  It has ~105 KB impact to compressed DXE/SMM 
usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

                                   Uncompressed      LZMA Compressed
CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE  EC=TRUE  Increase
====  ===============  ========  ========  =======  ========  =======  ========
IA32  NONE             CryptoPei    21536    21568                         0 KB
IA32  NONE             CryptoDxe    21632    21696                         0 KB
IA32  NONE             CryptoSmm    22976    23072                         0 KB
IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520   401034    113 KB
IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517   296022    105 KB
IA32  ALL              CryptoPei   423840   598976    189047   293759    104 KB
IA32  ALL              CryptoDxe   645280   838144    292955   405277    113 KB
IA32  ALL              CryptoSmm   441888   617184    198779   303628    105 KB
X64   NONE             CryptoPei    29632    29664                         0 KB
X64   NONE             CryptoDxe    29792    29792                         0 KB
X64   NONE             CryptoSmm    31296    31296                         0 KB
X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436   426596    115 KB
X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483   310775    106 KB
X64   ALL              CryptoPei   540384   730240    202494   308467    106 KB
X64   ALL              CryptoDxe   815392  1027296    316228   431321    115 KB
X64   ALL              CryptoSmm   563648   753696    213488   319644    106 KB

NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
      entire FV is compressed, the total size impact is typically the size of a
      single instance of a compressed CryptoLib.  The sizes of the Crypto* modules
      in the table above should be a close approximation of the size impact to a
      single FV.

Does this match your previous size analysis?

The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
causes the modules that do not use any EC services to grow by ~105KB.  Has any
detailed analysis of the final linked images been performed to see where this 
additional size is coming from?

Thanks,

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 5:54 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> I have did some POC that seems existed structured PCD is hard to control binary size,
> Here is the previous discussion for reference.
> https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> https://edk2.groups.io/g/devel/topic/86257810#81814
> https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> 
> Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 11:56 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> That change to OpensslLib.inf should not have been done either.
> 
> Looks like this EC feature needs more evaluation to fit into the
> structured PCD control of the lib sizes.
> 
> Mike
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Wednesday, September 21, 2022 7:16 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > Thanks for review.
> >
> > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> as
> > an error
> >         1 file(s) copied.
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > undefined; assuming extern returning int
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > levels of indirection from 'int'
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> > assuming extern returning int
> >
> > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > 02-L238
> >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> >
> > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> > welcome.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 12:22 AM
> > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Comments embedded below.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > To: devel@edk2.groups.io
> > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > 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>
> > > ---
> > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > >  8 files changed, 2186 insertions(+)
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > >
> > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > index b253923dd8..d74fc21c1e 100644
> > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >  #include <Uefi/UefiBaseType.h>
> > >
> > > +#define CRYPTO_NID_NULL  0x0000
> > > +
> > > +// Key Exchange
> > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > +
> > >  ///
> > >  /// MD5 digest size in bytes
> > >  ///
> > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > >    OUT VOID       *BnRes
> > >    );
> > >
> > > +// =====================================================================================
> > > +//    Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  );
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient.
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  );
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  );
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  );
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  );
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  );
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +// =====================================================================================
> > > +//    Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  );
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  );
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  );
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  );
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  );
> > > +
> > >  #endif // __BASE_CRYPT_LIB_H__
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > @@ -52,6 +52,8 @@
> > >    Pk/CryptTs.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSign.c
> > > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> >
> > The use of the PCD to select the file should not be needed here.  The
> > Ec Family and individual service enable/disable fields in the
> > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > disable the Ec services.
> >
> > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > completely as part of this patch series.
> >
> > >    Pem/CryptPem.c
> > >    Bn/CryptBn.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > index 65ad23fb81..383df2b23c 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > @@ -58,6 +58,7 @@
> > >    Pk/CryptTsNull.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSignNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPemNull.c
> > >    Rand/CryptRandNull.c
> > >    Bn/CryptBnNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > new file mode 100644
> > > index 0000000000..396c819834
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > @@ -0,0 +1,765 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "InternalCryptLib.h"
> > > +#include <openssl/objects.h>
> > > +#include <openssl/bn.h>
> > > +#include <openssl/ec.h>
> > > +
> > > +// =====================================================================================
> > > +//    Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Return the Nid of certain ECC curve.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval !=-1    On success.
> > > +  @retval -1      ECC curve not supported.
> > > +**/
> > > +STATIC
> > > +INT32
> > > +CryptoNidToOpensslNid (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  INT32  Nid;
> > > +
> > > +  switch (CryptoNid) {
> > > +    case CRYPTO_NID_SECP256R1:
> > > +      Nid = NID_X9_62_prime256v1;
> > > +      break;
> > > +    case CRYPTO_NID_SECP384R1:
> > > +      Nid = NID_secp384r1;
> > > +      break;
> > > +    case CRYPTO_NID_SECP521R1:
> > > +      Nid = NID_secp521r1;
> > > +      break;
> > > +    default:
> > > +      return -1;
> > > +  }
> > > +
> > > +  return Nid;
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  INT32  Nid;
> > > +
> > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > +
> > > +  if (Nid < 0) {
> > > +    return NULL;
> > > +  }
> > > +
> > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  EC_GROUP_free (EcGroup);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  return EC_POINT_new (EcGroup);
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  if (Clear) {
> > > +    EC_POINT_clear_free (EcPoint);
> > > +  } else {
> > > +    EC_POINT_free (EcPoint);
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > +}
> > > +
> > > +// =====================================================================================
> > > +//    Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > > +                    BaseCryptLib.h).
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  INT32  OpenSslNid;
> > > +
> > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > +  if (OpenSslNid < 0) {
> > > +    return NULL;
> > > +  }
> > > +
> > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  CONST EC_POINT  *EcPoint;
> > > +  BOOLEAN         RetVal;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  UINTN           HalfSize;
> > > +  INTN            XSize;
> > > +  INTN            YSize;
> > > +
> > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +
> > > +  // Assume RAND_seed was called
> > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (*PublicKeySize < HalfSize * 2) {
> > > +    *PublicKeySize = HalfSize * 2;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *PublicKeySize = HalfSize * 2;
> > > +
> > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > +  if (EcPoint == NULL) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  RetVal = FALSE;
> > > +  BnX    = BN_new ();
> > > +  BnY    = BN_new ();
> > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  XSize = BN_num_bytes (BnX);
> > > +  YSize = BN_num_bytes (BnY);
> > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  return RetVal;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  CONST EC_POINT  *EcPoint;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  UINTN           HalfSize;
> > > +  INTN            XSize;
> > > +  INTN            YSize;
> > > +  BOOLEAN         RetVal;
> > > +
> > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +  if (*PublicKeySize < HalfSize * 2) {
> > > +    *PublicKeySize = HalfSize * 2;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *PublicKeySize = HalfSize * 2;
> > > +
> > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > +  if (EcPoint == NULL) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  RetVal = FALSE;
> > > +  BnX    = BN_new ();
> > > +  BnY    = BN_new ();
> > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  XSize = BN_num_bytes (BnX);
> > > +  YSize = BN_num_bytes (BnY);
> > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > +  if (PublicKey != NULL) {
> > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +  }
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  return RetVal;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  EC_KEY          *PeerEcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  BOOLEAN         RetVal;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  EC_POINT        *Point;
> > > +  INT32           OpenSslNid;
> > > +  UINTN           HalfSize;
> > > +
> > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (PeerPublicSize > INT_MAX) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (*KeySize < HalfSize) {
> > > +    *KeySize = HalfSize;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *KeySize = HalfSize;
> > > +
> > > +  RetVal    = FALSE;
> > > +  Point     = NULL;
> > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > +  BnY       = NULL;
> > > +  Point     = EC_POINT_new (Group);
> > > +  PeerEcKey = NULL;
> > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (CompressFlag == NULL) {
> > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > +    if (BnY == NULL) {
> > > +      goto fail;
> > > +    }
> > > +
> > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > +      goto fail;
> > > +    }
> > > +  } else {
> > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > +      goto fail;
> > > +    }
> > > +  }
> > > +
> > > +  // Validate NIST ECDH public key
> > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > +  if (PeerEcKey == NULL) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  EC_POINT_free (Point);
> > > +  EC_KEY_free (PeerEcKey);
> > > +  return RetVal;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > index ce6a789dfd..4bc3063485 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > @@ -59,6 +59,7 @@
> > >    Pk/CryptTsNull.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSignNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPem.c
> > >    Bn/CryptBnNull.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > index 354f3d80aa..e1a57ef09f 100644
> > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > @@ -49,6 +49,7 @@
> > >    Pk/CryptX509Null.c
> > >    Pk/CryptAuthenticodeNull.c
> > >    Pk/CryptTsNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPemNull.c
> > >    Rand/CryptRandNull.c
> > >    Pk/CryptRsaPssNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > --
> > > 2.31.1.windows.1
> > >
> > >
> > >
> > > 
> > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-22 22:46           ` Michael D Kinney
@ 2022-09-23  3:01             ` yi1 li
  2022-09-23  5:25               ` Michael D Kinney
  0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-23  3:01 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Mike,

1. Yes, it matches.
By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.

2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509  ...

If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary size,
This an example from x509/x_pubkey.c , other modules is similar:
#ifndef OPENSSL_NO_EC
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
    EVP_PKEY *pkey;
    EC_KEY *key = NULL;
    //.... call EC functions
}
#endif

If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but  not another.
This an example from ec/ec_local.h , other error is similar:

#ifndef OPENSSL_NO_EC
typedef struct ec_group_st EC_GROUP;
typedef struct ec_point_st EC_POINT;
#endif

// but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
    int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
                                                  EC_POINT *, const BIGNUM *x,
                                                  const BIGNUM *y,
                                                  const BIGNUM *z, BN_CTX *);

To avoid this annoying openssl error, we introduced conditional EC.

Thanks,
Yi

-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com> 
Sent: Friday, September 23, 2022 6:47 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Hi Yi,

I agree EC is an important feature.

I did some analysis of the size impact to the CryptoPkg modules on current trunk
with EC on and off. Uncompressed size is important for PEI Phase.  For DXE and
SMM phase, the Crypto services can always be compressed.  From the table below,
building all the EC services in the OpensslLib has no size impact to the NONE 
profile and the MIN_PEI profile.  It has ~105 KB impact to compressed DXE/SMM 
usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

                                   Uncompressed      LZMA Compressed
CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE  EC=TRUE  Increase
====  ===============  ========  ========  =======  ========  =======  ========
IA32  NONE             CryptoPei    21536    21568                         0 KB
IA32  NONE             CryptoDxe    21632    21696                         0 KB
IA32  NONE             CryptoSmm    22976    23072                         0 KB
IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520   401034    113 KB
IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517   296022    105 KB
IA32  ALL              CryptoPei   423840   598976    189047   293759    104 KB
IA32  ALL              CryptoDxe   645280   838144    292955   405277    113 KB
IA32  ALL              CryptoSmm   441888   617184    198779   303628    105 KB
X64   NONE             CryptoPei    29632    29664                         0 KB
X64   NONE             CryptoDxe    29792    29792                         0 KB
X64   NONE             CryptoSmm    31296    31296                         0 KB
X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436   426596    115 KB
X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483   310775    106 KB
X64   ALL              CryptoPei   540384   730240    202494   308467    106 KB
X64   ALL              CryptoDxe   815392  1027296    316228   431321    115 KB
X64   ALL              CryptoSmm   563648   753696    213488   319644    106 KB

NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
      entire FV is compressed, the total size impact is typically the size of a
      single instance of a compressed CryptoLib.  The sizes of the Crypto* modules
      in the table above should be a close approximation of the size impact to a
      single FV.

Does this match your previous size analysis?

The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
causes the modules that do not use any EC services to grow by ~105KB.  Has any
detailed analysis of the final linked images been performed to see where this 
additional size is coming from?

Thanks,

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 5:54 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> I have did some POC that seems existed structured PCD is hard to control binary size,
> Here is the previous discussion for reference.
> https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> https://edk2.groups.io/g/devel/topic/86257810#81814
> https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> 
> Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 11:56 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> That change to OpensslLib.inf should not have been done either.
> 
> Looks like this EC feature needs more evaluation to fit into the
> structured PCD control of the lib sizes.
> 
> Mike
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Wednesday, September 21, 2022 7:16 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > Thanks for review.
> >
> > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> as
> > an error
> >         1 file(s) copied.
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > undefined; assuming extern returning int
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > levels of indirection from 'int'
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> > assuming extern returning int
> >
> > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > 02-L238
> >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> >
> > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> > welcome.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 12:22 AM
> > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Comments embedded below.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > To: devel@edk2.groups.io
> > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > 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>
> > > ---
> > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > >  8 files changed, 2186 insertions(+)
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > >
> > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > index b253923dd8..d74fc21c1e 100644
> > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >  #include <Uefi/UefiBaseType.h>
> > >
> > > +#define CRYPTO_NID_NULL  0x0000
> > > +
> > > +// Key Exchange
> > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > +
> > >  ///
> > >  /// MD5 digest size in bytes
> > >  ///
> > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > >    OUT VOID       *BnRes
> > >    );
> > >
> > > +// =====================================================================================
> > > +//    Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  );
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient.
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  );
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  );
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  );
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  );
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  );
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  );
> > > +
> > > +// =====================================================================================
> > > +//    Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  );
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  );
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  );
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  );
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  );
> > > +
> > >  #endif // __BASE_CRYPT_LIB_H__
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > @@ -52,6 +52,8 @@
> > >    Pk/CryptTs.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSign.c
> > > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> >
> > The use of the PCD to select the file should not be needed here.  The
> > Ec Family and individual service enable/disable fields in the
> > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > disable the Ec services.
> >
> > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > completely as part of this patch series.
> >
> > >    Pem/CryptPem.c
> > >    Bn/CryptBn.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > index 65ad23fb81..383df2b23c 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > @@ -58,6 +58,7 @@
> > >    Pk/CryptTsNull.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSignNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPemNull.c
> > >    Rand/CryptRandNull.c
> > >    Bn/CryptBnNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > new file mode 100644
> > > index 0000000000..396c819834
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > @@ -0,0 +1,765 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "InternalCryptLib.h"
> > > +#include <openssl/objects.h>
> > > +#include <openssl/bn.h>
> > > +#include <openssl/ec.h>
> > > +
> > > +// =====================================================================================
> > > +//    Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Return the Nid of certain ECC curve.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval !=-1    On success.
> > > +  @retval -1      ECC curve not supported.
> > > +**/
> > > +STATIC
> > > +INT32
> > > +CryptoNidToOpensslNid (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  INT32  Nid;
> > > +
> > > +  switch (CryptoNid) {
> > > +    case CRYPTO_NID_SECP256R1:
> > > +      Nid = NID_X9_62_prime256v1;
> > > +      break;
> > > +    case CRYPTO_NID_SECP384R1:
> > > +      Nid = NID_secp384r1;
> > > +      break;
> > > +    case CRYPTO_NID_SECP521R1:
> > > +      Nid = NID_secp521r1;
> > > +      break;
> > > +    default:
> > > +      return -1;
> > > +  }
> > > +
> > > +  return Nid;
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  INT32  Nid;
> > > +
> > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > +
> > > +  if (Nid < 0) {
> > > +    return NULL;
> > > +  }
> > > +
> > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  EC_GROUP_free (EcGroup);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  return EC_POINT_new (EcGroup);
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  if (Clear) {
> > > +    EC_POINT_clear_free (EcPoint);
> > > +  } else {
> > > +    EC_POINT_free (EcPoint);
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > +}
> > > +
> > > +// =====================================================================================
> > > +//    Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > > +                    BaseCryptLib.h).
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  INT32  OpenSslNid;
> > > +
> > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > +  if (OpenSslNid < 0) {
> > > +    return NULL;
> > > +  }
> > > +
> > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  CONST EC_POINT  *EcPoint;
> > > +  BOOLEAN         RetVal;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  UINTN           HalfSize;
> > > +  INTN            XSize;
> > > +  INTN            YSize;
> > > +
> > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +
> > > +  // Assume RAND_seed was called
> > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (*PublicKeySize < HalfSize * 2) {
> > > +    *PublicKeySize = HalfSize * 2;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *PublicKeySize = HalfSize * 2;
> > > +
> > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > +  if (EcPoint == NULL) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  RetVal = FALSE;
> > > +  BnX    = BN_new ();
> > > +  BnY    = BN_new ();
> > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  XSize = BN_num_bytes (BnX);
> > > +  YSize = BN_num_bytes (BnY);
> > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  return RetVal;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  CONST EC_POINT  *EcPoint;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  UINTN           HalfSize;
> > > +  INTN            XSize;
> > > +  INTN            YSize;
> > > +  BOOLEAN         RetVal;
> > > +
> > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +  if (*PublicKeySize < HalfSize * 2) {
> > > +    *PublicKeySize = HalfSize * 2;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *PublicKeySize = HalfSize * 2;
> > > +
> > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > +  if (EcPoint == NULL) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  RetVal = FALSE;
> > > +  BnX    = BN_new ();
> > > +  BnY    = BN_new ();
> > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  XSize = BN_num_bytes (BnX);
> > > +  YSize = BN_num_bytes (BnY);
> > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > +  if (PublicKey != NULL) {
> > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +  }
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  return RetVal;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  EC_KEY          *EcKey;
> > > +  EC_KEY          *PeerEcKey;
> > > +  CONST EC_GROUP  *Group;
> > > +  BOOLEAN         RetVal;
> > > +  BIGNUM          *BnX;
> > > +  BIGNUM          *BnY;
> > > +  EC_POINT        *Point;
> > > +  INT32           OpenSslNid;
> > > +  UINTN           HalfSize;
> > > +
> > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (PeerPublicSize > INT_MAX) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  EcKey    = (EC_KEY *)EcContext;
> > > +  Group    = EC_KEY_get0_group (EcKey);
> > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  if (*KeySize < HalfSize) {
> > > +    *KeySize = HalfSize;
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  *KeySize = HalfSize;
> > > +
> > > +  RetVal    = FALSE;
> > > +  Point     = NULL;
> > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > +  BnY       = NULL;
> > > +  Point     = EC_POINT_new (Group);
> > > +  PeerEcKey = NULL;
> > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (CompressFlag == NULL) {
> > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > +    if (BnY == NULL) {
> > > +      goto fail;
> > > +    }
> > > +
> > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > +      goto fail;
> > > +    }
> > > +  } else {
> > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > +      goto fail;
> > > +    }
> > > +  }
> > > +
> > > +  // Validate NIST ECDH public key
> > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > +  if (PeerEcKey == NULL) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > +    goto fail;
> > > +  }
> > > +
> > > +  RetVal = TRUE;
> > > +
> > > +fail:
> > > +  BN_free (BnX);
> > > +  BN_free (BnY);
> > > +  EC_POINT_free (Point);
> > > +  EC_KEY_free (PeerEcKey);
> > > +  return RetVal;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > index ce6a789dfd..4bc3063485 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > @@ -59,6 +59,7 @@
> > >    Pk/CryptTsNull.c
> > >    Pk/CryptRsaPss.c
> > >    Pk/CryptRsaPssSignNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPem.c
> > >    Bn/CryptBnNull.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > index 354f3d80aa..e1a57ef09f 100644
> > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > @@ -49,6 +49,7 @@
> > >    Pk/CryptX509Null.c
> > >    Pk/CryptAuthenticodeNull.c
> > >    Pk/CryptTsNull.c
> > > +  Pk/CryptEcNull.c
> > >    Pem/CryptPemNull.c
> > >    Rand/CryptRandNull.c
> > >    Pk/CryptRsaPssNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > +  and is used for calculation within this group. This object should be freed
> > > +  using EcGroupFree() function.
> > > +
> > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > +                          BaseCryptLib.h).
> > > +
> > > +  @retval EcGroup object  On success.
> > > +  @retval NULL            On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > +  IN UINTN  CryptoNid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > +  This function will set the provided Big Number objects  to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[out] BnPrime    Group prime number.
> > > +  @param[out] BnA        A coefficient.
> > > +  @param[out] BnB        B coefficient..
> > > +  @param[in]  BnCtx      BN context.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *BnPrime,
> > > +  OUT VOID       *BnA,
> > > +  OUT VOID       *BnB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Get EC group order.
> > > +  This function will set the provided Big Number object to the corresponding
> > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > +  is properly initialized.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[out] BnOrder   Group prime number.
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > +  IN VOID   *EcGroup,
> > > +  OUT VOID  *BnOrder
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC group object using EcGroupInit().
> > > +
> > > +  @param[in]  EcGroup   EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > +  IN VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > +  within the given EC group (curve).
> > > +
> > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > +
> > > +  @retval EC Point object  On success.
> > > +  @retval NULL             On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > +  IN CONST VOID  *EcGroup
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Free previously allocated EC Point object using EcPointInit().
> > > +
> > > +  @param[in]  EcPoint   EC Point to free.
> > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > +  IN VOID     *EcPoint,
> > > +  IN BOOLEAN  Clear
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Get EC point affine (x,y) coordinates.
> > > +  This function will set the provided Big Number objects to the corresponding
> > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > +  are properly initialized.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[out] BnX        X coordinate.
> > > +  @param[out] BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  OUT VOID       *BnX,
> > > +  OUT VOID       *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point affine (x,y) coordinates.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC point object.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  BnY        Y coordinate.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN CONST VOID  *BnY,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPointA         EC Point.
> > > +  @param[in]  EcPointB         EC Point.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > +  @param[in]  EcGroup          EC group object.
> > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > +                               be properly initialized.
> > > +  @param[in]  EcPoint          EC Point.
> > > +  @param[in]  BnPScalar        P Scalar.
> > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > +  IN CONST VOID  *EcGroup,
> > > +  OUT VOID       *EcPointResult,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN CONST VOID  *BnPScalar,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Calculate the inverse of the supplied EC point.
> > > +
> > > +  @param[in]     EcGroup   EC group object.
> > > +  @param[in,out] EcPoint   EC point to invert.
> > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN OUT VOID    *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is on EC curve.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On curve.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if the supplied point is at infinity.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPoint   EC point to check.
> > > +
> > > +  @retval TRUE          At infinity.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPoint
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Check if EC points are equal.
> > > +
> > > +  @param[in]  EcGroup   EC group object.
> > > +  @param[in]  EcPointA  EC point A.
> > > +  @param[in]  EcPointB  EC point B.
> > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          A == B.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN CONST VOID  *EcPointA,
> > > +  IN CONST VOID  *EcPointB,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > +  such that the point is on the curve there will only ever be two possible
> > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > +  possible values for y should be used.
> > > +
> > > +  @param[in]  EcGroup    EC group object.
> > > +  @param[in]  EcPoint    EC Point.
> > > +  @param[in]  BnX        X coordinate.
> > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > +
> > > +  @retval TRUE          On success.
> > > +  @retval FALSE         Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > +  IN CONST VOID  *EcGroup,
> > > +  IN VOID        *EcPoint,
> > > +  IN CONST VOID  *BnX,
> > > +  IN UINT8       YBit,
> > > +  IN VOID        *BnCtx
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > +  with the NID.
> > > +
> > > +  @param[in]  Nid cipher NID
> > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > +  IN UINTN  Nid
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return NULL;
> > > +}
> > > +
> > > +/**
> > > +  Release the specified EC context.
> > > +
> > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > +  IN  VOID  *EcContext
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > +  function was properly called before.
> > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > +  returned via parameter Public, PublicSize.
> > > +  X is the first half of Public with size being PublicSize / 2,
> > > +  Y is the second half of Public with size being PublicSize / 2.
> > > +  EC context is updated accordingly.
> > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PublicSize is NULL, then return FALSE.
> > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > +  @retval FALSE  EC public X,Y generation failed.
> > > +  @retval FALSE  PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Gets the public key component from the established EC context.
> > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > +  generate key pair from EcGenerateKey().
> > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > +  @retval  FALSE  Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > +  IN OUT  VOID   *EcContext,
> > > +  OUT     UINT8  *PublicKey,
> > > +  IN OUT  UINTN  *PublicKeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Computes exchanged common key.
> > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > +  based on its own context including value of curve parameter and random secret.
> > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > +  If EcContext is NULL, then return FALSE.
> > > +  If PeerPublic is NULL, then return FALSE.
> > > +  If PeerPublicSize is 0, then return FALSE.
> > > +  If Key is NULL, then return FALSE.
> > > +  If KeySize is not large enough, then return FALSE.
> > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > +  @retval FALSE  EC exchanged key generation failed.
> > > +  @retval FALSE  KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > +  IN OUT  VOID         *EcContext,
> > > +  IN      CONST UINT8  *PeerPublic,
> > > +  IN      UINTN        PeerPublicSize,
> > > +  IN      CONST INT32  *CompressFlag,
> > > +  OUT     UINT8        *Key,
> > > +  IN OUT  UINTN        *KeySize
> > > +  )
> > > +{
> > > +  ASSERT (FALSE);
> > > +  return FALSE;
> > > +}
> > > --
> > > 2.31.1.windows.1
> > >
> > >
> > >
> > > 
> > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-23  3:01             ` yi1 li
@ 2022-09-23  5:25               ` Michael D Kinney
  2022-09-23  7:08                 ` yi1 li
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-23  5:25 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io, Chen, Christine, Feng, Bob C,
	Kinney, Michael D
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Yi,

I agree there are some complex interactions in the opensll sources.

Since you are defining a family for EC, can we use the EC Family != 0 instead of
PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

I want to make sure developers do not run into strange build failures if
they do not keep the 2 different PCDs aligned.  I prefer a single PCD 
setting to enable use of EC services.

I also noticed that the use of a PCD expression in an INF to select source
files does not work if the PCD value is specified with the --pcd flag on
the build command line.  This looks like a significant bug with the PCD
expression in an INF file.  This also needs to be fixed.

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 8:02 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> 
> 1. Yes, it matches.
> By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.
> 
> 2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509  ...
> 
> If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> size,
> This an example from x509/x_pubkey.c , other modules is similar:
> #ifndef OPENSSL_NO_EC
> EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
> {
>     EVP_PKEY *pkey;
>     EC_KEY *key = NULL;
>     //.... call EC functions
> }
> #endif
> 
> If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
> Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but  not another.
> This an example from ec/ec_local.h , other error is similar:
> 
> #ifndef OPENSSL_NO_EC
> typedef struct ec_group_st EC_GROUP;
> typedef struct ec_point_st EC_POINT;
> #endif
> 
> // but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
>     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
>                                                   EC_POINT *, const BIGNUM *x,
>                                                   const BIGNUM *y,
>                                                   const BIGNUM *z, BN_CTX *);
> 
> To avoid this annoying openssl error, we introduced conditional EC.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 6:47 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Yi,
> 
> I agree EC is an important feature.
> 
> I did some analysis of the size impact to the CryptoPkg modules on current trunk
> with EC on and off. Uncompressed size is important for PEI Phase.  For DXE and
> SMM phase, the Crypto services can always be compressed.  From the table below,
> building all the EC services in the OpensslLib has no size impact to the NONE
> profile and the MIN_PEI profile.  It has ~105 KB impact to compressed DXE/SMM
> usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> 
>                                    Uncompressed      LZMA Compressed
> CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE  EC=TRUE  Increase
> ====  ===============  ========  ========  =======  ========  =======  ========
> IA32  NONE             CryptoPei    21536    21568                         0 KB
> IA32  NONE             CryptoDxe    21632    21696                         0 KB
> IA32  NONE             CryptoSmm    22976    23072                         0 KB
> IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
> IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520   401034    113 KB
> IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517   296022    105 KB
> IA32  ALL              CryptoPei   423840   598976    189047   293759    104 KB
> IA32  ALL              CryptoDxe   645280   838144    292955   405277    113 KB
> IA32  ALL              CryptoSmm   441888   617184    198779   303628    105 KB
> X64   NONE             CryptoPei    29632    29664                         0 KB
> X64   NONE             CryptoDxe    29792    29792                         0 KB
> X64   NONE             CryptoSmm    31296    31296                         0 KB
> X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
> X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436   426596    115 KB
> X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483   310775    106 KB
> X64   ALL              CryptoPei   540384   730240    202494   308467    106 KB
> X64   ALL              CryptoDxe   815392  1027296    316228   431321    115 KB
> X64   ALL              CryptoSmm   563648   753696    213488   319644    106 KB
> 
> NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
>       entire FV is compressed, the total size impact is typically the size of a
>       single instance of a compressed CryptoLib.  The sizes of the Crypto* modules
>       in the table above should be a close approximation of the size impact to a
>       single FV.
> 
> Does this match your previous size analysis?
> 
> The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
> causes the modules that do not use any EC services to grow by ~105KB.  Has any
> detailed analysis of the final linked images been performed to see where this
> additional size is coming from?
> 
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 5:54 AM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > I have did some POC that seems existed structured PCD is hard to control binary size,
> > Here is the previous discussion for reference.
> > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > https://edk2.groups.io/g/devel/topic/86257810#81814
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> >
> > Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> > Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 11:56 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > That change to OpensslLib.inf should not have been done either.
> >
> > Looks like this EC feature needs more evaluation to fit into the
> > structured PCD control of the lib sizes.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > Thanks for review.
> > >
> > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> > >
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> > as
> > > an error
> > >         1 file(s) copied.
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > undefined; assuming extern returning int
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > > levels of indirection from 'int'
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve'
> undefined;
> > > assuming extern returning int
> > >
> > > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > 02-L238
> > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> > >
> > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas
> are
> > > welcome.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 12:22 AM
> > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Comments embedded below.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > 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>
> > > > ---
> > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > >  8 files changed, 2186 insertions(+)
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index b253923dd8..d74fc21c1e 100644
> > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >  #include <Uefi/UefiBaseType.h>
> > > >
> > > > +#define CRYPTO_NID_NULL  0x0000
> > > > +
> > > > +// Key Exchange
> > > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > > +
> > > >  ///
> > > >  /// MD5 digest size in bytes
> > > >  ///
> > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > >    OUT VOID       *BnRes
> > > >    );
> > > >
> > > > +// =====================================================================================
> > > > +//    Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient.
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +// =====================================================================================
> > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  );
> > > > +
> > > >  #endif // __BASE_CRYPT_LIB_H__
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > @@ -52,6 +52,8 @@
> > > >    Pk/CryptTs.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSign.c
> > > > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > >
> > > The use of the PCD to select the file should not be needed here.  The
> > > Ec Family and individual service enable/disable fields in the
> > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > > disable the Ec services.
> > >
> > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > > completely as part of this patch series.
> > >
> > > >    Pem/CryptPem.c
> > > >    Bn/CryptBn.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > index 65ad23fb81..383df2b23c 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > @@ -58,6 +58,7 @@
> > > >    Pk/CryptTsNull.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSignNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPemNull.c
> > > >    Rand/CryptRandNull.c
> > > >    Bn/CryptBnNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > new file mode 100644
> > > > index 0000000000..396c819834
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > @@ -0,0 +1,765 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include "InternalCryptLib.h"
> > > > +#include <openssl/objects.h>
> > > > +#include <openssl/bn.h>
> > > > +#include <openssl/ec.h>
> > > > +
> > > > +// =====================================================================================
> > > > +//    Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Return the Nid of certain ECC curve.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval !=-1    On success.
> > > > +  @retval -1      ECC curve not supported.
> > > > +**/
> > > > +STATIC
> > > > +INT32
> > > > +CryptoNidToOpensslNid (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  INT32  Nid;
> > > > +
> > > > +  switch (CryptoNid) {
> > > > +    case CRYPTO_NID_SECP256R1:
> > > > +      Nid = NID_X9_62_prime256v1;
> > > > +      break;
> > > > +    case CRYPTO_NID_SECP384R1:
> > > > +      Nid = NID_secp384r1;
> > > > +      break;
> > > > +    case CRYPTO_NID_SECP521R1:
> > > > +      Nid = NID_secp521r1;
> > > > +      break;
> > > > +    default:
> > > > +      return -1;
> > > > +  }
> > > > +
> > > > +  return Nid;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  INT32  Nid;
> > > > +
> > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > +
> > > > +  if (Nid < 0) {
> > > > +    return NULL;
> > > > +  }
> > > > +
> > > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  EC_GROUP_free (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_new (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  if (Clear) {
> > > > +    EC_POINT_clear_free (EcPoint);
> > > > +  } else {
> > > > +    EC_POINT_free (EcPoint);
> > > > +  }
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > +}
> > > > +
> > > > +// =====================================================================================
> > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > > > +                    BaseCryptLib.h).
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  INT32  OpenSslNid;
> > > > +
> > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > +  if (OpenSslNid < 0) {
> > > > +    return NULL;
> > > > +  }
> > > > +
> > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  CONST EC_POINT  *EcPoint;
> > > > +  BOOLEAN         RetVal;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  UINTN           HalfSize;
> > > > +  INTN            XSize;
> > > > +  INTN            YSize;
> > > > +
> > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +
> > > > +  // Assume RAND_seed was called
> > > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > +    *PublicKeySize = HalfSize * 2;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *PublicKeySize = HalfSize * 2;
> > > > +
> > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > +  if (EcPoint == NULL) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  RetVal = FALSE;
> > > > +  BnX    = BN_new ();
> > > > +  BnY    = BN_new ();
> > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  XSize = BN_num_bytes (BnX);
> > > > +  YSize = BN_num_bytes (BnY);
> > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  CONST EC_POINT  *EcPoint;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  UINTN           HalfSize;
> > > > +  INTN            XSize;
> > > > +  INTN            YSize;
> > > > +  BOOLEAN         RetVal;
> > > > +
> > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > +    *PublicKeySize = HalfSize * 2;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *PublicKeySize = HalfSize * 2;
> > > > +
> > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > +  if (EcPoint == NULL) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  RetVal = FALSE;
> > > > +  BnX    = BN_new ();
> > > > +  BnY    = BN_new ();
> > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  XSize = BN_num_bytes (BnX);
> > > > +  YSize = BN_num_bytes (BnY);
> > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > +  if (PublicKey != NULL) {
> > > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +  }
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  EC_KEY          *PeerEcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  BOOLEAN         RetVal;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  EC_POINT        *Point;
> > > > +  INT32           OpenSslNid;
> > > > +  UINTN           HalfSize;
> > > > +
> > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (PeerPublicSize > INT_MAX) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (*KeySize < HalfSize) {
> > > > +    *KeySize = HalfSize;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *KeySize = HalfSize;
> > > > +
> > > > +  RetVal    = FALSE;
> > > > +  Point     = NULL;
> > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > +  BnY       = NULL;
> > > > +  Point     = EC_POINT_new (Group);
> > > > +  PeerEcKey = NULL;
> > > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (CompressFlag == NULL) {
> > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > +    if (BnY == NULL) {
> > > > +      goto fail;
> > > > +    }
> > > > +
> > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > > +      goto fail;
> > > > +    }
> > > > +  } else {
> > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > > +      goto fail;
> > > > +    }
> > > > +  }
> > > > +
> > > > +  // Validate NIST ECDH public key
> > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +  if (PeerEcKey == NULL) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  EC_POINT_free (Point);
> > > > +  EC_KEY_free (PeerEcKey);
> > > > +  return RetVal;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index ce6a789dfd..4bc3063485 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > @@ -59,6 +59,7 @@
> > > >    Pk/CryptTsNull.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSignNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPem.c
> > > >    Bn/CryptBnNull.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > index 354f3d80aa..e1a57ef09f 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > @@ -49,6 +49,7 @@
> > > >    Pk/CryptX509Null.c
> > > >    Pk/CryptAuthenticodeNull.c
> > > >    Pk/CryptTsNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPemNull.c
> > > >    Rand/CryptRandNull.c
> > > >    Pk/CryptRsaPssNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > --
> > > > 2.31.1.windows.1
> > > >
> > > >
> > > >
> > > > 
> > > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-23  5:25               ` Michael D Kinney
@ 2022-09-23  7:08                 ` yi1 li
  2022-09-23 22:40                   ` Yao, Jiewen
  0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-23  7:08 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C
  Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

Hi Mike,

I did make some attempts with it, but it doesn't work, two troubles here:

Bob and Yuwei, please point out if I'm wrong:
1. Using member of structure PCD in INF isn’t supported by Basetools currently,
At least it cannot be used as FeatureFlag Expression.

2. As far as I know, structure PCD actually is a const array in code, 
I afraid it will not work fine with precompile but we do have this need:
#if !FixedPcdGetBool (PcdOpensslEcEnabled)
# ifndef OPENSSL_NO_EC
#  define OPENSSL_NO_EC
# endif
#endif

This is really caused by the bad structure of openssl,
maybe we use more detailed comments to remind developers to sync the two PCDs?

Thanks,
Yi

-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com> 
Sent: Friday, September 23, 2022 1:25 PM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Hi Yi,

I agree there are some complex interactions in the opensll sources.

Since you are defining a family for EC, can we use the EC Family != 0 instead of
PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

I want to make sure developers do not run into strange build failures if
they do not keep the 2 different PCDs aligned.  I prefer a single PCD 
setting to enable use of EC services.

I also noticed that the use of a PCD expression in an INF to select source
files does not work if the PCD value is specified with the --pcd flag on
the build command line.  This looks like a significant bug with the PCD
expression in an INF file.  This also needs to be fixed.

Mike

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 8:02 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> 
> 1. Yes, it matches.
> By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.
> 
> 2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509  ...
> 
> If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> size,
> This an example from x509/x_pubkey.c , other modules is similar:
> #ifndef OPENSSL_NO_EC
> EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
> {
>     EVP_PKEY *pkey;
>     EC_KEY *key = NULL;
>     //.... call EC functions
> }
> #endif
> 
> If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
> Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but  not another.
> This an example from ec/ec_local.h , other error is similar:
> 
> #ifndef OPENSSL_NO_EC
> typedef struct ec_group_st EC_GROUP;
> typedef struct ec_point_st EC_POINT;
> #endif
> 
> // but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
>     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
>                                                   EC_POINT *, const BIGNUM *x,
>                                                   const BIGNUM *y,
>                                                   const BIGNUM *z, BN_CTX *);
> 
> To avoid this annoying openssl error, we introduced conditional EC.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 6:47 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Yi,
> 
> I agree EC is an important feature.
> 
> I did some analysis of the size impact to the CryptoPkg modules on current trunk
> with EC on and off. Uncompressed size is important for PEI Phase.  For DXE and
> SMM phase, the Crypto services can always be compressed.  From the table below,
> building all the EC services in the OpensslLib has no size impact to the NONE
> profile and the MIN_PEI profile.  It has ~105 KB impact to compressed DXE/SMM
> usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> 
>                                    Uncompressed      LZMA Compressed
> CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE  EC=TRUE  Increase
> ====  ===============  ========  ========  =======  ========  =======  ========
> IA32  NONE             CryptoPei    21536    21568                         0 KB
> IA32  NONE             CryptoDxe    21632    21696                         0 KB
> IA32  NONE             CryptoSmm    22976    23072                         0 KB
> IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
> IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520   401034    113 KB
> IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517   296022    105 KB
> IA32  ALL              CryptoPei   423840   598976    189047   293759    104 KB
> IA32  ALL              CryptoDxe   645280   838144    292955   405277    113 KB
> IA32  ALL              CryptoSmm   441888   617184    198779   303628    105 KB
> X64   NONE             CryptoPei    29632    29664                         0 KB
> X64   NONE             CryptoDxe    29792    29792                         0 KB
> X64   NONE             CryptoSmm    31296    31296                         0 KB
> X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
> X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436   426596    115 KB
> X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483   310775    106 KB
> X64   ALL              CryptoPei   540384   730240    202494   308467    106 KB
> X64   ALL              CryptoDxe   815392  1027296    316228   431321    115 KB
> X64   ALL              CryptoSmm   563648   753696    213488   319644    106 KB
> 
> NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
>       entire FV is compressed, the total size impact is typically the size of a
>       single instance of a compressed CryptoLib.  The sizes of the Crypto* modules
>       in the table above should be a close approximation of the size impact to a
>       single FV.
> 
> Does this match your previous size analysis?
> 
> The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
> causes the modules that do not use any EC services to grow by ~105KB.  Has any
> detailed analysis of the final linked images been performed to see where this
> additional size is coming from?
> 
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 5:54 AM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > I have did some POC that seems existed structured PCD is hard to control binary size,
> > Here is the previous discussion for reference.
> > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > https://edk2.groups.io/g/devel/topic/86257810#81814
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> >
> > Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> > Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 11:56 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > That change to OpensslLib.inf should not have been done either.
> >
> > Looks like this EC feature needs more evaluation to fit into the
> > structured PCD control of the lib sizes.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > Thanks for review.
> > >
> > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> > >
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> > as
> > > an error
> > >         1 file(s) copied.
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > undefined; assuming extern returning int
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > > levels of indirection from 'int'
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve'
> undefined;
> > > assuming extern returning int
> > >
> > > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > 02-L238
> > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> > >
> > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas
> are
> > > welcome.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 12:22 AM
> > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Comments embedded below.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > 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>
> > > > ---
> > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765 ++++++++++++++++++
> > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > >  8 files changed, 2186 insertions(+)
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > >  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index b253923dd8..d74fc21c1e 100644
> > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >  #include <Uefi/UefiBaseType.h>
> > > >
> > > > +#define CRYPTO_NID_NULL  0x0000
> > > > +
> > > > +// Key Exchange
> > > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > > +
> > > >  ///
> > > >  /// MD5 digest size in bytes
> > > >  ///
> > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > >    OUT VOID       *BnRes
> > > >    );
> > > >
> > > > +// =====================================================================================
> > > > +//    Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient.
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  );
> > > > +
> > > > +// =====================================================================================
> > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  );
> > > > +
> > > >  #endif // __BASE_CRYPT_LIB_H__
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > @@ -52,6 +52,8 @@
> > > >    Pk/CryptTs.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSign.c
> > > > +  Pk/CryptEcNull.c    |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > +  Pk/CryptEc.c    |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > >
> > > The use of the PCD to select the file should not be needed here.  The
> > > Ec Family and individual service enable/disable fields in the
> > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > > disable the Ec services.
> > >
> > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > > completely as part of this patch series.
> > >
> > > >    Pem/CryptPem.c
> > > >    Bn/CryptBn.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > index 65ad23fb81..383df2b23c 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > @@ -58,6 +58,7 @@
> > > >    Pk/CryptTsNull.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSignNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPemNull.c
> > > >    Rand/CryptRandNull.c
> > > >    Bn/CryptBnNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > new file mode 100644
> > > > index 0000000000..396c819834
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > @@ -0,0 +1,765 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include "InternalCryptLib.h"
> > > > +#include <openssl/objects.h>
> > > > +#include <openssl/bn.h>
> > > > +#include <openssl/ec.h>
> > > > +
> > > > +// =====================================================================================
> > > > +//    Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Return the Nid of certain ECC curve.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval !=-1    On success.
> > > > +  @retval -1      ECC curve not supported.
> > > > +**/
> > > > +STATIC
> > > > +INT32
> > > > +CryptoNidToOpensslNid (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  INT32  Nid;
> > > > +
> > > > +  switch (CryptoNid) {
> > > > +    case CRYPTO_NID_SECP256R1:
> > > > +      Nid = NID_X9_62_prime256v1;
> > > > +      break;
> > > > +    case CRYPTO_NID_SECP384R1:
> > > > +      Nid = NID_secp384r1;
> > > > +      break;
> > > > +    case CRYPTO_NID_SECP521R1:
> > > > +      Nid = NID_secp521r1;
> > > > +      break;
> > > > +    default:
> > > > +      return -1;
> > > > +  }
> > > > +
> > > > +  return Nid;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  INT32  Nid;
> > > > +
> > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > +
> > > > +  if (Nid < 0) {
> > > > +    return NULL;
> > > > +  }
> > > > +
> > > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  EC_GROUP_free (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_new (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  if (Clear) {
> > > > +    EC_POINT_clear_free (EcPoint);
> > > > +  } else {
> > > > +    EC_POINT_free (EcPoint);
> > > > +  }
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > +}
> > > > +
> > > > +// =====================================================================================
> > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined in
> > > > +                    BaseCryptLib.h).
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  INT32  OpenSslNid;
> > > > +
> > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > +  if (OpenSslNid < 0) {
> > > > +    return NULL;
> > > > +  }
> > > > +
> > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  CONST EC_POINT  *EcPoint;
> > > > +  BOOLEAN         RetVal;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  UINTN           HalfSize;
> > > > +  INTN            XSize;
> > > > +  INTN            YSize;
> > > > +
> > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +
> > > > +  // Assume RAND_seed was called
> > > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > +    *PublicKeySize = HalfSize * 2;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *PublicKeySize = HalfSize * 2;
> > > > +
> > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > +  if (EcPoint == NULL) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  RetVal = FALSE;
> > > > +  BnX    = BN_new ();
> > > > +  BnY    = BN_new ();
> > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  XSize = BN_num_bytes (BnX);
> > > > +  YSize = BN_num_bytes (BnY);
> > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  CONST EC_POINT  *EcPoint;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  UINTN           HalfSize;
> > > > +  INTN            XSize;
> > > > +  INTN            YSize;
> > > > +  BOOLEAN         RetVal;
> > > > +
> > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > +    *PublicKeySize = HalfSize * 2;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *PublicKeySize = HalfSize * 2;
> > > > +
> > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > +  if (EcPoint == NULL) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  RetVal = FALSE;
> > > > +  BnX    = BN_new ();
> > > > +  BnY    = BN_new ();
> > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  XSize = BN_num_bytes (BnX);
> > > > +  YSize = BN_num_bytes (BnY);
> > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > +  if (PublicKey != NULL) {
> > > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +  }
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If public key is compressed, the PeerPublic will only contain half key (X).
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  EC_KEY          *EcKey;
> > > > +  EC_KEY          *PeerEcKey;
> > > > +  CONST EC_GROUP  *Group;
> > > > +  BOOLEAN         RetVal;
> > > > +  BIGNUM          *BnX;
> > > > +  BIGNUM          *BnY;
> > > > +  EC_POINT        *Point;
> > > > +  INT32           OpenSslNid;
> > > > +  UINTN           HalfSize;
> > > > +
> > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (PeerPublicSize > INT_MAX) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  if (*KeySize < HalfSize) {
> > > > +    *KeySize = HalfSize;
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  *KeySize = HalfSize;
> > > > +
> > > > +  RetVal    = FALSE;
> > > > +  Point     = NULL;
> > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > +  BnY       = NULL;
> > > > +  Point     = EC_POINT_new (Group);
> > > > +  PeerEcKey = NULL;
> > > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (CompressFlag == NULL) {
> > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > +    if (BnY == NULL) {
> > > > +      goto fail;
> > > > +    }
> > > > +
> > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > > +      goto fail;
> > > > +    }
> > > > +  } else {
> > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > > +      goto fail;
> > > > +    }
> > > > +  }
> > > > +
> > > > +  // Validate NIST ECDH public key
> > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +  if (PeerEcKey == NULL) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > +    goto fail;
> > > > +  }
> > > > +
> > > > +  RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > +  BN_free (BnX);
> > > > +  BN_free (BnY);
> > > > +  EC_POINT_free (Point);
> > > > +  EC_KEY_free (PeerEcKey);
> > > > +  return RetVal;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index ce6a789dfd..4bc3063485 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > @@ -59,6 +59,7 @@
> > > >    Pk/CryptTsNull.c
> > > >    Pk/CryptRsaPss.c
> > > >    Pk/CryptRsaPssSignNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPem.c
> > > >    Bn/CryptBnNull.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > index 354f3d80aa..e1a57ef09f 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > @@ -49,6 +49,7 @@
> > > >    Pk/CryptX509Null.c
> > > >    Pk/CryptAuthenticodeNull.c
> > > >    Pk/CryptTsNull.c
> > > > +  Pk/CryptEcNull.c
> > > >    Pem/CryptPemNull.c
> > > >    Rand/CryptRandNull.c
> > > >    Pk/CryptRsaPssNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > +  and is used for calculation within this group. This object should be freed
> > > > +  using EcGroupFree() function.
> > > > +
> > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
> > > > +                          BaseCryptLib.h).
> > > > +
> > > > +  @retval EcGroup object  On success.
> > > > +  @retval NULL            On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > +  IN UINTN  CryptoNid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > +  This function will set the provided Big Number objects  to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[out] BnPrime    Group prime number.
> > > > +  @param[out] BnA        A coefficient.
> > > > +  @param[out] BnB        B coefficient..
> > > > +  @param[in]  BnCtx      BN context.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *BnPrime,
> > > > +  OUT VOID       *BnA,
> > > > +  OUT VOID       *BnB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC group order.
> > > > +  This function will set the provided Big Number object to the corresponding
> > > > +  value. The caller needs to make sure that the "out" BigNumber parameter
> > > > +  is properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[out] BnOrder   Group prime number.
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > +  IN VOID   *EcGroup,
> > > > +  OUT VOID  *BnOrder
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > +  @param[in]  EcGroup   EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > +  IN VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Initialize new opaque EC Point object. This object represents an EC point
> > > > +  within the given EC group (curve).
> > > > +
> > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > +  @retval EC Point object  On success.
> > > > +  @retval NULL             On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > +  IN CONST VOID  *EcGroup
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > +  @param[in]  EcPoint   EC Point to free.
> > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > +  IN VOID     *EcPoint,
> > > > +  IN BOOLEAN  Clear
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Get EC point affine (x,y) coordinates.
> > > > +  This function will set the provided Big Number objects to the corresponding
> > > > +  values. The caller needs to make sure all the "out" BigNumber parameters
> > > > +  are properly initialized.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[out] BnX        X coordinate.
> > > > +  @param[out] BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  OUT VOID       *BnX,
> > > > +  OUT VOID       *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point affine (x,y) coordinates.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC point object.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  BnY        Y coordinate.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN CONST VOID  *BnY,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPointA         EC Point.
> > > > +  @param[in]  EcPointB         EC Point.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > +  @param[in]  EcGroup          EC group object.
> > > > +  @param[out] EcPointResult    EC point to hold the result. The point should
> > > > +                               be properly initialized.
> > > > +  @param[in]  EcPoint          EC Point.
> > > > +  @param[in]  BnPScalar        P Scalar.
> > > > +  @param[in]  BnCtx            BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  OUT VOID       *EcPointResult,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN CONST VOID  *BnPScalar,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Calculate the inverse of the supplied EC point.
> > > > +
> > > > +  @param[in]     EcGroup   EC group object.
> > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > +  @param[in]     BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN OUT VOID    *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is on EC curve.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On curve.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if the supplied point is at infinity.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPoint   EC point to check.
> > > > +
> > > > +  @retval TRUE          At infinity.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPoint
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Check if EC points are equal.
> > > > +
> > > > +  @param[in]  EcGroup   EC group object.
> > > > +  @param[in]  EcPointA  EC point A.
> > > > +  @param[in]  EcPointB  EC point B.
> > > > +  @param[in]  BnCtx     BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          A == B.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN CONST VOID  *EcPointA,
> > > > +  IN CONST VOID  *EcPointB,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Set EC point compressed coordinates. Points can be described in terms of
> > > > +  their compressed coordinates. For a point (x, y), for any given value for x
> > > > +  such that the point is on the curve there will only ever be two possible
> > > > +  values for y. Therefore, a point can be set using this function where BnX is
> > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > +  possible values for y should be used.
> > > > +
> > > > +  @param[in]  EcGroup    EC group object.
> > > > +  @param[in]  EcPoint    EC Point.
> > > > +  @param[in]  BnX        X coordinate.
> > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > +  @param[in]  BnCtx      BN context, created with BigNumNewContext().
> > > > +
> > > > +  @retval TRUE          On success.
> > > > +  @retval FALSE         Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > +  IN CONST VOID  *EcGroup,
> > > > +  IN VOID        *EcPoint,
> > > > +  IN CONST VOID  *BnX,
> > > > +  IN UINT8       YBit,
> > > > +  IN VOID        *BnCtx
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > +  with the NID.
> > > > +
> > > > +  @param[in]  Nid cipher NID
> > > > +  @return     Pointer to the Elliptic Curve Context that has been initialized.
> > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > +  IN UINTN  Nid
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Release the specified EC context.
> > > > +
> > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > +  IN  VOID  *EcContext
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > +  Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > +  pseudo random number generator. The caller must make sure RandomSeed()
> > > > +  function was properly called before.
> > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > +  This function generates random secret, and computes the public key (X, Y), which is
> > > > +  returned via parameter Public, PublicSize.
> > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > +  EC context is updated accordingly.
> > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > +  PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PublicSize is NULL, then return FALSE.
> > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets the public key component from the established EC context.
> > > > +  The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > +  generate key pair from EcGenerateKey().
> > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > +  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
> > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
> > > > +                                  On output, the size of data returned in Public buffer in bytes.
> > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > +  @retval  FALSE  Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > +  IN OUT  VOID   *EcContext,
> > > > +  OUT     UINT8  *PublicKey,
> > > > +  IN OUT  UINTN  *PublicKeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Computes exchanged common key.
> > > > +  Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > +  based on its own context including value of curve parameter and random secret.
> > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > +  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > +  If EcContext is NULL, then return FALSE.
> > > > +  If PeerPublic is NULL, then return FALSE.
> > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > +  If Key is NULL, then return FALSE.
> > > > +  If KeySize is not large enough, then return FALSE.
> > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > +  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
> > > > +  @param[out]      Key                Pointer to the buffer to receive generated key.
> > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
> > > > +                                      On output, the size of data returned in Key buffer in bytes.
> > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > +  @retval FALSE  KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > +  IN OUT  VOID         *EcContext,
> > > > +  IN      CONST UINT8  *PeerPublic,
> > > > +  IN      UINTN        PeerPublicSize,
> > > > +  IN      CONST INT32  *CompressFlag,
> > > > +  OUT     UINT8        *Key,
> > > > +  IN OUT  UINTN        *KeySize
> > > > +  )
> > > > +{
> > > > +  ASSERT (FALSE);
> > > > +  return FALSE;
> > > > +}
> > > > --
> > > > 2.31.1.windows.1
> > > >
> > > >
> > > >
> > > > 
> > > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-23  7:08                 ` yi1 li
@ 2022-09-23 22:40                   ` Yao, Jiewen
  2022-09-24  2:19                     ` Michael D Kinney
  0 siblings, 1 reply; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-23 22:40 UTC (permalink / raw)
  To: Li, Yi1, Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

Hi Mike
This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.

Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do enhancement for PCD related stuff later?

Or if you have any other idea, please let us know.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Friday, September 23, 2022 3:09 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob
> C <bob.c.feng@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike,
> 
> I did make some attempts with it, but it doesn't work, two troubles here:
> 
> Bob and Yuwei, please point out if I'm wrong:
> 1. Using member of structure PCD in INF isn’t supported by Basetools
> currently,
> At least it cannot be used as FeatureFlag Expression.
> 
> 2. As far as I know, structure PCD actually is a const array in code,
> I afraid it will not work fine with precompile but we do have this need:
> #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> # ifndef OPENSSL_NO_EC
> #  define OPENSSL_NO_EC
> # endif
> #endif
> 
> This is really caused by the bad structure of openssl,
> maybe we use more detailed comments to remind developers to sync the
> two PCDs?
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 1:25 PM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine
> <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Yi,
> 
> I agree there are some complex interactions in the opensll sources.
> 
> Since you are defining a family for EC, can we use the EC Family != 0 instead
> of
> PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> 
> I want to make sure developers do not run into strange build failures if
> they do not keep the 2 different PCDs aligned.  I prefer a single PCD
> setting to enable use of EC services.
> 
> I also noticed that the use of a PCD expression in an INF to select source
> files does not work if the PCD value is specified with the --pcd flag on
> the build command line.  This looks like a significant bug with the PCD
> expression in an INF file.  This also needs to be fixed.
> 
> Mike
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 8:02 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > 1. Yes, it matches.
> > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> refer to another internal email.
> >
> > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> PEM X509  ...
> >
> > If we added EC source to OpensslLib.inf and disabled macro
> OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > size,
> > This an example from x509/x_pubkey.c , other modules is similar:
> > #ifndef OPENSSL_NO_EC
> > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> length)
> > {
> >     EVP_PKEY *pkey;
> >     EC_KEY *key = NULL;
> >     //.... call EC functions
> > }
> > #endif
> >
> > If we added EC source to OpensslLib.inf and enable macro
> OPENSSL_NO_EC, EC module will throw build error,
> > Since some EC internal APIs or structs have been disabled by
> OPENSSL_NO_EC but  not another.
> > This an example from ec/ec_local.h , other error is similar:
> >
> > #ifndef OPENSSL_NO_EC
> > typedef struct ec_group_st EC_GROUP;
> > typedef struct ec_point_st EC_POINT;
> > #endif
> >
> > // but this function not been enclosed by OPENSSL_NO_EC, and will
> throw build error
> >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> >                                                   EC_POINT *, const BIGNUM *x,
> >                                                   const BIGNUM *y,
> >                                                   const BIGNUM *z, BN_CTX *);
> >
> > To avoid this annoying openssl error, we introduced conditional EC.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Friday, September 23, 2022 6:47 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D
> <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree EC is an important feature.
> >
> > I did some analysis of the size impact to the CryptoPkg modules on
> current trunk
> > with EC on and off. Uncompressed size is important for PEI Phase.  For
> DXE and
> > SMM phase, the Crypto services can always be compressed.  From the
> table below,
> > building all the EC services in the OpensslLib has no size impact to the
> NONE
> > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed
> DXE/SMM
> > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> >
> >                                    Uncompressed      LZMA Compressed
> > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE
> EC=TRUE  Increase
> > ====  ===============  ========  ========  =======  ========
> =======  ========
> > IA32  NONE             CryptoPei    21536    21568                         0 KB
> > IA32  NONE             CryptoDxe    21632    21696                         0 KB
> > IA32  NONE             CryptoSmm    22976    23072                         0 KB
> > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
> > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520
> 401034    113 KB
> > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517
> 296022    105 KB
> > IA32  ALL              CryptoPei   423840   598976    189047   293759    104
> KB
> > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113
> KB
> > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105
> KB
> > X64   NONE             CryptoPei    29632    29664                         0 KB
> > X64   NONE             CryptoDxe    29792    29792                         0 KB
> > X64   NONE             CryptoSmm    31296    31296                         0 KB
> > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
> > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436
> 426596    115 KB
> > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483
> 310775    106 KB
> > X64   ALL              CryptoPei   540384   730240    202494   308467    106
> KB
> > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115
> KB
> > X64   ALL              CryptoSmm   563648   753696    213488   319644    106
> KB
> >
> > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> the
> >       entire FV is compressed, the total size impact is typically the size of a
> >       single instance of a compressed CryptoLib.  The sizes of the Crypto*
> modules
> >       in the table above should be a close approximation of the size impact
> to a
> >       single FV.
> >
> > Does this match your previous size analysis?
> >
> > The critical issue to evaluate here is why adding the EC sources to
> OpensllLib.inf
> > causes the modules that do not use any EC services to grow by ~105KB.
> Has any
> > detailed analysis of the final linked images been performed to see where
> this
> > additional size is coming from?
> >
> > Thanks,
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Thursday, September 22, 2022 5:54 AM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > I have did some POC that seems existed structured PCD is hard to
> control binary size,
> > > Here is the previous discussion for reference.
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > >
> > > Anyway EC is an important feature which consumed by vary modern
> security features such WPA3 , SPDM, TLS1.3 etc.
> > > Hope it can be added to edk2, and I am glad to take the code and test
> work if there are other ways to control the size.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 11:56 AM
> > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly
> <shelly.kishore@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > That change to OpensslLib.inf should not have been done either.
> > >
> > > Looks like this EC feature needs more evaluation to fit into the
> > > structured PCD control of the lib sizes.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > Thanks for review.
> > > >
> > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> will also be compiled and throw build error:
> > > >
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): error C2220: the following warning is treated
> > > as
> > > > an error
> > > >         1 file(s) copied.
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > undefined; assuming extern returning int
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): warning C4047: 'return': 'void *' differs in
> > > > levels of indirection from 'int'
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(105): warning C4013: 'EC_GROUP_get_curve'
> > undefined;
> > > > assuming extern returning int
> > > >
> > > > I think the root cause is that we have enabled conditional ec in
> OpensslLib.inf before by PcdOpensslEcEnabled,
> > > >
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > 02-L238
> > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > This will save 200+kb memory on platforms which use dxe driver but
> do not need ec feature.
> > > >
> > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> sure if there is any other way, other better ideas
> > are
> > > > welcome.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael
> D <michael.d.kinney@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Comments embedded below.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> yi1 li
> > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > To: devel@edk2.groups.io
> > > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > 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>
> > > > > ---
> > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765
> ++++++++++++++++++
> > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > >  8 files changed, 2186 insertions(+)
> > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > >  create mode 100644
> CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > >  create mode 100644
> CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > >
> > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > index b253923dd8..d74fc21c1e 100644
> > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > >  #include <Uefi/UefiBaseType.h>
> > > > >
> > > > > +#define CRYPTO_NID_NULL  0x0000
> > > > > +
> > > > > +// Key Exchange
> > > > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > > > +
> > > > >  ///
> > > > >  /// MD5 digest size in bytes
> > > > >  ///
> > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > >    OUT VOID       *BnRes
> > > > >    );
> > > > >
> > > > > +//
> ==========================================================
> ===========================
> > > > > +//    Basic Elliptic Curve Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > +  and is used for calculation within this group. This object should be
> freed
> > > > > +  using EcGroupFree() function.
> > > > > +
> > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> (Defined in
> > > > > +                          BaseCryptLib.h).
> > > > > +
> > > > > +  @retval EcGroup object  On success.
> > > > > +  @retval NULL            On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > +  IN UINTN  CryptoNid
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > +  This function will set the provided Big Number objects  to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[out] BnPrime    Group prime number.
> > > > > +  @param[out] BnA        A coefficient.
> > > > > +  @param[out] BnB        B coefficient.
> > > > > +  @param[in]  BnCtx      BN context.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *BnPrime,
> > > > > +  OUT VOID       *BnA,
> > > > > +  OUT VOID       *BnB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Get EC group order.
> > > > > +  This function will set the provided Big Number object to the
> corresponding
> > > > > +  value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > +  is properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[out] BnOrder   Group prime number.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > +  IN VOID   *EcGroup,
> > > > > +  OUT VOID  *BnOrder
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > +  IN VOID  *EcGroup
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > +  within the given EC group (curve).
> > > > > +
> > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > +  @retval EC Point object  On success.
> > > > > +  @retval NULL             On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > +  IN CONST VOID  *EcGroup
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > +  IN VOID     *EcPoint,
> > > > > +  IN BOOLEAN  Clear
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Get EC point affine (x,y) coordinates.
> > > > > +  This function will set the provided Big Number objects to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[out] BnX        X coordinate.
> > > > > +  @param[out] BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  OUT VOID       *BnX,
> > > > > +  OUT VOID       *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN CONST VOID  *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPointA         EC Point.
> > > > > +  @param[in]  EcPointB         EC Point.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPoint          EC Point.
> > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN CONST VOID  *BnPScalar,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > +  @param[in]     EcGroup   EC group object.
> > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > +  @param[in]     BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN OUT VOID    *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is on EC curve.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On curve.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is at infinity.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +
> > > > > +  @retval TRUE          At infinity.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Check if EC points are equal.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPointA  EC point A.
> > > > > +  @param[in]  EcPointB  EC point B.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          A == B.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > +  their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > +  such that the point is on the curve there will only ever be two
> possible
> > > > > +  values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > +  possible values for y should be used.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC Point.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN UINT8       YBit,
> > > > > +  IN VOID        *BnCtx
> > > > > +  );
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > +  with the NID.
> > > > > +
> > > > > +  @param[in]  Nid cipher NID
> > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > +  IN UINTN  Nid
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Release the specified EC context.
> > > > > +
> > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > +  IN  VOID  *EcContext
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > +  pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > +  function was properly called before.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > +  This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > +  returned via parameter Public, PublicSize.
> > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > +  EC context is updated accordingly.
> > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Gets the public key component from the established EC context.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > +  generate key pair from EcGenerateKey().
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  );
> > > > > +
> > > > > +/**
> > > > > +  Computes exchanged common key.
> > > > > +  Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > +  based on its own context including value of curve parameter and
> random secret.
> > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > +  If Key is NULL, then return FALSE.
> > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> compressed or not.
> > > > > +  @param[out]      Key                Pointer to the buffer to receive
> generated key.
> > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> bytes.
> > > > > +                                      On output, the size of data returned in Key
> buffer in bytes.
> > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > +  IN OUT  VOID         *EcContext,
> > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > +  IN      UINTN        PeerPublicSize,
> > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > +  OUT     UINT8        *Key,
> > > > > +  IN OUT  UINTN        *KeySize
> > > > > +  );
> > > > > +
> > > > >  #endif // __BASE_CRYPT_LIB_H__
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > @@ -52,6 +52,8 @@
> > > > >    Pk/CryptTs.c
> > > > >    Pk/CryptRsaPss.c
> > > > >    Pk/CryptRsaPssSign.c
> > > > > +  Pk/CryptEcNull.c
> |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > +  Pk/CryptEc.c
> |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > >
> > > > The use of the PCD to select the file should not be needed here.  The
> > > > Ec Family and individual service enable/disable fields in the
> > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> needed to
> > > > disable the Ec services.
> > > >
> > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> be removed
> > > > completely as part of this patch series.
> > > >
> > > > >    Pem/CryptPem.c
> > > > >    Bn/CryptBn.c
> > > > >
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > index 65ad23fb81..383df2b23c 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > @@ -58,6 +58,7 @@
> > > > >    Pk/CryptTsNull.c
> > > > >    Pk/CryptRsaPss.c
> > > > >    Pk/CryptRsaPssSignNull.c
> > > > > +  Pk/CryptEcNull.c
> > > > >    Pem/CryptPemNull.c
> > > > >    Rand/CryptRandNull.c
> > > > >    Bn/CryptBnNull.c
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > new file mode 100644
> > > > > index 0000000000..396c819834
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > @@ -0,0 +1,765 @@
> > > > > +/** @file
> > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include "InternalCryptLib.h"
> > > > > +#include <openssl/objects.h>
> > > > > +#include <openssl/bn.h>
> > > > > +#include <openssl/ec.h>
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +//    Basic Elliptic Curve Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > +  Return the Nid of certain ECC curve.
> > > > > +
> > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> (Defined in
> > > > > +                          BaseCryptLib.h).
> > > > > +
> > > > > +  @retval !=-1    On success.
> > > > > +  @retval -1      ECC curve not supported.
> > > > > +**/
> > > > > +STATIC
> > > > > +INT32
> > > > > +CryptoNidToOpensslNid (
> > > > > +  IN UINTN  CryptoNid
> > > > > +  )
> > > > > +{
> > > > > +  INT32  Nid;
> > > > > +
> > > > > +  switch (CryptoNid) {
> > > > > +    case CRYPTO_NID_SECP256R1:
> > > > > +      Nid = NID_X9_62_prime256v1;
> > > > > +      break;
> > > > > +    case CRYPTO_NID_SECP384R1:
> > > > > +      Nid = NID_secp384r1;
> > > > > +      break;
> > > > > +    case CRYPTO_NID_SECP521R1:
> > > > > +      Nid = NID_secp521r1;
> > > > > +      break;
> > > > > +    default:
> > > > > +      return -1;
> > > > > +  }
> > > > > +
> > > > > +  return Nid;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > +  and is used for calculation within this group. This object should be
> freed
> > > > > +  using EcGroupFree() function.
> > > > > +
> > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> (Defined in
> > > > > +                          BaseCryptLib.h).
> > > > > +
> > > > > +  @retval EcGroup object  On success.
> > > > > +  @retval NULL            On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > +  IN UINTN  CryptoNid
> > > > > +  )
> > > > > +{
> > > > > +  INT32  Nid;
> > > > > +
> > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > +
> > > > > +  if (Nid < 0) {
> > > > > +    return NULL;
> > > > > +  }
> > > > > +
> > > > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > +  This function will set the provided Big Number objects  to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[out] BnPrime    Group prime number.
> > > > > +  @param[out] BnA        A coefficient.
> > > > > +  @param[out] BnB        B coefficient..
> > > > > +  @param[in]  BnCtx      BN context.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *BnPrime,
> > > > > +  OUT VOID       *BnA,
> > > > > +  OUT VOID       *BnB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> BnB, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC group order.
> > > > > +  This function will set the provided Big Number object to the
> corresponding
> > > > > +  value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > +  is properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[out] BnOrder   Group prime number.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > +  IN VOID   *EcGroup,
> > > > > +  OUT VOID  *BnOrder
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> NULL);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > +  IN VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  EC_GROUP_free (EcGroup);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > +  within the given EC group (curve).
> > > > > +
> > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > +  @retval EC Point object  On success.
> > > > > +  @retval NULL             On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > +  IN CONST VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  return EC_POINT_new (EcGroup);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > +  IN VOID     *EcPoint,
> > > > > +  IN BOOLEAN  Clear
> > > > > +  )
> > > > > +{
> > > > > +  if (Clear) {
> > > > > +    EC_POINT_clear_free (EcPoint);
> > > > > +  } else {
> > > > > +    EC_POINT_free (EcPoint);
> > > > > +  }
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC point affine (x,y) coordinates.
> > > > > +  This function will set the provided Big Number objects to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[out] BnX        X coordinate.
> > > > > +  @param[out] BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  OUT VOID       *BnX,
> > > > > +  OUT VOID       *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> EcPoint, BnX, BnY, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN CONST VOID  *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> EcPoint, BnX, BnY, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPointA         EC Point.
> > > > > +  @param[in]  EcPointB         EC Point.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> EcPointA, EcPointB, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPoint          EC Point.
> > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN CONST VOID  *BnPScalar,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> EcPoint, BnPScalar, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > +  @param[in]     EcGroup   EC group object.
> > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > +  @param[in]     BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN OUT VOID    *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is on EC curve.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On curve.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is at infinity.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +
> > > > > +  @retval TRUE          At infinity.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint
> > > > > +  )
> > > > > +{
> > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if EC points are equal.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPointA  EC point A.
> > > > > +  @param[in]  EcPointB  EC point B.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          A == B.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > +  their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > +  such that the point is on the curve there will only ever be two
> possible
> > > > > +  values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > +  possible values for y should be used.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC Point.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN UINT8       YBit,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates
> (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > +}
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > +  with the NID.
> > > > > +
> > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined
> in
> > > > > +                    BaseCryptLib.h).
> > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > +  IN UINTN  Nid
> > > > > +  )
> > > > > +{
> > > > > +  INT32  OpenSslNid;
> > > > > +
> > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > +  if (OpenSslNid < 0) {
> > > > > +    return NULL;
> > > > > +  }
> > > > > +
> > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Release the specified EC context.
> > > > > +
> > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > +  IN  VOID  *EcContext
> > > > > +  )
> > > > > +{
> > > > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > +  pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > +  function was properly called before.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > +  This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > +  returned via parameter Public, PublicSize.
> > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > +  EC context is updated accordingly.
> > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  EC_KEY          *EcKey;
> > > > > +  CONST EC_GROUP  *Group;
> > > > > +  CONST EC_POINT  *EcPoint;
> > > > > +  BOOLEAN         RetVal;
> > > > > +  BIGNUM          *BnX;
> > > > > +  BIGNUM          *BnY;
> > > > > +  UINTN           HalfSize;
> > > > > +  INTN            XSize;
> > > > > +  INTN            YSize;
> > > > > +
> > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > +
> > > > > +  // Assume RAND_seed was called
> > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > > +    *PublicKeySize = HalfSize * 2;
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  *PublicKeySize = HalfSize * 2;
> > > > > +
> > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > +  if (EcPoint == NULL) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  RetVal = FALSE;
> > > > > +  BnX    = BN_new ();
> > > > > +  BnY    = BN_new ();
> > > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> NULL) != 1) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  XSize = BN_num_bytes (BnX);
> > > > > +  YSize = BN_num_bytes (BnY);
> > > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > +
> > > > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > +
> > > > > +  RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > +  BN_free (BnX);
> > > > > +  BN_free (BnY);
> > > > > +  return RetVal;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Gets the public key component from the established EC context.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > +  generate key pair from EcGenerateKey().
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  EC_KEY          *EcKey;
> > > > > +  CONST EC_GROUP  *Group;
> > > > > +  CONST EC_POINT  *EcPoint;
> > > > > +  BIGNUM          *BnX;
> > > > > +  BIGNUM          *BnY;
> > > > > +  UINTN           HalfSize;
> > > > > +  INTN            XSize;
> > > > > +  INTN            YSize;
> > > > > +  BOOLEAN         RetVal;
> > > > > +
> > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > > +    *PublicKeySize = HalfSize * 2;
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  *PublicKeySize = HalfSize * 2;
> > > > > +
> > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > +  if (EcPoint == NULL) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  RetVal = FALSE;
> > > > > +  BnX    = BN_new ();
> > > > > +  BnY    = BN_new ();
> > > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> NULL) != 1) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  XSize = BN_num_bytes (BnX);
> > > > > +  YSize = BN_num_bytes (BnY);
> > > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > +
> > > > > +  if (PublicKey != NULL) {
> > > > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > +  }
> > > > > +
> > > > > +  RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > +  BN_free (BnX);
> > > > > +  BN_free (BnY);
> > > > > +  return RetVal;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Computes exchanged common key.
> > > > > +  Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > +  based on its own context including value of curve parameter and
> random secret.
> > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > +  If public key is compressed, the PeerPublic will only contain half
> key (X).
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > +  If Key is NULL, then return FALSE.
> > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> compressed or not.
> > > > > +  @param[out]      Key                Pointer to the buffer to receive
> generated key.
> > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> bytes.
> > > > > +                                      On output, the size of data returned in Key
> buffer in bytes.
> > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > +  IN OUT  VOID         *EcContext,
> > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > +  IN      UINTN        PeerPublicSize,
> > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > +  OUT     UINT8        *Key,
> > > > > +  IN OUT  UINTN        *KeySize
> > > > > +  )
> > > > > +{
> > > > > +  EC_KEY          *EcKey;
> > > > > +  EC_KEY          *PeerEcKey;
> > > > > +  CONST EC_GROUP  *Group;
> > > > > +  BOOLEAN         RetVal;
> > > > > +  BIGNUM          *BnX;
> > > > > +  BIGNUM          *BnY;
> > > > > +  EC_POINT        *Point;
> > > > > +  INT32           OpenSslNid;
> > > > > +  UINTN           HalfSize;
> > > > > +
> > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> NULL)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if (PeerPublicSize > INT_MAX) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  if (*KeySize < HalfSize) {
> > > > > +    *KeySize = HalfSize;
> > > > > +    return FALSE;
> > > > > +  }
> > > > > +
> > > > > +  *KeySize = HalfSize;
> > > > > +
> > > > > +  RetVal    = FALSE;
> > > > > +  Point     = NULL;
> > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > +  BnY       = NULL;
> > > > > +  Point     = EC_POINT_new (Group);
> > > > > +  PeerEcKey = NULL;
> > > > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (CompressFlag == NULL) {
> > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > +    if (BnY == NULL) {
> > > > > +      goto fail;
> > > > > +    }
> > > > > +
> > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> NULL) != 1) {
> > > > > +      goto fail;
> > > > > +    }
> > > > > +  } else {
> > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> *CompressFlag, NULL) != 1) {
> > > > > +      goto fail;
> > > > > +    }
> > > > > +  }
> > > > > +
> > > > > +  // Validate NIST ECDH public key
> > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > +  if (PeerEcKey == NULL) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > +    goto fail;
> > > > > +  }
> > > > > +
> > > > > +  RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > +  BN_free (BnX);
> > > > > +  BN_free (BnY);
> > > > > +  EC_POINT_free (Point);
> > > > > +  EC_KEY_free (PeerEcKey);
> > > > > +  return RetVal;
> > > > > +}
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > new file mode 100644
> > > > > index 0000000000..d9f1004f6c
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > @@ -0,0 +1,496 @@
> > > > > +/** @file
> > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include <Library/BaseCryptLib.h>
> > > > > +#include <Library/DebugLib.h>
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > +  and is used for calculation within this group. This object should be
> freed
> > > > > +  using EcGroupFree() function.
> > > > > +
> > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> (Defined in
> > > > > +                          BaseCryptLib.h).
> > > > > +
> > > > > +  @retval EcGroup object  On success.
> > > > > +  @retval NULL            On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > +  IN UINTN  CryptoNid
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > +  This function will set the provided Big Number objects  to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[out] BnPrime    Group prime number.
> > > > > +  @param[out] BnA        A coefficient.
> > > > > +  @param[out] BnB        B coefficient..
> > > > > +  @param[in]  BnCtx      BN context.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *BnPrime,
> > > > > +  OUT VOID       *BnA,
> > > > > +  OUT VOID       *BnB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC group order.
> > > > > +  This function will set the provided Big Number object to the
> corresponding
> > > > > +  value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > +  is properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[out] BnOrder   Group prime number.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > +  IN VOID   *EcGroup,
> > > > > +  OUT VOID  *BnOrder
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > +  IN VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > +  within the given EC group (curve).
> > > > > +
> > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > +  @retval EC Point object  On success.
> > > > > +  @retval NULL             On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > +  IN CONST VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > +  IN VOID     *EcPoint,
> > > > > +  IN BOOLEAN  Clear
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC point affine (x,y) coordinates.
> > > > > +  This function will set the provided Big Number objects to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[out] BnX        X coordinate.
> > > > > +  @param[out] BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  OUT VOID       *BnX,
> > > > > +  OUT VOID       *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN CONST VOID  *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPointA         EC Point.
> > > > > +  @param[in]  EcPointB         EC Point.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPoint          EC Point.
> > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN CONST VOID  *BnPScalar,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > +  @param[in]     EcGroup   EC group object.
> > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > +  @param[in]     BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN OUT VOID    *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is on EC curve.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On curve.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is at infinity.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +
> > > > > +  @retval TRUE          At infinity.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if EC points are equal.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPointA  EC point A.
> > > > > +  @param[in]  EcPointB  EC point B.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          A == B.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > +  their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > +  such that the point is on the curve there will only ever be two
> possible
> > > > > +  values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > +  possible values for y should be used.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC Point.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN UINT8       YBit,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > +  with the NID.
> > > > > +
> > > > > +  @param[in]  Nid cipher NID
> > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > +  IN UINTN  Nid
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Release the specified EC context.
> > > > > +
> > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > +  IN  VOID  *EcContext
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > +  pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > +  function was properly called before.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > +  This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > +  returned via parameter Public, PublicSize.
> > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > +  EC context is updated accordingly.
> > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Gets the public key component from the established EC context.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > +  generate key pair from EcGenerateKey().
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Computes exchanged common key.
> > > > > +  Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > +  based on its own context including value of curve parameter and
> random secret.
> > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > +  If Key is NULL, then return FALSE.
> > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> compressed or not.
> > > > > +  @param[out]      Key                Pointer to the buffer to receive
> generated key.
> > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> bytes.
> > > > > +                                      On output, the size of data returned in Key
> buffer in bytes.
> > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > +  IN OUT  VOID         *EcContext,
> > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > +  IN      UINTN        PeerPublicSize,
> > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > +  OUT     UINT8        *Key,
> > > > > +  IN OUT  UINTN        *KeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > index ce6a789dfd..4bc3063485 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > @@ -59,6 +59,7 @@
> > > > >    Pk/CryptTsNull.c
> > > > >    Pk/CryptRsaPss.c
> > > > >    Pk/CryptRsaPssSignNull.c
> > > > > +  Pk/CryptEcNull.c
> > > > >    Pem/CryptPem.c
> > > > >    Bn/CryptBnNull.c
> > > > >
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > @@ -49,6 +49,7 @@
> > > > >    Pk/CryptX509Null.c
> > > > >    Pk/CryptAuthenticodeNull.c
> > > > >    Pk/CryptTsNull.c
> > > > > +  Pk/CryptEcNull.c
> > > > >    Pem/CryptPemNull.c
> > > > >    Rand/CryptRandNull.c
> > > > >    Pk/CryptRsaPssNull.c
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > new file mode 100644
> > > > > index 0000000000..d9f1004f6c
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > @@ -0,0 +1,496 @@
> > > > > +/** @file
> > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include <Library/BaseCryptLib.h>
> > > > > +#include <Library/DebugLib.h>
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > +  and is used for calculation within this group. This object should be
> freed
> > > > > +  using EcGroupFree() function.
> > > > > +
> > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> (Defined in
> > > > > +                          BaseCryptLib.h).
> > > > > +
> > > > > +  @retval EcGroup object  On success.
> > > > > +  @retval NULL            On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > +  IN UINTN  CryptoNid
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > +  This function will set the provided Big Number objects  to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[out] BnPrime    Group prime number.
> > > > > +  @param[out] BnA        A coefficient.
> > > > > +  @param[out] BnB        B coefficient..
> > > > > +  @param[in]  BnCtx      BN context.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *BnPrime,
> > > > > +  OUT VOID       *BnA,
> > > > > +  OUT VOID       *BnB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC group order.
> > > > > +  This function will set the provided Big Number object to the
> corresponding
> > > > > +  value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > +  is properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[out] BnOrder   Group prime number.
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > +  IN VOID   *EcGroup,
> > > > > +  OUT VOID  *BnOrder
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > +  IN VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > +  within the given EC group (curve).
> > > > > +
> > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > +  @retval EC Point object  On success.
> > > > > +  @retval NULL             On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > +  IN CONST VOID  *EcGroup
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > +  IN VOID     *EcPoint,
> > > > > +  IN BOOLEAN  Clear
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Get EC point affine (x,y) coordinates.
> > > > > +  This function will set the provided Big Number objects to the
> corresponding
> > > > > +  values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > +  are properly initialized.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[out] BnX        X coordinate.
> > > > > +  @param[out] BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  OUT VOID       *BnX,
> > > > > +  OUT VOID       *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC point object.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  BnY        Y coordinate.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN CONST VOID  *BnY,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPointA         EC Point.
> > > > > +  @param[in]  EcPointB         EC Point.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > +  @param[in]  EcGroup          EC group object.
> > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> point should
> > > > > +                               be properly initialized.
> > > > > +  @param[in]  EcPoint          EC Point.
> > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > +  @param[in]  BnCtx            BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  OUT VOID       *EcPointResult,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN CONST VOID  *BnPScalar,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > +  @param[in]     EcGroup   EC group object.
> > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > +  @param[in]     BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN OUT VOID    *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is on EC curve.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On curve.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if the supplied point is at infinity.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > +
> > > > > +  @retval TRUE          At infinity.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPoint
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Check if EC points are equal.
> > > > > +
> > > > > +  @param[in]  EcGroup   EC group object.
> > > > > +  @param[in]  EcPointA  EC point A.
> > > > > +  @param[in]  EcPointB  EC point B.
> > > > > +  @param[in]  BnCtx     BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          A == B.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN CONST VOID  *EcPointA,
> > > > > +  IN CONST VOID  *EcPointB,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > +  their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > +  such that the point is on the curve there will only ever be two
> possible
> > > > > +  values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > +  possible values for y should be used.
> > > > > +
> > > > > +  @param[in]  EcGroup    EC group object.
> > > > > +  @param[in]  EcPoint    EC Point.
> > > > > +  @param[in]  BnX        X coordinate.
> > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > +  @param[in]  BnCtx      BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > +  @retval TRUE          On success.
> > > > > +  @retval FALSE         Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > +  IN CONST VOID  *EcGroup,
> > > > > +  IN VOID        *EcPoint,
> > > > > +  IN CONST VOID  *BnX,
> > > > > +  IN UINT8       YBit,
> > > > > +  IN VOID        *BnCtx
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > +  with the NID.
> > > > > +
> > > > > +  @param[in]  Nid cipher NID
> > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > +  IN UINTN  Nid
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Release the specified EC context.
> > > > > +
> > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > +  IN  VOID  *EcContext
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > +  pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > +  function was properly called before.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > +  This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > +  returned via parameter Public, PublicSize.
> > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > +  EC context is updated accordingly.
> > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Gets the public key component from the established EC context.
> > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > +  generate key pair from EcGenerateKey().
> > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> generated public X,Y.
> > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> in bytes.
> > > > > +                                  On output, the size of data returned in Public
> buffer in bytes.
> > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > +  IN OUT  VOID   *EcContext,
> > > > > +  OUT     UINT8  *PublicKey,
> > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  Computes exchanged common key.
> > > > > +  Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > +  based on its own context including value of curve parameter and
> random secret.
> > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > +  If EcContext is NULL, then return FALSE.
> > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > +  If Key is NULL, then return FALSE.
> > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> compressed or not.
> > > > > +  @param[out]      Key                Pointer to the buffer to receive
> generated key.
> > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> bytes.
> > > > > +                                      On output, the size of data returned in Key
> buffer in bytes.
> > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > +  IN OUT  VOID         *EcContext,
> > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > +  IN      UINTN        PeerPublicSize,
> > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > +  OUT     UINT8        *Key,
> > > > > +  IN OUT  UINTN        *KeySize
> > > > > +  )
> > > > > +{
> > > > > +  ASSERT (FALSE);
> > > > > +  return FALSE;
> > > > > +}
> > > > > --
> > > > > 2.31.1.windows.1
> > > > >
> > > > >
> > > > >
> > > > > 
> > > > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-23 22:40                   ` Yao, Jiewen
@ 2022-09-24  2:19                     ` Michael D Kinney
  2022-09-24  3:44                       ` yi1 li
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-24  2:19 UTC (permalink / raw)
  To: Yao, Jiewen, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C, Kinney, Michael D
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

Hi Jiewen,

My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.

    https://edk2.groups.io/g/devel/message/89019

My main concern at this point is how a platform developer knows how to configure these PCDs.

When should PcdOpensslEcEnabled be set to TRUE?  The name of the PCD implies that EC services
are available, but that is not actually true.  It only compiles the EC source files into
the openssl lib.

I think a developer has to enable other features in order to actually make use of the 
content provided by those source files.  Correct?

The other INF that adds the SSL files has the same issue.  How does a developer know when
to use the INF with the SSL files or not.  And what features need to be enabled in order to use
the content added by those SSL files.  

We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.

Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources.  If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources

Example:

gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable   SSL    EC    Description
========================================================  =====  =====  ===========
Sha256.Services.Init                                      FALSE  FALSE
Sha256.Services.Init                                      FALSE   TRUE
Sha256.Services.Init                                       TRUE  FALSE
Sha256.Services.Init                                       TRUE   TRUE

If there is a shorter way to describe the impact at the family level or groups of families, then 
that would be acceptable as well.

I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.  However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs.  This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.

Thanks,

Mike


> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Chen, Christine
> <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo,
> Heng <heng.luo@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> 
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
> 
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
> 
> Or if you have any other idea, please let us know.
> 
> Thank you
> Yao Jiewen
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob
> > C <bob.c.feng@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > #  define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine
> > <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney,
> > Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned.  I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line.  This looks like a significant bug with the PCD
> > expression in an INF file.  This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509  ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > >     EVP_PKEY *pkey;
> > >     EC_KEY *key = NULL;
> > >     //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but  not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > >                                                   EC_POINT *, const BIGNUM *x,
> > >                                                   const BIGNUM *y,
> > >                                                   const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D
> > <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase.  For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed.  From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > >                                    Uncompressed      LZMA Compressed
> > > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE
> > EC=TRUE  Increase
> > > ====  ===============  ========  ========  =======  ========
> > =======  ========
> > > IA32  NONE             CryptoPei    21536    21568                         0 KB
> > > IA32  NONE             CryptoDxe    21632    21696                         0 KB
> > > IA32  NONE             CryptoSmm    22976    23072                         0 KB
> > > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB
> > > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520
> > 401034    113 KB
> > > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517
> > 296022    105 KB
> > > IA32  ALL              CryptoPei   423840   598976    189047   293759    104
> > KB
> > > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113
> > KB
> > > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105
> > KB
> > > X64   NONE             CryptoPei    29632    29664                         0 KB
> > > X64   NONE             CryptoDxe    29792    29792                         0 KB
> > > X64   NONE             CryptoSmm    31296    31296                         0 KB
> > > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB
> > > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436
> > 426596    115 KB
> > > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483
> > 310775    106 KB
> > > X64   ALL              CryptoPei   540384   730240    202494   308467    106
> > KB
> > > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115
> > KB
> > > X64   ALL              CryptoSmm   563648   753696    213488   319644    106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > >       entire FV is compressed, the total size impact is typically the size of a
> > >       single instance of a compressed CryptoLib.  The sizes of the Crypto*
> > modules
> > >       in the table above should be a close approximation of the size impact
> > to a
> > >       single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly
> > <shelly.kishore@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > >         1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael
> > D <michael.d.kinney@intel.com>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > 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>
> > > > > > ---
> > > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++
> > > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +
> > > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
> > > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765
> > ++++++++++++++++++
> > > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++
> > > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
> > > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
> > > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > >  8 files changed, 2186 insertions(+)
> > > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > >  create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > >  create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > >  #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL  0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1  0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1  0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1  0x0206
> > > > > > +
> > > > > >  ///
> > > > > >  /// MD5 digest size in bytes
> > > > > >  ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > >    OUT VOID       *BnRes
> > > > > >    );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +//    Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > +  and is used for calculation within this group. This object should be
> > freed
> > > > > > +  using EcGroupFree() function.
> > > > > > +
> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> > (Defined in
> > > > > > +                          BaseCryptLib.h).
> > > > > > +
> > > > > > +  @retval EcGroup object  On success.
> > > > > > +  @retval NULL            On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > +  IN UINTN  CryptoNid
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > +  This function will set the provided Big Number objects  to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[out] BnPrime    Group prime number.
> > > > > > +  @param[out] BnA        A coefficient.
> > > > > > +  @param[out] BnB        B coefficient.
> > > > > > +  @param[in]  BnCtx      BN context.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *BnPrime,
> > > > > > +  OUT VOID       *BnA,
> > > > > > +  OUT VOID       *BnB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC group order.
> > > > > > +  This function will set the provided Big Number object to the
> > corresponding
> > > > > > +  value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > +  is properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[out] BnOrder   Group prime number.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > +  IN VOID   *EcGroup,
> > > > > > +  OUT VOID  *BnOrder
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > +  IN VOID  *EcGroup
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > +  within the given EC group (curve).
> > > > > > +
> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > +  @retval EC Point object  On success.
> > > > > > +  @retval NULL             On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > +  IN CONST VOID  *EcGroup
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > +  IN VOID     *EcPoint,
> > > > > > +  IN BOOLEAN  Clear
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC point affine (x,y) coordinates.
> > > > > > +  This function will set the provided Big Number objects to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[out] BnX        X coordinate.
> > > > > > +  @param[out] BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  OUT VOID       *BnX,
> > > > > > +  OUT VOID       *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN CONST VOID  *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPointA         EC Point.
> > > > > > +  @param[in]  EcPointB         EC Point.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPoint          EC Point.
> > > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN CONST VOID  *BnPScalar,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > +  @param[in]     EcGroup   EC group object.
> > > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > > +  @param[in]     BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN OUT VOID    *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On curve.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is at infinity.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +
> > > > > > +  @retval TRUE          At infinity.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if EC points are equal.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPointA  EC point A.
> > > > > > +  @param[in]  EcPointB  EC point B.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          A == B.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > +  their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > +  such that the point is on the curve there will only ever be two
> > possible
> > > > > > +  values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > +  possible values for y should be used.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC Point.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN UINT8       YBit,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > +  with the NID.
> > > > > > +
> > > > > > +  @param[in]  Nid cipher NID
> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > +  IN UINTN  Nid
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Release the specified EC context.
> > > > > > +
> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > +  IN  VOID  *EcContext
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > +  pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > +  function was properly called before.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > > +  This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > +  returned via parameter Public, PublicSize.
> > > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > > +  EC context is updated accordingly.
> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Gets the public key component from the established EC context.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > +  generate key pair from EcGenerateKey().
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  );
> > > > > > +
> > > > > > +/**
> > > > > > +  Computes exchanged common key.
> > > > > > +  Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > +  based on its own context including value of curve parameter and
> > random secret.
> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > > +  If Key is NULL, then return FALSE.
> > > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> > compressed or not.
> > > > > > +  @param[out]      Key                Pointer to the buffer to receive
> > generated key.
> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> > bytes.
> > > > > > +                                      On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > +  IN OUT  VOID         *EcContext,
> > > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > > +  IN      UINTN        PeerPublicSize,
> > > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > > +  OUT     UINT8        *Key,
> > > > > > +  IN OUT  UINTN        *KeySize
> > > > > > +  );
> > > > > > +
> > > > > >  #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > >    Pk/CryptTs.c
> > > > > >    Pk/CryptRsaPss.c
> > > > > >    Pk/CryptRsaPssSign.c
> > > > > > +  Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > +  Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here.  The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > >    Pem/CryptPem.c
> > > > > >    Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > >    Pk/CryptTsNull.c
> > > > > >    Pk/CryptRsaPss.c
> > > > > >    Pk/CryptRsaPssSignNull.c
> > > > > > +  Pk/CryptEcNull.c
> > > > > >    Pem/CryptPemNull.c
> > > > > >    Rand/CryptRandNull.c
> > > > > >    Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +//    Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > +  Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> > (Defined in
> > > > > > +                          BaseCryptLib.h).
> > > > > > +
> > > > > > +  @retval !=-1    On success.
> > > > > > +  @retval -1      ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > +  IN UINTN  CryptoNid
> > > > > > +  )
> > > > > > +{
> > > > > > +  INT32  Nid;
> > > > > > +
> > > > > > +  switch (CryptoNid) {
> > > > > > +    case CRYPTO_NID_SECP256R1:
> > > > > > +      Nid = NID_X9_62_prime256v1;
> > > > > > +      break;
> > > > > > +    case CRYPTO_NID_SECP384R1:
> > > > > > +      Nid = NID_secp384r1;
> > > > > > +      break;
> > > > > > +    case CRYPTO_NID_SECP521R1:
> > > > > > +      Nid = NID_secp521r1;
> > > > > > +      break;
> > > > > > +    default:
> > > > > > +      return -1;
> > > > > > +  }
> > > > > > +
> > > > > > +  return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > +  and is used for calculation within this group. This object should be
> > freed
> > > > > > +  using EcGroupFree() function.
> > > > > > +
> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> > (Defined in
> > > > > > +                          BaseCryptLib.h).
> > > > > > +
> > > > > > +  @retval EcGroup object  On success.
> > > > > > +  @retval NULL            On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > +  IN UINTN  CryptoNid
> > > > > > +  )
> > > > > > +{
> > > > > > +  INT32  Nid;
> > > > > > +
> > > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > +  if (Nid < 0) {
> > > > > > +    return NULL;
> > > > > > +  }
> > > > > > +
> > > > > > +  return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > +  This function will set the provided Big Number objects  to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[out] BnPrime    Group prime number.
> > > > > > +  @param[out] BnA        A coefficient.
> > > > > > +  @param[out] BnB        B coefficient..
> > > > > > +  @param[in]  BnCtx      BN context.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *BnPrime,
> > > > > > +  OUT VOID       *BnA,
> > > > > > +  OUT VOID       *BnB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC group order.
> > > > > > +  This function will set the provided Big Number object to the
> > corresponding
> > > > > > +  value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > +  is properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[out] BnOrder   Group prime number.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > +  IN VOID   *EcGroup,
> > > > > > +  OUT VOID  *BnOrder
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > +  IN VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > +  within the given EC group (curve).
> > > > > > +
> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > +  @retval EC Point object  On success.
> > > > > > +  @retval NULL             On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > +  IN CONST VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > +  IN VOID     *EcPoint,
> > > > > > +  IN BOOLEAN  Clear
> > > > > > +  )
> > > > > > +{
> > > > > > +  if (Clear) {
> > > > > > +    EC_POINT_clear_free (EcPoint);
> > > > > > +  } else {
> > > > > > +    EC_POINT_free (EcPoint);
> > > > > > +  }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC point affine (x,y) coordinates.
> > > > > > +  This function will set the provided Big Number objects to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[out] BnX        X coordinate.
> > > > > > +  @param[out] BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  OUT VOID       *BnX,
> > > > > > +  OUT VOID       *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN CONST VOID  *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPointA         EC Point.
> > > > > > +  @param[in]  EcPointB         EC Point.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPoint          EC Point.
> > > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN CONST VOID  *BnPScalar,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > +  @param[in]     EcGroup   EC group object.
> > > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > > +  @param[in]     BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN OUT VOID    *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On curve.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is at infinity.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +
> > > > > > +  @retval TRUE          At infinity.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint
> > > > > > +  )
> > > > > > +{
> > > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if EC points are equal.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPointA  EC point A.
> > > > > > +  @param[in]  EcPointB  EC point B.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          A == B.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > +  their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > +  such that the point is on the curve there will only ever be two
> > possible
> > > > > > +  values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > +  possible values for y should be used.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC Point.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN UINT8       YBit,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +//    Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > +  with the NID.
> > > > > > +
> > > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined
> > in
> > > > > > +                    BaseCryptLib.h).
> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > +  IN UINTN  Nid
> > > > > > +  )
> > > > > > +{
> > > > > > +  INT32  OpenSslNid;
> > > > > > +
> > > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > +  if (OpenSslNid < 0) {
> > > > > > +    return NULL;
> > > > > > +  }
> > > > > > +
> > > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Release the specified EC context.
> > > > > > +
> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > +  IN  VOID  *EcContext
> > > > > > +  )
> > > > > > +{
> > > > > > +  EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > +  pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > +  function was properly called before.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > > +  This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > +  returned via parameter Public, PublicSize.
> > > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > > +  EC context is updated accordingly.
> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  EC_KEY          *EcKey;
> > > > > > +  CONST EC_GROUP  *Group;
> > > > > > +  CONST EC_POINT  *EcPoint;
> > > > > > +  BOOLEAN         RetVal;
> > > > > > +  BIGNUM          *BnX;
> > > > > > +  BIGNUM          *BnY;
> > > > > > +  UINTN           HalfSize;
> > > > > > +  INTN            XSize;
> > > > > > +  INTN            YSize;
> > > > > > +
> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > +  // Assume RAND_seed was called
> > > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > > > +    *PublicKeySize = HalfSize * 2;
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > +  if (EcPoint == NULL) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  RetVal = FALSE;
> > > > > > +  BnX    = BN_new ();
> > > > > > +  BnY    = BN_new ();
> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  XSize = BN_num_bytes (BnX);
> > > > > > +  YSize = BN_num_bytes (BnY);
> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > +  ZeroMem (PublicKey, *PublicKeySize);
> > > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > +  RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > +  BN_free (BnX);
> > > > > > +  BN_free (BnY);
> > > > > > +  return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Gets the public key component from the established EC context.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > +  generate key pair from EcGenerateKey().
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  EC_KEY          *EcKey;
> > > > > > +  CONST EC_GROUP  *Group;
> > > > > > +  CONST EC_POINT  *EcPoint;
> > > > > > +  BIGNUM          *BnX;
> > > > > > +  BIGNUM          *BnY;
> > > > > > +  UINTN           HalfSize;
> > > > > > +  INTN            XSize;
> > > > > > +  INTN            YSize;
> > > > > > +  BOOLEAN         RetVal;
> > > > > > +
> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +  if (*PublicKeySize < HalfSize * 2) {
> > > > > > +    *PublicKeySize = HalfSize * 2;
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > +  if (EcPoint == NULL) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  RetVal = FALSE;
> > > > > > +  BnX    = BN_new ();
> > > > > > +  BnY    = BN_new ();
> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  XSize = BN_num_bytes (BnX);
> > > > > > +  YSize = BN_num_bytes (BnY);
> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > +  if (PublicKey != NULL) {
> > > > > > +    ZeroMem (PublicKey, *PublicKeySize);
> > > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +  }
> > > > > > +
> > > > > > +  RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > +  BN_free (BnX);
> > > > > > +  BN_free (BnY);
> > > > > > +  return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Computes exchanged common key.
> > > > > > +  Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > +  based on its own context including value of curve parameter and
> > random secret.
> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > +  If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > > +  If Key is NULL, then return FALSE.
> > > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> > compressed or not.
> > > > > > +  @param[out]      Key                Pointer to the buffer to receive
> > generated key.
> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> > bytes.
> > > > > > +                                      On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > +  IN OUT  VOID         *EcContext,
> > > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > > +  IN      UINTN        PeerPublicSize,
> > > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > > +  OUT     UINT8        *Key,
> > > > > > +  IN OUT  UINTN        *KeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  EC_KEY          *EcKey;
> > > > > > +  EC_KEY          *PeerEcKey;
> > > > > > +  CONST EC_GROUP  *Group;
> > > > > > +  BOOLEAN         RetVal;
> > > > > > +  BIGNUM          *BnX;
> > > > > > +  BIGNUM          *BnY;
> > > > > > +  EC_POINT        *Point;
> > > > > > +  INT32           OpenSslNid;
> > > > > > +  UINTN           HalfSize;
> > > > > > +
> > > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (PeerPublicSize > INT_MAX) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  EcKey    = (EC_KEY *)EcContext;
> > > > > > +  Group    = EC_KEY_get0_group (EcKey);
> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (*KeySize < HalfSize) {
> > > > > > +    *KeySize = HalfSize;
> > > > > > +    return FALSE;
> > > > > > +  }
> > > > > > +
> > > > > > +  *KeySize = HalfSize;
> > > > > > +
> > > > > > +  RetVal    = FALSE;
> > > > > > +  Point     = NULL;
> > > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > +  BnY       = NULL;
> > > > > > +  Point     = EC_POINT_new (Group);
> > > > > > +  PeerEcKey = NULL;
> > > > > > +  if ((BnX == NULL) || (Point == NULL)) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (CompressFlag == NULL) {
> > > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > +    if (BnY == NULL) {
> > > > > > +      goto fail;
> > > > > > +    }
> > > > > > +
> > > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > +      goto fail;
> > > > > > +    }
> > > > > > +  } else {
> > > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > +      goto fail;
> > > > > > +    }
> > > > > > +  }
> > > > > > +
> > > > > > +  // Validate NIST ECDH public key
> > > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +  if (PeerEcKey == NULL) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > +    goto fail;
> > > > > > +  }
> > > > > > +
> > > > > > +  RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > +  BN_free (BnX);
> > > > > > +  BN_free (BnY);
> > > > > > +  EC_POINT_free (Point);
> > > > > > +  EC_KEY_free (PeerEcKey);
> > > > > > +  return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > +  and is used for calculation within this group. This object should be
> > freed
> > > > > > +  using EcGroupFree() function.
> > > > > > +
> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> > (Defined in
> > > > > > +                          BaseCryptLib.h).
> > > > > > +
> > > > > > +  @retval EcGroup object  On success.
> > > > > > +  @retval NULL            On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > +  IN UINTN  CryptoNid
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > +  This function will set the provided Big Number objects  to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[out] BnPrime    Group prime number.
> > > > > > +  @param[out] BnA        A coefficient.
> > > > > > +  @param[out] BnB        B coefficient..
> > > > > > +  @param[in]  BnCtx      BN context.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *BnPrime,
> > > > > > +  OUT VOID       *BnA,
> > > > > > +  OUT VOID       *BnB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC group order.
> > > > > > +  This function will set the provided Big Number object to the
> > corresponding
> > > > > > +  value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > +  is properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[out] BnOrder   Group prime number.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > +  IN VOID   *EcGroup,
> > > > > > +  OUT VOID  *BnOrder
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > +  IN VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > +  within the given EC group (curve).
> > > > > > +
> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > +  @retval EC Point object  On success.
> > > > > > +  @retval NULL             On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > +  IN CONST VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > +  IN VOID     *EcPoint,
> > > > > > +  IN BOOLEAN  Clear
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC point affine (x,y) coordinates.
> > > > > > +  This function will set the provided Big Number objects to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[out] BnX        X coordinate.
> > > > > > +  @param[out] BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  OUT VOID       *BnX,
> > > > > > +  OUT VOID       *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN CONST VOID  *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPointA         EC Point.
> > > > > > +  @param[in]  EcPointB         EC Point.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPoint          EC Point.
> > > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN CONST VOID  *BnPScalar,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > +  @param[in]     EcGroup   EC group object.
> > > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > > +  @param[in]     BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN OUT VOID    *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On curve.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is at infinity.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +
> > > > > > +  @retval TRUE          At infinity.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if EC points are equal.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPointA  EC point A.
> > > > > > +  @param[in]  EcPointB  EC point B.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          A == B.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > +  their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > +  such that the point is on the curve there will only ever be two
> > possible
> > > > > > +  values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > +  possible values for y should be used.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC Point.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN UINT8       YBit,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > +  with the NID.
> > > > > > +
> > > > > > +  @param[in]  Nid cipher NID
> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > +  IN UINTN  Nid
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Release the specified EC context.
> > > > > > +
> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > +  IN  VOID  *EcContext
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > +  pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > +  function was properly called before.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > > +  This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > +  returned via parameter Public, PublicSize.
> > > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > > +  EC context is updated accordingly.
> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Gets the public key component from the established EC context.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > +  generate key pair from EcGenerateKey().
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Computes exchanged common key.
> > > > > > +  Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > +  based on its own context including value of curve parameter and
> > random secret.
> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > > +  If Key is NULL, then return FALSE.
> > > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> > compressed or not.
> > > > > > +  @param[out]      Key                Pointer to the buffer to receive
> > generated key.
> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> > bytes.
> > > > > > +                                      On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > +  IN OUT  VOID         *EcContext,
> > > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > > +  IN      UINTN        PeerPublicSize,
> > > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > > +  OUT     UINT8        *Key,
> > > > > > +  IN OUT  UINTN        *KeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > >    Pk/CryptTsNull.c
> > > > > >    Pk/CryptRsaPss.c
> > > > > >    Pk/CryptRsaPssSignNull.c
> > > > > > +  Pk/CryptEcNull.c
> > > > > >    Pem/CryptPem.c
> > > > > >    Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > >    Pk/CryptX509Null.c
> > > > > >    Pk/CryptAuthenticodeNull.c
> > > > > >    Pk/CryptTsNull.c
> > > > > > +  Pk/CryptEcNull.c
> > > > > >    Pem/CryptPemNull.c
> > > > > >    Rand/CryptRandNull.c
> > > > > >    Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > +  and is used for calculation within this group. This object should be
> > freed
> > > > > > +  using EcGroupFree() function.
> > > > > > +
> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve
> > (Defined in
> > > > > > +                          BaseCryptLib.h).
> > > > > > +
> > > > > > +  @retval EcGroup object  On success.
> > > > > > +  @retval NULL            On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > +  IN UINTN  CryptoNid
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > +  This function will set the provided Big Number objects  to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[out] BnPrime    Group prime number.
> > > > > > +  @param[out] BnA        A coefficient.
> > > > > > +  @param[out] BnB        B coefficient..
> > > > > > +  @param[in]  BnCtx      BN context.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *BnPrime,
> > > > > > +  OUT VOID       *BnA,
> > > > > > +  OUT VOID       *BnB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC group order.
> > > > > > +  This function will set the provided Big Number object to the
> > corresponding
> > > > > > +  value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > +  is properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[out] BnOrder   Group prime number.
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > +  IN VOID   *EcGroup,
> > > > > > +  OUT VOID  *BnOrder
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > +  IN VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > +  within the given EC group (curve).
> > > > > > +
> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > +  @retval EC Point object  On success.
> > > > > > +  @retval NULL             On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > +  IN CONST VOID  *EcGroup
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > +  @param[in]  EcPoint   EC Point to free.
> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > +  IN VOID     *EcPoint,
> > > > > > +  IN BOOLEAN  Clear
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Get EC point affine (x,y) coordinates.
> > > > > > +  This function will set the provided Big Number objects to the
> > corresponding
> > > > > > +  values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > +  are properly initialized.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[out] BnX        X coordinate.
> > > > > > +  @param[out] BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  OUT VOID       *BnX,
> > > > > > +  OUT VOID       *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC point object.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  BnY        Y coordinate.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN CONST VOID  *BnY,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPointA         EC Point.
> > > > > > +  @param[in]  EcPointB         EC Point.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > +  @param[in]  EcGroup          EC group object.
> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The
> > point should
> > > > > > +                               be properly initialized.
> > > > > > +  @param[in]  EcPoint          EC Point.
> > > > > > +  @param[in]  BnPScalar        P Scalar.
> > > > > > +  @param[in]  BnCtx            BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  OUT VOID       *EcPointResult,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN CONST VOID  *BnPScalar,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > +  @param[in]     EcGroup   EC group object.
> > > > > > +  @param[in,out] EcPoint   EC point to invert.
> > > > > > +  @param[in]     BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN OUT VOID    *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On curve.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if the supplied point is at infinity.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPoint   EC point to check.
> > > > > > +
> > > > > > +  @retval TRUE          At infinity.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPoint
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Check if EC points are equal.
> > > > > > +
> > > > > > +  @param[in]  EcGroup   EC group object.
> > > > > > +  @param[in]  EcPointA  EC point A.
> > > > > > +  @param[in]  EcPointB  EC point B.
> > > > > > +  @param[in]  BnCtx     BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          A == B.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN CONST VOID  *EcPointA,
> > > > > > +  IN CONST VOID  *EcPointB,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > +  their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > +  such that the point is on the curve there will only ever be two
> > possible
> > > > > > +  values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > +  possible values for y should be used.
> > > > > > +
> > > > > > +  @param[in]  EcGroup    EC group object.
> > > > > > +  @param[in]  EcPoint    EC Point.
> > > > > > +  @param[in]  BnX        X coordinate.
> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.
> > > > > > +  @param[in]  BnCtx      BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > +  @retval TRUE          On success.
> > > > > > +  @retval FALSE         Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > +  IN CONST VOID  *EcGroup,
> > > > > > +  IN VOID        *EcPoint,
> > > > > > +  IN CONST VOID  *BnX,
> > > > > > +  IN UINT8       YBit,
> > > > > > +  IN VOID        *BnCtx
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > +  with the NID.
> > > > > > +
> > > > > > +  @param[in]  Nid cipher NID
> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > +  IN UINTN  Nid
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Release the specified EC context.
> > > > > > +
> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > +  IN  VOID  *EcContext
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > +  pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > +  function was properly called before.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.
> > > > > > +  This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > +  returned via parameter Public, PublicSize.
> > > > > > +  X is the first half of Public with size being PublicSize / 2,
> > > > > > +  Y is the second half of Public with size being PublicSize / 2.
> > > > > > +  EC context is updated accordingly.
> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PublicSize is NULL, then return FALSE.
> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.
> > > > > > +  @retval FALSE  EC public X,Y generation failed.
> > > > > > +  @retval FALSE  PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Gets the public key component from the established EC context.
> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > +  generate key pair from EcGenerateKey().
> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.
> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer
> > in bytes.
> > > > > > +                                  On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.
> > > > > > +  @retval  FALSE  Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > +  IN OUT  VOID   *EcContext,
> > > > > > +  OUT     UINT8  *PublicKey,
> > > > > > +  IN OUT  UINTN  *PublicKeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > +  Computes exchanged common key.
> > > > > > +  Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > +  based on its own context including value of curve parameter and
> > random secret.
> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > +  If EcContext is NULL, then return FALSE.
> > > > > > +  If PeerPublic is NULL, then return FALSE.
> > > > > > +  If PeerPublicSize is 0, then return FALSE.
> > > > > > +  If Key is NULL, then return FALSE.
> > > > > > +  If KeySize is not large enough, then return FALSE.
> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.
> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is
> > compressed or not.
> > > > > > +  @param[out]      Key                Pointer to the buffer to receive
> > generated key.
> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in
> > bytes.
> > > > > > +                                      On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.
> > > > > > +  @retval FALSE  EC exchanged key generation failed.
> > > > > > +  @retval FALSE  KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > +  IN OUT  VOID         *EcContext,
> > > > > > +  IN      CONST UINT8  *PeerPublic,
> > > > > > +  IN      UINTN        PeerPublicSize,
> > > > > > +  IN      CONST INT32  *CompressFlag,
> > > > > > +  OUT     UINT8        *Key,
> > > > > > +  IN OUT  UINTN        *KeySize
> > > > > > +  )
> > > > > > +{
> > > > > > +  ASSERT (FALSE);
> > > > > > +  return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > > 
> > > > > >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-24  2:19                     ` Michael D Kinney
@ 2022-09-24  3:44                       ` yi1 li
  2022-09-24 10:21                         ` Yao, Jiewen
  0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-24  3:44 UTC (permalink / raw)
  To: Kinney, Michael D, Yao, Jiewen, devel@edk2.groups.io,
	Chen, Christine, Feng, Bob C
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

[-- Attachment #1: Type: text/plain, Size: 126172 bytes --]

Hi Mike,

My bad missed this feedback ☹, this important issue should be discussed as early as possible.



The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs

additional information about the source files config PCD to ensure that the service is enabled properly.

We can add the following table to the DSC file for reference.



################################################################################

#

# Openssl Source Config Table

#

################################################################################

# Note: To ensure crypto services are properly enabled, platform requires:

#       1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family

#          to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,

#          OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X

#          to TRUE if only function X of Services XX needed.

#       2. To optimize Crypto Driver binary size, source files of some crypto

#          services have been set to conditional. Additional PCD in below table should

#          be set to TRUE.

#===============================================================================

#|  Crypto Service  |                     Additional PCD                       |

#===============================================================================

#|TlsSet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|TlsGet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|Ec                | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled          |

#===============================================================================



Welcome basetools to provide better ways to optimize the use of PCD,

but from the previous discussion it seems to take quite a long time,

do you think we can merge the current patch first and then optimize it?



Thanks,

Yi



-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support



Hi Jiewen,



My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.



    https://edk2.groups.io/g/devel/message/89019



My main concern at this point is how a platform developer knows how to configure these PCDs.



When should PcdOpensslEcEnabled be set to TRUE?  The name of the PCD implies that EC services

are available, but that is not actually true.  It only compiles the EC source files into

the openssl lib.



I think a developer has to enable other features in order to actually make use of the

content provided by those source files.  Correct?



The other INF that adds the SSL files has the same issue.  How does a developer know when

to use the INF with the SSL files or not.  And what features need to be enabled in order to use

the content added by those SSL files.



We have a number of services in the BaseCryptLib that can be enabled and disabled using

the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.



Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable

and if the service is impacted by the inclusion of the ssl sources and/or the ec sources.  If there is an impact,

then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources



Example:



gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable   SSL    EC    Description

========================================================  =====  =====  ===========

Sha256.Services.Init                                      FALSE  FALSE

Sha256.Services.Init                                      FALSE   TRUE

Sha256.Services.Init                                       TRUE  FALSE

Sha256.Services.Init                                       TRUE   TRUE



If there is a shorter way to describe the impact at the family level or groups of families, then

that would be acceptable as well.



I would prefer the ssl and ec sources from openssl be added/removed based on settings

in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.  However, the feature

flag expressions supported in INF files today do not support use of fields from

structured PCDs.  This needs to be discuss with the BaseTools owners to see if this

would be difficult to support or not.



Thanks,



Mike





> -----Original Message-----

> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>

> Sent: Friday, September 23, 2022 3:40 PM

> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,

> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

>

> Hi Mike

> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.

>

> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do

> enhancement for PCD related stuff later?

>

> Or if you have any other idea, please let us know.

>

> Thank you

> Yao Jiewen

>

> > -----Original Message-----

> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > Sent: Friday, September 23, 2022 3:09 PM

> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob

> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Mike,

> >

> > I did make some attempts with it, but it doesn't work, two troubles here:

> >

> > Bob and Yuwei, please point out if I'm wrong:

> > 1. Using member of structure PCD in INF isn’t supported by Basetools

> > currently,

> > At least it cannot be used as FeatureFlag Expression.

> >

> > 2. As far as I know, structure PCD actually is a const array in code,

> > I afraid it will not work fine with precompile but we do have this need:

> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)

> > # ifndef OPENSSL_NO_EC

> > #  define OPENSSL_NO_EC

> > # endif

> > #endif

> >

> > This is really caused by the bad structure of openssl,

> > maybe we use more detailed comments to remind developers to sync the

> > two PCDs?

> >

> > Thanks,

> > Yi

> >

> > -----Original Message-----

> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Sent: Friday, September 23, 2022 1:25 PM

> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,

> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Yi,

> >

> > I agree there are some complex interactions in the opensll sources.

> >

> > Since you are defining a family for EC, can we use the EC Family != 0 instead

> > of

> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

> >

> > I want to make sure developers do not run into strange build failures if

> > they do not keep the 2 different PCDs aligned.  I prefer a single PCD

> > setting to enable use of EC services.

> >

> > I also noticed that the use of a PCD expression in an INF to select source

> > files does not work if the PCD value is specified with the --pcd flag on

> > the build command line.  This looks like a significant bug with the PCD

> > expression in an INF file.  This also needs to be fixed.

> >

> > Mike

> >

> > > -----Original Message-----

> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > Sent: Thursday, September 22, 2022 8:02 PM

> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Mike,

> > >

> > > 1. Yes, it matches.

> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please

> > refer to another internal email.

> > >

> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS

> > PEM X509  ...

> > >

> > > If we added EC source to OpensslLib.inf and disabled macro

> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary

> > > size,

> > > This an example from x509/x_pubkey.c , other modules is similar:

> > > #ifndef OPENSSL_NO_EC

> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long

> > length)

> > > {

> > >     EVP_PKEY *pkey;

> > >     EC_KEY *key = NULL;

> > >     //.... call EC functions

> > > }

> > > #endif

> > >

> > > If we added EC source to OpensslLib.inf and enable macro

> > OPENSSL_NO_EC, EC module will throw build error,

> > > Since some EC internal APIs or structs have been disabled by

> > OPENSSL_NO_EC but  not another.

> > > This an example from ec/ec_local.h , other error is similar:

> > >

> > > #ifndef OPENSSL_NO_EC

> > > typedef struct ec_group_st EC_GROUP;

> > > typedef struct ec_point_st EC_POINT;

> > > #endif

> > >

> > > // but this function not been enclosed by OPENSSL_NO_EC, and will

> > throw build error

> > >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,

> > >                                                   EC_POINT *, const BIGNUM *x,

> > >                                                   const BIGNUM *y,

> > >                                                   const BIGNUM *z, BN_CTX *);

> > >

> > > To avoid this annoying openssl error, we introduced conditional EC.

> > >

> > > Thanks,

> > > Yi

> > >

> > > -----Original Message-----

> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Sent: Friday, September 23, 2022 6:47 AM

> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D

> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Yi,

> > >

> > > I agree EC is an important feature.

> > >

> > > I did some analysis of the size impact to the CryptoPkg modules on

> > current trunk

> > > with EC on and off. Uncompressed size is important for PEI Phase.  For

> > DXE and

> > > SMM phase, the Crypto services can always be compressed.  From the

> > table below,

> > > building all the EC services in the OpensslLib has no size impact to the

> > NONE

> > > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed

> > DXE/SMM

> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

> > >

> > >                                    Uncompressed      LZMA Compressed

> > > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE

> > EC=TRUE  Increase

> > > ====  ===============  ========  ========  =======  ========

> > =======  ========

> > > IA32  NONE             CryptoPei    21536    21568                         0 KB

> > > IA32  NONE             CryptoDxe    21632    21696                         0 KB

> > > IA32  NONE             CryptoSmm    22976    23072                         0 KB

> > > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520

> > 401034    113 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517

> > 296022    105 KB

> > > IA32  ALL              CryptoPei   423840   598976    189047   293759    104

> > KB

> > > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113

> > KB

> > > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105

> > KB

> > > X64   NONE             CryptoPei    29632    29664                         0 KB

> > > X64   NONE             CryptoDxe    29792    29792                         0 KB

> > > X64   NONE             CryptoSmm    31296    31296                         0 KB

> > > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436

> > 426596    115 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483

> > 310775    106 KB

> > > X64   ALL              CryptoPei   540384   730240    202494   308467    106

> > KB

> > > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115

> > KB

> > > X64   ALL              CryptoSmm   563648   753696    213488   319644    106

> > KB

> > >

> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if

> > the

> > >       entire FV is compressed, the total size impact is typically the size of a

> > >       single instance of a compressed CryptoLib.  The sizes of the Crypto*

> > modules

> > >       in the table above should be a close approximation of the size impact

> > to a

> > >       single FV.

> > >

> > > Does this match your previous size analysis?

> > >

> > > The critical issue to evaluate here is why adding the EC sources to

> > OpensllLib.inf

> > > causes the modules that do not use any EC services to grow by ~105KB.

> > Has any

> > > detailed analysis of the final linked images been performed to see where

> > this

> > > additional size is coming from?

> > >

> > > Thanks,

> > >

> > > Mike

> > >

> > > > -----Original Message-----

> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > Sent: Thursday, September 22, 2022 5:54 AM

> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > Hi Mike,

> > > > I have did some POC that seems existed structured PCD is hard to

> > control binary size,

> > > > Here is the previous discussion for reference.

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679

> > > > https://edk2.groups.io/g/devel/topic/86257810#81814

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446

> > > >

> > > > Anyway EC is an important feature which consumed by vary modern

> > security features such WPA3 , SPDM, TLS1.3 etc.

> > > > Hope it can be added to edk2, and I am glad to take the code and test

> > work if there are other ways to control the size.

> > > >

> > > > Thanks,

> > > > Yi

> > > >

> > > > -----Original Message-----

> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > Sent: Thursday, September 22, 2022 11:56 AM

> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly

> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > That change to OpensslLib.inf should not have been done either.

> > > >

> > > > Looks like this EC feature needs more evaluation to fit into the

> > > > structured PCD control of the lib sizes.

> > > >

> > > > Mike

> > > >

> > > > > -----Original Message-----

> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > Sent: Wednesday, September 21, 2022 7:16 PM

> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Hi Mike,

> > > > > Thanks for review.

> > > > >

> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c

> > will also be compiled and throw build error:

> > > > >

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): error C2220: the following warning is treated

> > > > as

> > > > > an error

> > > > >         1 file(s) copied.

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'

> > > > > undefined; assuming extern returning int

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4047: 'return': 'void *' differs in

> > > > > levels of indirection from 'int'

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(105): warning C4013: 'EC_GROUP_get_curve'

> > > undefined;

> > > > > assuming extern returning int

> > > > >

> > > > > I think the root cause is that we have enabled conditional ec in

> > OpensslLib.inf before by PcdOpensslEcEnabled,

> > > > >

> > > >

> > >

> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934

> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2

> > > > > 02-L238

> > > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.

> > > > > This will save 200+kb memory on platforms which use dxe driver but

> > do not need ec feature.

> > > > >

> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not

> > sure if there is any other way, other better ideas

> > > are

> > > > > welcome.

> > > > >

> > > > > Thanks,

> > > > > Yi

> > > > >

> > > > > -----Original Message-----

> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Sent: Thursday, September 22, 2022 12:22 AM

> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael

> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Comments embedded below.

> > > > >

> > > > > Mike

> > > > >

> > > > > > -----Original Message-----

> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of

> > yi1 li

> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM

> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;

> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1

> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > > >

> > > > > > 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<mailto:jiewen.yao@intel.com>>

> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>

> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>

> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > >

> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > > ---

> > > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++

> > > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +

> > > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +

> > > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765

> > ++++++++++++++++++

> > > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++

> > > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +

> > > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +

> > > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++

> > > > > >  8 files changed, 2186 insertions(+)

> > > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h

> > b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > index b253923dd8..d74fc21c1e 100644

> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > >

> > > > > >  #include <Uefi/UefiBaseType.h>

> > > > > >

> > > > > > +#define CRYPTO_NID_NULL  0x0000

> > > > > > +

> > > > > > +// Key Exchange

> > > > > > +#define CRYPTO_NID_SECP256R1  0x0204

> > > > > > +#define CRYPTO_NID_SECP384R1  0x0205

> > > > > > +#define CRYPTO_NID_SECP521R1  0x0206

> > > > > > +

> > > > > >  ///

> > > > > >  /// MD5 digest size in bytes

> > > > > >  ///

> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (

> > > > > >    OUT VOID       *BnRes

> > > > > >    );

> > > > > >

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient.

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  );

> > > > > > +

> > > > > >  #endif // __BASE_CRYPT_LIB_H__

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > @@ -52,6 +52,8 @@

> > > > > >    Pk/CryptTs.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSign.c

> > > > > > +  Pk/CryptEcNull.c

> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > > > +  Pk/CryptEc.c

> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > >

> > > > > The use of the PCD to select the file should not be needed here.  The

> > > > > Ec Family and individual service enable/disable fields in the

> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is

> > needed to

> > > > > disable the Ec services.

> > > > >

> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should

> > be removed

> > > > > completely as part of this patch series.

> > > > >

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBn.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > index 65ad23fb81..383df2b23c 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > @@ -58,6 +58,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Bn/CryptBnNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..396c819834

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > @@ -0,0 +1,765 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include "InternalCryptLib.h"

> > > > > > +#include <openssl/objects.h>

> > > > > > +#include <openssl/bn.h>

> > > > > > +#include <openssl/ec.h>

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Return the Nid of certain ECC curve.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval !=-1    On success.

> > > > > > +  @retval -1      ECC curve not supported.

> > > > > > +**/

> > > > > > +STATIC

> > > > > > +INT32

> > > > > > +CryptoNidToOpensslNid (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  switch (CryptoNid) {

> > > > > > +    case CRYPTO_NID_SECP256R1:

> > > > > > +      Nid = NID_X9_62_prime256v1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP384R1:

> > > > > > +      Nid = NID_secp384r1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP521R1:

> > > > > > +      Nid = NID_secp521r1;

> > > > > > +      break;

> > > > > > +    default:

> > > > > > +      return -1;

> > > > > > +  }

> > > > > > +

> > > > > > +  return Nid;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);

> > > > > > +

> > > > > > +  if (Nid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return EC_GROUP_new_by_curve_name (Nid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,

> > BnB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,

> > NULL);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_GROUP_free (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_new (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  if (Clear) {

> > > > > > +    EC_POINT_clear_free (EcPoint);

> > > > > > +  } else {

> > > > > > +    EC_POINT_free (EcPoint);

> > > > > > +  }

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,

> > EcPointA, EcPointB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,

> > EcPoint, BnPScalar, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates

> > (EcGroup, EcPoint, BnX, YBit, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined

> > in

> > > > > > +                    BaseCryptLib.h).

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  OpenSslNid;

> > > > > > +

> > > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);

> > > > > > +  if (OpenSslNid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY_free ((EC_KEY *)EcContext);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +

> > > > > > +  // Assume RAND_seed was called

> > > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  if (PublicKey != NULL) {

> > > > > > +    ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If public key is compressed, the PeerPublic will only contain half

> > key (X).

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  EC_KEY          *PeerEcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  EC_POINT        *Point;

> > > > > > +  INT32           OpenSslNid;

> > > > > > +  UINTN           HalfSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==

> > NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((Key == NULL) && (*KeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (PeerPublicSize > INT_MAX) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*KeySize < HalfSize) {

> > > > > > +    *KeySize = HalfSize;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *KeySize = HalfSize;

> > > > > > +

> > > > > > +  RetVal    = FALSE;

> > > > > > +  Point     = NULL;

> > > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);

> > > > > > +  BnY       = NULL;

> > > > > > +  Point     = EC_POINT_new (Group);

> > > > > > +  PeerEcKey = NULL;

> > > > > > +  if ((BnX == NULL) || (Point == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (CompressFlag == NULL) {

> > > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);

> > > > > > +    if (BnY == NULL) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +

> > > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,

> > NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  } else {

> > > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,

> > *CompressFlag, NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  }

> > > > > > +

> > > > > > +  // Validate NIST ECDH public key

> > > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);

> > > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +  if (PeerEcKey == NULL) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  EC_POINT_free (Point);

> > > > > > +  EC_KEY_free (PeerEcKey);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > index ce6a789dfd..4bc3063485 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > @@ -59,6 +59,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBnNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > index 354f3d80aa..e1a57ef09f 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > @@ -49,6 +49,7 @@

> > > > > >    Pk/CryptX509Null.c

> > > > > >    Pk/CryptAuthenticodeNull.c

> > > > > >    Pk/CryptTsNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Pk/CryptRsaPssNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > --

> > > > > > 2.31.1.windows.1

> > > > > >

> > > > > >

> > > > > >

> > > > > > 

> > > > > >



[-- Attachment #2: Type: text/html, Size: 330483 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-24  3:44                       ` yi1 li
@ 2022-09-24 10:21                         ` Yao, Jiewen
  2022-09-24 15:16                           ` Michael D Kinney
  0 siblings, 1 reply; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-24 10:21 UTC (permalink / raw)
  To: Li, Yi1, Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

[-- Attachment #1: Type: text/plain, Size: 128133 bytes --]

Hi Mike
To clarify current situation: We support 3 different use cases:

1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.

2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.

3)  PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.

I think a platform developer should know its configuration and make right choice.

For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.

For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.


Thank you
Yao, Jiewen


From: Li, Yi1 <yi1.li@intel.com>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support


Hi Mike,

My bad missed this feedback ☹, this important issue should be discussed as early as possible.



The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs

additional information about the source files config PCD to ensure that the service is enabled properly.

We can add the following table to the DSC file for reference.



################################################################################

#

# Openssl Source Config Table

#

################################################################################

# Note: To ensure crypto services are properly enabled, platform requires:

#       1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family

#          to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,

#          OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X

#          to TRUE if only function X of Services XX needed.

#       2. To optimize Crypto Driver binary size, source files of some crypto

#          services have been set to conditional. Additional PCD in below table should

#          be set to TRUE.

#===============================================================================

#|  Crypto Service  |                     Additional PCD                       |

#===============================================================================

#|TlsSet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|TlsGet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|Ec                | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled          |

#===============================================================================



Welcome basetools to provide better ways to optimize the use of PCD,

but from the previous discussion it seems to take quite a long time,

do you think we can merge the current patch first and then optimize it?



Thanks,

Yi



-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support



Hi Jiewen,



My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.



    https://edk2.groups.io/g/devel/message/89019



My main concern at this point is how a platform developer knows how to configure these PCDs.



When should PcdOpensslEcEnabled be set to TRUE?  The name of the PCD implies that EC services

are available, but that is not actually true.  It only compiles the EC source files into

the openssl lib.



I think a developer has to enable other features in order to actually make use of the

content provided by those source files.  Correct?



The other INF that adds the SSL files has the same issue.  How does a developer know when

to use the INF with the SSL files or not.  And what features need to be enabled in order to use

the content added by those SSL files.



We have a number of services in the BaseCryptLib that can be enabled and disabled using

the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.



Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable

and if the service is impacted by the inclusion of the ssl sources and/or the ec sources.  If there is an impact,

then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources



Example:



gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable   SSL    EC    Description

========================================================  =====  =====  ===========

Sha256.Services.Init                                      FALSE  FALSE

Sha256.Services.Init                                      FALSE   TRUE

Sha256.Services.Init                                       TRUE  FALSE

Sha256.Services.Init                                       TRUE   TRUE



If there is a shorter way to describe the impact at the family level or groups of families, then

that would be acceptable as well.



I would prefer the ssl and ec sources from openssl be added/removed based on settings

in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.  However, the feature

flag expressions supported in INF files today do not support use of fields from

structured PCDs.  This needs to be discuss with the BaseTools owners to see if this

would be difficult to support or not.



Thanks,



Mike





> -----Original Message-----

> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>

> Sent: Friday, September 23, 2022 3:40 PM

> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,

> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

>

> Hi Mike

> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.

>

> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do

> enhancement for PCD related stuff later?

>

> Or if you have any other idea, please let us know.

>

> Thank you

> Yao Jiewen

>

> > -----Original Message-----

> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > Sent: Friday, September 23, 2022 3:09 PM

> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob

> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Mike,

> >

> > I did make some attempts with it, but it doesn't work, two troubles here:

> >

> > Bob and Yuwei, please point out if I'm wrong:

> > 1. Using member of structure PCD in INF isn’t supported by Basetools

> > currently,

> > At least it cannot be used as FeatureFlag Expression.

> >

> > 2. As far as I know, structure PCD actually is a const array in code,

> > I afraid it will not work fine with precompile but we do have this need:

> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)

> > # ifndef OPENSSL_NO_EC

> > #  define OPENSSL_NO_EC

> > # endif

> > #endif

> >

> > This is really caused by the bad structure of openssl,

> > maybe we use more detailed comments to remind developers to sync the

> > two PCDs?

> >

> > Thanks,

> > Yi

> >

> > -----Original Message-----

> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Sent: Friday, September 23, 2022 1:25 PM

> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,

> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Yi,

> >

> > I agree there are some complex interactions in the opensll sources.

> >

> > Since you are defining a family for EC, can we use the EC Family != 0 instead

> > of

> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

> >

> > I want to make sure developers do not run into strange build failures if

> > they do not keep the 2 different PCDs aligned.  I prefer a single PCD

> > setting to enable use of EC services.

> >

> > I also noticed that the use of a PCD expression in an INF to select source

> > files does not work if the PCD value is specified with the --pcd flag on

> > the build command line.  This looks like a significant bug with the PCD

> > expression in an INF file.  This also needs to be fixed.

> >

> > Mike

> >

> > > -----Original Message-----

> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > Sent: Thursday, September 22, 2022 8:02 PM

> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Mike,

> > >

> > > 1. Yes, it matches.

> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please

> > refer to another internal email.

> > >

> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS

> > PEM X509  ...

> > >

> > > If we added EC source to OpensslLib.inf and disabled macro

> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary

> > > size,

> > > This an example from x509/x_pubkey.c , other modules is similar:

> > > #ifndef OPENSSL_NO_EC

> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long

> > length)

> > > {

> > >     EVP_PKEY *pkey;

> > >     EC_KEY *key = NULL;

> > >     //.... call EC functions

> > > }

> > > #endif

> > >

> > > If we added EC source to OpensslLib.inf and enable macro

> > OPENSSL_NO_EC, EC module will throw build error,

> > > Since some EC internal APIs or structs have been disabled by

> > OPENSSL_NO_EC but  not another.

> > > This an example from ec/ec_local.h , other error is similar:

> > >

> > > #ifndef OPENSSL_NO_EC

> > > typedef struct ec_group_st EC_GROUP;

> > > typedef struct ec_point_st EC_POINT;

> > > #endif

> > >

> > > // but this function not been enclosed by OPENSSL_NO_EC, and will

> > throw build error

> > >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,

> > >                                                   EC_POINT *, const BIGNUM *x,

> > >                                                   const BIGNUM *y,

> > >                                                   const BIGNUM *z, BN_CTX *);

> > >

> > > To avoid this annoying openssl error, we introduced conditional EC.

> > >

> > > Thanks,

> > > Yi

> > >

> > > -----Original Message-----

> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Sent: Friday, September 23, 2022 6:47 AM

> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D

> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Yi,

> > >

> > > I agree EC is an important feature.

> > >

> > > I did some analysis of the size impact to the CryptoPkg modules on

> > current trunk

> > > with EC on and off. Uncompressed size is important for PEI Phase.  For

> > DXE and

> > > SMM phase, the Crypto services can always be compressed.  From the

> > table below,

> > > building all the EC services in the OpensslLib has no size impact to the

> > NONE

> > > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed

> > DXE/SMM

> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

> > >

> > >                                    Uncompressed      LZMA Compressed

> > > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE

> > EC=TRUE  Increase

> > > ====  ===============  ========  ========  =======  ========

> > =======  ========

> > > IA32  NONE             CryptoPei    21536    21568                         0 KB

> > > IA32  NONE             CryptoDxe    21632    21696                         0 KB

> > > IA32  NONE             CryptoSmm    22976    23072                         0 KB

> > > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520

> > 401034    113 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517

> > 296022    105 KB

> > > IA32  ALL              CryptoPei   423840   598976    189047   293759    104

> > KB

> > > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113

> > KB

> > > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105

> > KB

> > > X64   NONE             CryptoPei    29632    29664                         0 KB

> > > X64   NONE             CryptoDxe    29792    29792                         0 KB

> > > X64   NONE             CryptoSmm    31296    31296                         0 KB

> > > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436

> > 426596    115 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483

> > 310775    106 KB

> > > X64   ALL              CryptoPei   540384   730240    202494   308467    106

> > KB

> > > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115

> > KB

> > > X64   ALL              CryptoSmm   563648   753696    213488   319644    106

> > KB

> > >

> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if

> > the

> > >       entire FV is compressed, the total size impact is typically the size of a

> > >       single instance of a compressed CryptoLib.  The sizes of the Crypto*

> > modules

> > >       in the table above should be a close approximation of the size impact

> > to a

> > >       single FV.

> > >

> > > Does this match your previous size analysis?

> > >

> > > The critical issue to evaluate here is why adding the EC sources to

> > OpensllLib.inf

> > > causes the modules that do not use any EC services to grow by ~105KB.

> > Has any

> > > detailed analysis of the final linked images been performed to see where

> > this

> > > additional size is coming from?

> > >

> > > Thanks,

> > >

> > > Mike

> > >

> > > > -----Original Message-----

> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > Sent: Thursday, September 22, 2022 5:54 AM

> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > Hi Mike,

> > > > I have did some POC that seems existed structured PCD is hard to

> > control binary size,

> > > > Here is the previous discussion for reference.

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679

> > > > https://edk2.groups.io/g/devel/topic/86257810#81814

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446

> > > >

> > > > Anyway EC is an important feature which consumed by vary modern

> > security features such WPA3 , SPDM, TLS1.3 etc.

> > > > Hope it can be added to edk2, and I am glad to take the code and test

> > work if there are other ways to control the size.

> > > >

> > > > Thanks,

> > > > Yi

> > > >

> > > > -----Original Message-----

> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > Sent: Thursday, September 22, 2022 11:56 AM

> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly

> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > That change to OpensslLib.inf should not have been done either.

> > > >

> > > > Looks like this EC feature needs more evaluation to fit into the

> > > > structured PCD control of the lib sizes.

> > > >

> > > > Mike

> > > >

> > > > > -----Original Message-----

> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > Sent: Wednesday, September 21, 2022 7:16 PM

> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Hi Mike,

> > > > > Thanks for review.

> > > > >

> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c

> > will also be compiled and throw build error:

> > > > >

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): error C2220: the following warning is treated

> > > > as

> > > > > an error

> > > > >         1 file(s) copied.

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'

> > > > > undefined; assuming extern returning int

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4047: 'return': 'void *' differs in

> > > > > levels of indirection from 'int'

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(105): warning C4013: 'EC_GROUP_get_curve'

> > > undefined;

> > > > > assuming extern returning int

> > > > >

> > > > > I think the root cause is that we have enabled conditional ec in

> > OpensslLib.inf before by PcdOpensslEcEnabled,

> > > > >

> > > >

> > >

> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934

> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2

> > > > > 02-L238

> > > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.

> > > > > This will save 200+kb memory on platforms which use dxe driver but

> > do not need ec feature.

> > > > >

> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not

> > sure if there is any other way, other better ideas

> > > are

> > > > > welcome.

> > > > >

> > > > > Thanks,

> > > > > Yi

> > > > >

> > > > > -----Original Message-----

> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Sent: Thursday, September 22, 2022 12:22 AM

> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael

> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Comments embedded below.

> > > > >

> > > > > Mike

> > > > >

> > > > > > -----Original Message-----

> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of

> > yi1 li

> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM

> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;

> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1

> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > > >

> > > > > > 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<mailto:jiewen.yao@intel.com>>

> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>

> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>

> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > >

> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > > ---

> > > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++

> > > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +

> > > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +

> > > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765

> > ++++++++++++++++++

> > > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++

> > > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +

> > > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +

> > > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++

> > > > > >  8 files changed, 2186 insertions(+)

> > > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h

> > b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > index b253923dd8..d74fc21c1e 100644

> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > >

> > > > > >  #include <Uefi/UefiBaseType.h>

> > > > > >

> > > > > > +#define CRYPTO_NID_NULL  0x0000

> > > > > > +

> > > > > > +// Key Exchange

> > > > > > +#define CRYPTO_NID_SECP256R1  0x0204

> > > > > > +#define CRYPTO_NID_SECP384R1  0x0205

> > > > > > +#define CRYPTO_NID_SECP521R1  0x0206

> > > > > > +

> > > > > >  ///

> > > > > >  /// MD5 digest size in bytes

> > > > > >  ///

> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (

> > > > > >    OUT VOID       *BnRes

> > > > > >    );

> > > > > >

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient.

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  );

> > > > > > +

> > > > > >  #endif // __BASE_CRYPT_LIB_H__

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > @@ -52,6 +52,8 @@

> > > > > >    Pk/CryptTs.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSign.c

> > > > > > +  Pk/CryptEcNull.c

> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > > > +  Pk/CryptEc.c

> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > >

> > > > > The use of the PCD to select the file should not be needed here.  The

> > > > > Ec Family and individual service enable/disable fields in the

> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is

> > needed to

> > > > > disable the Ec services.

> > > > >

> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should

> > be removed

> > > > > completely as part of this patch series.

> > > > >

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBn.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > index 65ad23fb81..383df2b23c 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > @@ -58,6 +58,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Bn/CryptBnNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..396c819834

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > @@ -0,0 +1,765 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include "InternalCryptLib.h"

> > > > > > +#include <openssl/objects.h>

> > > > > > +#include <openssl/bn.h>

> > > > > > +#include <openssl/ec.h>

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Return the Nid of certain ECC curve.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval !=-1    On success.

> > > > > > +  @retval -1      ECC curve not supported.

> > > > > > +**/

> > > > > > +STATIC

> > > > > > +INT32

> > > > > > +CryptoNidToOpensslNid (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  switch (CryptoNid) {

> > > > > > +    case CRYPTO_NID_SECP256R1:

> > > > > > +      Nid = NID_X9_62_prime256v1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP384R1:

> > > > > > +      Nid = NID_secp384r1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP521R1:

> > > > > > +      Nid = NID_secp521r1;

> > > > > > +      break;

> > > > > > +    default:

> > > > > > +      return -1;

> > > > > > +  }

> > > > > > +

> > > > > > +  return Nid;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);

> > > > > > +

> > > > > > +  if (Nid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return EC_GROUP_new_by_curve_name (Nid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,

> > BnB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,

> > NULL);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_GROUP_free (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_new (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  if (Clear) {

> > > > > > +    EC_POINT_clear_free (EcPoint);

> > > > > > +  } else {

> > > > > > +    EC_POINT_free (EcPoint);

> > > > > > +  }

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,

> > EcPointA, EcPointB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,

> > EcPoint, BnPScalar, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates

> > (EcGroup, EcPoint, BnX, YBit, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined

> > in

> > > > > > +                    BaseCryptLib.h).

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  OpenSslNid;

> > > > > > +

> > > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);

> > > > > > +  if (OpenSslNid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY_free ((EC_KEY *)EcContext);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +

> > > > > > +  // Assume RAND_seed was called

> > > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  if (PublicKey != NULL) {

> > > > > > +    ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If public key is compressed, the PeerPublic will only contain half

> > key (X).

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  EC_KEY          *PeerEcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  EC_POINT        *Point;

> > > > > > +  INT32           OpenSslNid;

> > > > > > +  UINTN           HalfSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==

> > NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((Key == NULL) && (*KeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (PeerPublicSize > INT_MAX) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*KeySize < HalfSize) {

> > > > > > +    *KeySize = HalfSize;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *KeySize = HalfSize;

> > > > > > +

> > > > > > +  RetVal    = FALSE;

> > > > > > +  Point     = NULL;

> > > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);

> > > > > > +  BnY       = NULL;

> > > > > > +  Point     = EC_POINT_new (Group);

> > > > > > +  PeerEcKey = NULL;

> > > > > > +  if ((BnX == NULL) || (Point == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (CompressFlag == NULL) {

> > > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);

> > > > > > +    if (BnY == NULL) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +

> > > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,

> > NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  } else {

> > > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,

> > *CompressFlag, NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  }

> > > > > > +

> > > > > > +  // Validate NIST ECDH public key

> > > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);

> > > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +  if (PeerEcKey == NULL) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  EC_POINT_free (Point);

> > > > > > +  EC_KEY_free (PeerEcKey);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > index ce6a789dfd..4bc3063485 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > @@ -59,6 +59,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBnNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > index 354f3d80aa..e1a57ef09f 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > @@ -49,6 +49,7 @@

> > > > > >    Pk/CryptX509Null.c

> > > > > >    Pk/CryptAuthenticodeNull.c

> > > > > >    Pk/CryptTsNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Pk/CryptRsaPssNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > --

> > > > > > 2.31.1.windows.1

> > > > > >

> > > > > >

> > > > > >

> > > > > > 

> > > > > >



[-- Attachment #2: Type: text/html, Size: 334643 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-24 10:21                         ` Yao, Jiewen
@ 2022-09-24 15:16                           ` Michael D Kinney
  2022-09-24 16:03                             ` Yao, Jiewen
  0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-24 15:16 UTC (permalink / raw)
  To: Yao, Jiewen, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C, Kinney, Michael D
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

[-- Attachment #1: Type: text/plain, Size: 129909 bytes --]

Hi Jiewen,

Can you explain interaction with compiling SSL sources or not.  There are 2 INFs a developer has to select from.

Also, just to clarify.  I think you referring to the cyphers available through some of the openssl services.

There is a baseline set of cyphers that were selected for FW use a long time ago.  What is that baseline set?

Building the EC sources extends the set of cyphers available.

Some FW features depend on different sets of cyphers in the CryptLib

Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features.  Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.

I would like to see this documentation added and reviewed as part of the EC patch series.

Thanks,

Mike

From: Yao, Jiewen <jiewen.yao@intel.com>
Sent: Saturday, September 24, 2022 3:22 AM
To: Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Hi Mike
To clarify current situation: We support 3 different use cases:

1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.

2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.

3)  PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.

I think a platform developer should know its configuration and make right choice.

For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.

For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.


Thank you
Yao, Jiewen


From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support


Hi Mike,

My bad missed this feedback ☹, this important issue should be discussed as early as possible.



The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs

additional information about the source files config PCD to ensure that the service is enabled properly.

We can add the following table to the DSC file for reference.



################################################################################

#

# Openssl Source Config Table

#

################################################################################

# Note: To ensure crypto services are properly enabled, platform requires:

#       1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family

#          to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,

#          OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X

#          to TRUE if only function X of Services XX needed.

#       2. To optimize Crypto Driver binary size, source files of some crypto

#          services have been set to conditional. Additional PCD in below table should

#          be set to TRUE.

#===============================================================================

#|  Crypto Service  |                     Additional PCD                       |

#===============================================================================

#|TlsSet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|TlsGet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|Ec                | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled          |

#===============================================================================



Welcome basetools to provide better ways to optimize the use of PCD,

but from the previous discussion it seems to take quite a long time,

do you think we can merge the current patch first and then optimize it?



Thanks,

Yi



-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support



Hi Jiewen,



My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.



    https://edk2.groups.io/g/devel/message/89019



My main concern at this point is how a platform developer knows how to configure these PCDs.



When should PcdOpensslEcEnabled be set to TRUE?  The name of the PCD implies that EC services

are available, but that is not actually true.  It only compiles the EC source files into

the openssl lib.



I think a developer has to enable other features in order to actually make use of the

content provided by those source files.  Correct?



The other INF that adds the SSL files has the same issue.  How does a developer know when

to use the INF with the SSL files or not.  And what features need to be enabled in order to use

the content added by those SSL files.



We have a number of services in the BaseCryptLib that can be enabled and disabled using

the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.



Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable

and if the service is impacted by the inclusion of the ssl sources and/or the ec sources.  If there is an impact,

then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources



Example:



gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable   SSL    EC    Description

========================================================  =====  =====  ===========

Sha256.Services.Init                                      FALSE  FALSE

Sha256.Services.Init                                      FALSE   TRUE

Sha256.Services.Init                                       TRUE  FALSE

Sha256.Services.Init                                       TRUE   TRUE



If there is a shorter way to describe the impact at the family level or groups of families, then

that would be acceptable as well.



I would prefer the ssl and ec sources from openssl be added/removed based on settings

in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.  However, the feature

flag expressions supported in INF files today do not support use of fields from

structured PCDs.  This needs to be discuss with the BaseTools owners to see if this

would be difficult to support or not.



Thanks,



Mike





> -----Original Message-----

> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>

> Sent: Friday, September 23, 2022 3:40 PM

> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,

> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

>

> Hi Mike

> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.

>

> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do

> enhancement for PCD related stuff later?

>

> Or if you have any other idea, please let us know.

>

> Thank you

> Yao Jiewen

>

> > -----Original Message-----

> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > Sent: Friday, September 23, 2022 3:09 PM

> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob

> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Mike,

> >

> > I did make some attempts with it, but it doesn't work, two troubles here:

> >

> > Bob and Yuwei, please point out if I'm wrong:

> > 1. Using member of structure PCD in INF isn’t supported by Basetools

> > currently,

> > At least it cannot be used as FeatureFlag Expression.

> >

> > 2. As far as I know, structure PCD actually is a const array in code,

> > I afraid it will not work fine with precompile but we do have this need:

> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)

> > # ifndef OPENSSL_NO_EC

> > #  define OPENSSL_NO_EC

> > # endif

> > #endif

> >

> > This is really caused by the bad structure of openssl,

> > maybe we use more detailed comments to remind developers to sync the

> > two PCDs?

> >

> > Thanks,

> > Yi

> >

> > -----Original Message-----

> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Sent: Friday, September 23, 2022 1:25 PM

> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,

> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Yi,

> >

> > I agree there are some complex interactions in the opensll sources.

> >

> > Since you are defining a family for EC, can we use the EC Family != 0 instead

> > of

> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

> >

> > I want to make sure developers do not run into strange build failures if

> > they do not keep the 2 different PCDs aligned.  I prefer a single PCD

> > setting to enable use of EC services.

> >

> > I also noticed that the use of a PCD expression in an INF to select source

> > files does not work if the PCD value is specified with the --pcd flag on

> > the build command line.  This looks like a significant bug with the PCD

> > expression in an INF file.  This also needs to be fixed.

> >

> > Mike

> >

> > > -----Original Message-----

> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > Sent: Thursday, September 22, 2022 8:02 PM

> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Mike,

> > >

> > > 1. Yes, it matches.

> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please

> > refer to another internal email.

> > >

> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS

> > PEM X509  ...

> > >

> > > If we added EC source to OpensslLib.inf and disabled macro

> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary

> > > size,

> > > This an example from x509/x_pubkey.c , other modules is similar:

> > > #ifndef OPENSSL_NO_EC

> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long

> > length)

> > > {

> > >     EVP_PKEY *pkey;

> > >     EC_KEY *key = NULL;

> > >     //.... call EC functions

> > > }

> > > #endif

> > >

> > > If we added EC source to OpensslLib.inf and enable macro

> > OPENSSL_NO_EC, EC module will throw build error,

> > > Since some EC internal APIs or structs have been disabled by

> > OPENSSL_NO_EC but  not another.

> > > This an example from ec/ec_local.h , other error is similar:

> > >

> > > #ifndef OPENSSL_NO_EC

> > > typedef struct ec_group_st EC_GROUP;

> > > typedef struct ec_point_st EC_POINT;

> > > #endif

> > >

> > > // but this function not been enclosed by OPENSSL_NO_EC, and will

> > throw build error

> > >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,

> > >                                                   EC_POINT *, const BIGNUM *x,

> > >                                                   const BIGNUM *y,

> > >                                                   const BIGNUM *z, BN_CTX *);

> > >

> > > To avoid this annoying openssl error, we introduced conditional EC.

> > >

> > > Thanks,

> > > Yi

> > >

> > > -----Original Message-----

> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Sent: Friday, September 23, 2022 6:47 AM

> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D

> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Yi,

> > >

> > > I agree EC is an important feature.

> > >

> > > I did some analysis of the size impact to the CryptoPkg modules on

> > current trunk

> > > with EC on and off. Uncompressed size is important for PEI Phase.  For

> > DXE and

> > > SMM phase, the Crypto services can always be compressed.  From the

> > table below,

> > > building all the EC services in the OpensslLib has no size impact to the

> > NONE

> > > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed

> > DXE/SMM

> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

> > >

> > >                                    Uncompressed      LZMA Compressed

> > > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE

> > EC=TRUE  Increase

> > > ====  ===============  ========  ========  =======  ========

> > =======  ========

> > > IA32  NONE             CryptoPei    21536    21568                         0 KB

> > > IA32  NONE             CryptoDxe    21632    21696                         0 KB

> > > IA32  NONE             CryptoSmm    22976    23072                         0 KB

> > > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520

> > 401034    113 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517

> > 296022    105 KB

> > > IA32  ALL              CryptoPei   423840   598976    189047   293759    104

> > KB

> > > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113

> > KB

> > > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105

> > KB

> > > X64   NONE             CryptoPei    29632    29664                         0 KB

> > > X64   NONE             CryptoDxe    29792    29792                         0 KB

> > > X64   NONE             CryptoSmm    31296    31296                         0 KB

> > > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436

> > 426596    115 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483

> > 310775    106 KB

> > > X64   ALL              CryptoPei   540384   730240    202494   308467    106

> > KB

> > > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115

> > KB

> > > X64   ALL              CryptoSmm   563648   753696    213488   319644    106

> > KB

> > >

> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if

> > the

> > >       entire FV is compressed, the total size impact is typically the size of a

> > >       single instance of a compressed CryptoLib.  The sizes of the Crypto*

> > modules

> > >       in the table above should be a close approximation of the size impact

> > to a

> > >       single FV.

> > >

> > > Does this match your previous size analysis?

> > >

> > > The critical issue to evaluate here is why adding the EC sources to

> > OpensllLib.inf

> > > causes the modules that do not use any EC services to grow by ~105KB.

> > Has any

> > > detailed analysis of the final linked images been performed to see where

> > this

> > > additional size is coming from?

> > >

> > > Thanks,

> > >

> > > Mike

> > >

> > > > -----Original Message-----

> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > Sent: Thursday, September 22, 2022 5:54 AM

> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > Hi Mike,

> > > > I have did some POC that seems existed structured PCD is hard to

> > control binary size,

> > > > Here is the previous discussion for reference.

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679

> > > > https://edk2.groups.io/g/devel/topic/86257810#81814

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446

> > > >

> > > > Anyway EC is an important feature which consumed by vary modern

> > security features such WPA3 , SPDM, TLS1.3 etc.

> > > > Hope it can be added to edk2, and I am glad to take the code and test

> > work if there are other ways to control the size.

> > > >

> > > > Thanks,

> > > > Yi

> > > >

> > > > -----Original Message-----

> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > Sent: Thursday, September 22, 2022 11:56 AM

> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly

> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > That change to OpensslLib.inf should not have been done either.

> > > >

> > > > Looks like this EC feature needs more evaluation to fit into the

> > > > structured PCD control of the lib sizes.

> > > >

> > > > Mike

> > > >

> > > > > -----Original Message-----

> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > Sent: Wednesday, September 21, 2022 7:16 PM

> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Hi Mike,

> > > > > Thanks for review.

> > > > >

> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c

> > will also be compiled and throw build error:

> > > > >

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): error C2220: the following warning is treated

> > > > as

> > > > > an error

> > > > >         1 file(s) copied.

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'

> > > > > undefined; assuming extern returning int

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4047: 'return': 'void *' differs in

> > > > > levels of indirection from 'int'

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(105): warning C4013: 'EC_GROUP_get_curve'

> > > undefined;

> > > > > assuming extern returning int

> > > > >

> > > > > I think the root cause is that we have enabled conditional ec in

> > OpensslLib.inf before by PcdOpensslEcEnabled,

> > > > >

> > > >

> > >

> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934

> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2

> > > > > 02-L238

> > > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.

> > > > > This will save 200+kb memory on platforms which use dxe driver but

> > do not need ec feature.

> > > > >

> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not

> > sure if there is any other way, other better ideas

> > > are

> > > > > welcome.

> > > > >

> > > > > Thanks,

> > > > > Yi

> > > > >

> > > > > -----Original Message-----

> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Sent: Thursday, September 22, 2022 12:22 AM

> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael

> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Comments embedded below.

> > > > >

> > > > > Mike

> > > > >

> > > > > > -----Original Message-----

> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of

> > yi1 li

> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM

> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;

> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1

> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > > >

> > > > > > 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<mailto:jiewen.yao@intel.com>>

> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>

> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>

> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > >

> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > > ---

> > > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++

> > > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +

> > > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +

> > > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765

> > ++++++++++++++++++

> > > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++

> > > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +

> > > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +

> > > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++

> > > > > >  8 files changed, 2186 insertions(+)

> > > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h

> > b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > index b253923dd8..d74fc21c1e 100644

> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > >

> > > > > >  #include <Uefi/UefiBaseType.h>

> > > > > >

> > > > > > +#define CRYPTO_NID_NULL  0x0000

> > > > > > +

> > > > > > +// Key Exchange

> > > > > > +#define CRYPTO_NID_SECP256R1  0x0204

> > > > > > +#define CRYPTO_NID_SECP384R1  0x0205

> > > > > > +#define CRYPTO_NID_SECP521R1  0x0206

> > > > > > +

> > > > > >  ///

> > > > > >  /// MD5 digest size in bytes

> > > > > >  ///

> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (

> > > > > >    OUT VOID       *BnRes

> > > > > >    );

> > > > > >

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient.

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  );

> > > > > > +

> > > > > >  #endif // __BASE_CRYPT_LIB_H__

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > @@ -52,6 +52,8 @@

> > > > > >    Pk/CryptTs.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSign.c

> > > > > > +  Pk/CryptEcNull.c

> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > > > +  Pk/CryptEc.c

> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > >

> > > > > The use of the PCD to select the file should not be needed here.  The

> > > > > Ec Family and individual service enable/disable fields in the

> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is

> > needed to

> > > > > disable the Ec services.

> > > > >

> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should

> > be removed

> > > > > completely as part of this patch series.

> > > > >

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBn.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > index 65ad23fb81..383df2b23c 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > @@ -58,6 +58,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Bn/CryptBnNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..396c819834

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > @@ -0,0 +1,765 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include "InternalCryptLib.h"

> > > > > > +#include <openssl/objects.h>

> > > > > > +#include <openssl/bn.h>

> > > > > > +#include <openssl/ec.h>

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Return the Nid of certain ECC curve.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval !=-1    On success.

> > > > > > +  @retval -1      ECC curve not supported.

> > > > > > +**/

> > > > > > +STATIC

> > > > > > +INT32

> > > > > > +CryptoNidToOpensslNid (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  switch (CryptoNid) {

> > > > > > +    case CRYPTO_NID_SECP256R1:

> > > > > > +      Nid = NID_X9_62_prime256v1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP384R1:

> > > > > > +      Nid = NID_secp384r1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP521R1:

> > > > > > +      Nid = NID_secp521r1;

> > > > > > +      break;

> > > > > > +    default:

> > > > > > +      return -1;

> > > > > > +  }

> > > > > > +

> > > > > > +  return Nid;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);

> > > > > > +

> > > > > > +  if (Nid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return EC_GROUP_new_by_curve_name (Nid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,

> > BnB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,

> > NULL);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_GROUP_free (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_new (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  if (Clear) {

> > > > > > +    EC_POINT_clear_free (EcPoint);

> > > > > > +  } else {

> > > > > > +    EC_POINT_free (EcPoint);

> > > > > > +  }

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,

> > EcPointA, EcPointB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,

> > EcPoint, BnPScalar, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates

> > (EcGroup, EcPoint, BnX, YBit, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined

> > in

> > > > > > +                    BaseCryptLib.h).

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  OpenSslNid;

> > > > > > +

> > > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);

> > > > > > +  if (OpenSslNid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY_free ((EC_KEY *)EcContext);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +

> > > > > > +  // Assume RAND_seed was called

> > > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  if (PublicKey != NULL) {

> > > > > > +    ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If public key is compressed, the PeerPublic will only contain half

> > key (X).

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  EC_KEY          *PeerEcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  EC_POINT        *Point;

> > > > > > +  INT32           OpenSslNid;

> > > > > > +  UINTN           HalfSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==

> > NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((Key == NULL) && (*KeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (PeerPublicSize > INT_MAX) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*KeySize < HalfSize) {

> > > > > > +    *KeySize = HalfSize;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *KeySize = HalfSize;

> > > > > > +

> > > > > > +  RetVal    = FALSE;

> > > > > > +  Point     = NULL;

> > > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);

> > > > > > +  BnY       = NULL;

> > > > > > +  Point     = EC_POINT_new (Group);

> > > > > > +  PeerEcKey = NULL;

> > > > > > +  if ((BnX == NULL) || (Point == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (CompressFlag == NULL) {

> > > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);

> > > > > > +    if (BnY == NULL) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +

> > > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,

> > NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  } else {

> > > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,

> > *CompressFlag, NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  }

> > > > > > +

> > > > > > +  // Validate NIST ECDH public key

> > > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);

> > > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +  if (PeerEcKey == NULL) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  EC_POINT_free (Point);

> > > > > > +  EC_KEY_free (PeerEcKey);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > index ce6a789dfd..4bc3063485 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > @@ -59,6 +59,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBnNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > index 354f3d80aa..e1a57ef09f 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > @@ -49,6 +49,7 @@

> > > > > >    Pk/CryptX509Null.c

> > > > > >    Pk/CryptAuthenticodeNull.c

> > > > > >    Pk/CryptTsNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Pk/CryptRsaPssNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > --

> > > > > > 2.31.1.windows.1

> > > > > >

> > > > > >

> > > > > >

> > > > > > 

> > > > > >



[-- Attachment #2: Type: text/html, Size: 379577 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
  2022-09-24 15:16                           ` Michael D Kinney
@ 2022-09-24 16:03                             ` Yao, Jiewen
  0 siblings, 0 replies; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-24 16:03 UTC (permalink / raw)
  To: Kinney, Michael D, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
	Feng, Bob C
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng

[-- Attachment #1: Type: text/plain, Size: 132784 bytes --]

Hi Mike
Good feedback and suggestion. I try to answer:


  1.  We don’t have PCD to control SSL yet. Neither PcdOpensslEcEnabled nor PcdCryptoServiceFamilyEnable controls SSL.
PcdOpensslEcEnabled controls the OPENSSL configuration.
PcdCryptoServiceFamilyEnable controls Crypto driver configuration.

They are in different level.


  1.  The PcdOpensslEcEnabled is to control if we need enable ECC MACRO for openssl.
Please refer to https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h


  1.  The base line of crypto set in openssl is controlled by https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf_generated.h

Before we introduce ECC, we don’t have any PcdOpensslXXXEnabled.
However, when we need ECC capability for TLS, we faced the situation that the size of crypto library is increased dramatically. That impacts the existing platform.

As such, the PcdOpensslEcEnabled is introduced to resolved the size issue, to control openssl MACRO such as OPENSSL_NO_EC.
We did tried reuse PcdCryptoServiceFamilyEnable. However, structure PCD solution does not work, which is confirmed with tool team.


  1.  Yes, I agree with you that we should provide better documentation to describe the usage and interaction between PcdOpensslEcEnabled and PcdCryptoServiceFamilyEnable.EC.
At least we should say: if PcdCryptoServiceFamilyEnable.EC is 1, then PcdOpensslEcEnabled must be TRUE.


Hi Yi
Please follow Mike’s suggestion to add one more patch to address below feedback:
=================
Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features.  Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.
=================


Thank you
Yao Jiewen



From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Saturday, September 24, 2022 11:17 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Hi Jiewen,

Can you explain interaction with compiling SSL sources or not.  There are 2 INFs a developer has to select from.

Also, just to clarify.  I think you referring to the cyphers available through some of the openssl services.

There is a baseline set of cyphers that were selected for FW use a long time ago.  What is that baseline set?

Building the EC sources extends the set of cyphers available.

Some FW features depend on different sets of cyphers in the CryptLib

Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features.  Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.

I would like to see this documentation added and reviewed as part of the EC patch series.

Thanks,

Mike

From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Sent: Saturday, September 24, 2022 3:22 AM
To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

Hi Mike
To clarify current situation: We support 3 different use cases:

1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.

2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.

3)  PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.

I think a platform developer should know its configuration and make right choice.

For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.

For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.


Thank you
Yao, Jiewen


From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support


Hi Mike,

My bad missed this feedback ☹, this important issue should be discussed as early as possible.



The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs

additional information about the source files config PCD to ensure that the service is enabled properly.

We can add the following table to the DSC file for reference.



################################################################################

#

# Openssl Source Config Table

#

################################################################################

# Note: To ensure crypto services are properly enabled, platform requires:

#       1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family

#          to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,

#          OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X

#          to TRUE if only function X of Services XX needed.

#       2. To optimize Crypto Driver binary size, source files of some crypto

#          services have been set to conditional. Additional PCD in below table should

#          be set to TRUE.

#===============================================================================

#|  Crypto Service  |                     Additional PCD                       |

#===============================================================================

#|TlsSet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|TlsGet            | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD]   |

#|Ec                | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled          |

#===============================================================================



Welcome basetools to provide better ways to optimize the use of PCD,

but from the previous discussion it seems to take quite a long time,

do you think we can merge the current patch first and then optimize it?



Thanks,

Yi



-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support



Hi Jiewen,



My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.



    https://edk2.groups.io/g/devel/message/89019



My main concern at this point is how a platform developer knows how to configure these PCDs.



When should PcdOpensslEcEnabled be set to TRUE?  The name of the PCD implies that EC services

are available, but that is not actually true.  It only compiles the EC source files into

the openssl lib.



I think a developer has to enable other features in order to actually make use of the

content provided by those source files.  Correct?



The other INF that adds the SSL files has the same issue.  How does a developer know when

to use the INF with the SSL files or not.  And what features need to be enabled in order to use

the content added by those SSL files.



We have a number of services in the BaseCryptLib that can be enabled and disabled using

the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.



Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable

and if the service is impacted by the inclusion of the ssl sources and/or the ec sources.  If there is an impact,

then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources



Example:



gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable   SSL    EC    Description

========================================================  =====  =====  ===========

Sha256.Services.Init                                      FALSE  FALSE

Sha256.Services.Init                                      FALSE   TRUE

Sha256.Services.Init                                       TRUE  FALSE

Sha256.Services.Init                                       TRUE   TRUE



If there is a shorter way to describe the impact at the family level or groups of families, then

that would be acceptable as well.



I would prefer the ssl and ec sources from openssl be added/removed based on settings

in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.  However, the feature

flag expressions supported in INF files today do not support use of fields from

structured PCDs.  This needs to be discuss with the BaseTools owners to see if this

would be difficult to support or not.



Thanks,



Mike





> -----Original Message-----

> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>

> Sent: Friday, September 23, 2022 3:40 PM

> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,

> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

>

> Hi Mike

> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.

>

> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do

> enhancement for PCD related stuff later?

>

> Or if you have any other idea, please let us know.

>

> Thank you

> Yao Jiewen

>

> > -----Original Message-----

> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > Sent: Friday, September 23, 2022 3:09 PM

> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob

> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Mike,

> >

> > I did make some attempts with it, but it doesn't work, two troubles here:

> >

> > Bob and Yuwei, please point out if I'm wrong:

> > 1. Using member of structure PCD in INF isn’t supported by Basetools

> > currently,

> > At least it cannot be used as FeatureFlag Expression.

> >

> > 2. As far as I know, structure PCD actually is a const array in code,

> > I afraid it will not work fine with precompile but we do have this need:

> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)

> > # ifndef OPENSSL_NO_EC

> > #  define OPENSSL_NO_EC

> > # endif

> > #endif

> >

> > This is really caused by the bad structure of openssl,

> > maybe we use more detailed comments to remind developers to sync the

> > two PCDs?

> >

> > Thanks,

> > Yi

> >

> > -----Original Message-----

> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Sent: Friday, September 23, 2022 1:25 PM

> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine

> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,

> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> >

> > Hi Yi,

> >

> > I agree there are some complex interactions in the opensll sources.

> >

> > Since you are defining a family for EC, can we use the EC Family != 0 instead

> > of

> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.

> >

> > I want to make sure developers do not run into strange build failures if

> > they do not keep the 2 different PCDs aligned.  I prefer a single PCD

> > setting to enable use of EC services.

> >

> > I also noticed that the use of a PCD expression in an INF to select source

> > files does not work if the PCD value is specified with the --pcd flag on

> > the build command line.  This looks like a significant bug with the PCD

> > expression in an INF file.  This also needs to be fixed.

> >

> > Mike

> >

> > > -----Original Message-----

> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > Sent: Thursday, September 22, 2022 8:02 PM

> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Mike,

> > >

> > > 1. Yes, it matches.

> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please

> > refer to another internal email.

> > >

> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS

> > PEM X509  ...

> > >

> > > If we added EC source to OpensslLib.inf and disabled macro

> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary

> > > size,

> > > This an example from x509/x_pubkey.c , other modules is similar:

> > > #ifndef OPENSSL_NO_EC

> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long

> > length)

> > > {

> > >     EVP_PKEY *pkey;

> > >     EC_KEY *key = NULL;

> > >     //.... call EC functions

> > > }

> > > #endif

> > >

> > > If we added EC source to OpensslLib.inf and enable macro

> > OPENSSL_NO_EC, EC module will throw build error,

> > > Since some EC internal APIs or structs have been disabled by

> > OPENSSL_NO_EC but  not another.

> > > This an example from ec/ec_local.h , other error is similar:

> > >

> > > #ifndef OPENSSL_NO_EC

> > > typedef struct ec_group_st EC_GROUP;

> > > typedef struct ec_point_st EC_POINT;

> > > #endif

> > >

> > > // but this function not been enclosed by OPENSSL_NO_EC, and will

> > throw build error

> > >     int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,

> > >                                                   EC_POINT *, const BIGNUM *x,

> > >                                                   const BIGNUM *y,

> > >                                                   const BIGNUM *z, BN_CTX *);

> > >

> > > To avoid this annoying openssl error, we introduced conditional EC.

> > >

> > > Thanks,

> > > Yi

> > >

> > > -----Original Message-----

> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Sent: Friday, September 23, 2022 6:47 AM

> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D

> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > >

> > > Hi Yi,

> > >

> > > I agree EC is an important feature.

> > >

> > > I did some analysis of the size impact to the CryptoPkg modules on

> > current trunk

> > > with EC on and off. Uncompressed size is important for PEI Phase.  For

> > DXE and

> > > SMM phase, the Crypto services can always be compressed.  From the

> > table below,

> > > building all the EC services in the OpensslLib has no size impact to the

> > NONE

> > > profile and the MIN_PEI profile.  It has ~105 KB impact to compressed

> > DXE/SMM

> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.

> > >

> > >                                    Uncompressed      LZMA Compressed

> > > CPU   CRYPTO_SERVICES    Module  EC=FALSE  EC=TRUE  EC=FALSE

> > EC=TRUE  Increase

> > > ====  ===============  ========  ========  =======  ========

> > =======  ========

> > > IA32  NONE             CryptoPei    21536    21568                         0 KB

> > > IA32  NONE             CryptoDxe    21632    21696                         0 KB

> > > IA32  NONE             CryptoSmm    22976    23072                         0 KB

> > > IA32  MIN_PEI          CryptoPei   248992   249120                         0 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoDxe   636672   829568    288520

> > 401034    113 KB

> > > IA32  MIN_DXE_MIN_SMM  CryptoSmm   426048   601472    191517

> > 296022    105 KB

> > > IA32  ALL              CryptoPei   423840   598976    189047   293759    104

> > KB

> > > IA32  ALL              CryptoDxe   645280   838144    292955   405277    113

> > KB

> > > IA32  ALL              CryptoSmm   441888   617184    198779   303628    105

> > KB

> > > X64   NONE             CryptoPei    29632    29664                         0 KB

> > > X64   NONE             CryptoDxe    29792    29792                         0 KB

> > > X64   NONE             CryptoSmm    31296    31296                         0 KB

> > > X64   MIN_PEI          CryptoPei   310784   310848                         0 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoDxe   804288  1016256    311436

> > 426596    115 KB

> > > X64   MIN_DXE_MIN_SMM  CryptoSmm   543776   733920    204483

> > 310775    106 KB

> > > X64   ALL              CryptoPei   540384   730240    202494   308467    106

> > KB

> > > X64   ALL              CryptoDxe   815392  1027296    316228   431321    115

> > KB

> > > X64   ALL              CryptoSmm   563648   753696    213488   319644    106

> > KB

> > >

> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if

> > the

> > >       entire FV is compressed, the total size impact is typically the size of a

> > >       single instance of a compressed CryptoLib.  The sizes of the Crypto*

> > modules

> > >       in the table above should be a close approximation of the size impact

> > to a

> > >       single FV.

> > >

> > > Does this match your previous size analysis?

> > >

> > > The critical issue to evaluate here is why adding the EC sources to

> > OpensllLib.inf

> > > causes the modules that do not use any EC services to grow by ~105KB.

> > Has any

> > > detailed analysis of the final linked images been performed to see where

> > this

> > > additional size is coming from?

> > >

> > > Thanks,

> > >

> > > Mike

> > >

> > > > -----Original Message-----

> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > Sent: Thursday, September 22, 2022 5:54 AM

> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > Hi Mike,

> > > > I have did some POC that seems existed structured PCD is hard to

> > control binary size,

> > > > Here is the previous discussion for reference.

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679

> > > > https://edk2.groups.io/g/devel/topic/86257810#81814

> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446

> > > >

> > > > Anyway EC is an important feature which consumed by vary modern

> > security features such WPA3 , SPDM, TLS1.3 etc.

> > > > Hope it can be added to edk2, and I am glad to take the code and test

> > work if there are other ways to control the size.

> > > >

> > > > Thanks,

> > > > Yi

> > > >

> > > > -----Original Message-----

> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > Sent: Thursday, September 22, 2022 11:56 AM

> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly

> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>

> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > >

> > > > That change to OpensslLib.inf should not have been done either.

> > > >

> > > > Looks like this EC feature needs more evaluation to fit into the

> > > > structured PCD control of the lib sizes.

> > > >

> > > > Mike

> > > >

> > > > > -----Original Message-----

> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > Sent: Wednesday, September 21, 2022 7:16 PM

> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;

> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Hi Mike,

> > > > > Thanks for review.

> > > > >

> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c

> > will also be compiled and throw build error:

> > > > >

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): error C2220: the following warning is treated

> > > > as

> > > > > an error

> > > > >         1 file(s) copied.

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'

> > > > > undefined; assuming extern returning int

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(77): warning C4047: 'return': 'void *' differs in

> > > > > levels of indirection from 'int'

> > > > >

> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.

> > c(105): warning C4013: 'EC_GROUP_get_curve'

> > > undefined;

> > > > > assuming extern returning int

> > > > >

> > > > > I think the root cause is that we have enabled conditional ec in

> > OpensslLib.inf before by PcdOpensslEcEnabled,

> > > > >

> > > >

> > >

> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934

> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2

> > > > > 02-L238

> > > > >  if PcdOpensslEcEnabled not true, all ec files will not be compiled.

> > > > > This will save 200+kb memory on platforms which use dxe driver but

> > do not need ec feature.

> > > > >

> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not

> > sure if there is any other way, other better ideas

> > > are

> > > > > welcome.

> > > > >

> > > > > Thanks,

> > > > > Yi

> > > > >

> > > > > -----Original Message-----

> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Sent: Thursday, September 22, 2022 12:22 AM

> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael

> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>

> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J

> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,

> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > >

> > > > > Comments embedded below.

> > > > >

> > > > > Mike

> > > > >

> > > > > > -----Original Message-----

> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of

> > yi1 li

> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM

> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>

> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;

> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1

> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support

> > > > > >

> > > > > > 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<mailto:jiewen.yao@intel.com>>

> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>

> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>

> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>

> > > > > >

> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>

> > > > > > ---

> > > > > >  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 ++++++++++

> > > > > >  .../Library/BaseCryptLib/BaseCryptLib.inf     |   2 +

> > > > > >  .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +

> > > > > >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 765

> > ++++++++++++++++++

> > > > > >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     | 496 ++++++++++++

> > > > > >  .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +

> > > > > >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +

> > > > > >  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++

> > > > > >  8 files changed, 2186 insertions(+)

> > > > > >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > >  create mode 100644

> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h

> > b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > index b253923dd8..d74fc21c1e 100644

> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h

> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > >

> > > > > >  #include <Uefi/UefiBaseType.h>

> > > > > >

> > > > > > +#define CRYPTO_NID_NULL  0x0000

> > > > > > +

> > > > > > +// Key Exchange

> > > > > > +#define CRYPTO_NID_SECP256R1  0x0204

> > > > > > +#define CRYPTO_NID_SECP384R1  0x0205

> > > > > > +#define CRYPTO_NID_SECP521R1  0x0206

> > > > > > +

> > > > > >  ///

> > > > > >  /// MD5 digest size in bytes

> > > > > >  ///

> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (

> > > > > >    OUT VOID       *BnRes

> > > > > >    );

> > > > > >

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient.

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  );

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  );

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  );

> > > > > > +

> > > > > >  #endif // __BASE_CRYPT_LIB_H__

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf

> > > > > > @@ -52,6 +52,8 @@

> > > > > >    Pk/CryptTs.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSign.c

> > > > > > +  Pk/CryptEcNull.c

> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > > > +  Pk/CryptEc.c

> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled

> > > > >

> > > > > The use of the PCD to select the file should not be needed here.  The

> > > > > Ec Family and individual service enable/disable fields in the

> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is

> > needed to

> > > > > disable the Ec services.

> > > > >

> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should

> > be removed

> > > > > completely as part of this patch series.

> > > > >

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBn.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > index 65ad23fb81..383df2b23c 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf

> > > > > > @@ -58,6 +58,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Bn/CryptBnNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..396c819834

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c

> > > > > > @@ -0,0 +1,765 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include "InternalCryptLib.h"

> > > > > > +#include <openssl/objects.h>

> > > > > > +#include <openssl/bn.h>

> > > > > > +#include <openssl/ec.h>

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Basic Elliptic Curve Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Return the Nid of certain ECC curve.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval !=-1    On success.

> > > > > > +  @retval -1      ECC curve not supported.

> > > > > > +**/

> > > > > > +STATIC

> > > > > > +INT32

> > > > > > +CryptoNidToOpensslNid (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  switch (CryptoNid) {

> > > > > > +    case CRYPTO_NID_SECP256R1:

> > > > > > +      Nid = NID_X9_62_prime256v1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP384R1:

> > > > > > +      Nid = NID_secp384r1;

> > > > > > +      break;

> > > > > > +    case CRYPTO_NID_SECP521R1:

> > > > > > +      Nid = NID_secp521r1;

> > > > > > +      break;

> > > > > > +    default:

> > > > > > +      return -1;

> > > > > > +  }

> > > > > > +

> > > > > > +  return Nid;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  Nid;

> > > > > > +

> > > > > > +  Nid = CryptoNidToOpensslNid (CryptoNid);

> > > > > > +

> > > > > > +  if (Nid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return EC_GROUP_new_by_curve_name (Nid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,

> > BnB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,

> > NULL);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_GROUP_free (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_new (EcGroup);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  if (Clear) {

> > > > > > +    EC_POINT_clear_free (EcPoint);

> > > > > > +  } else {

> > > > > > +    EC_POINT_free (EcPoint);

> > > > > > +  }

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,

> > EcPoint, BnX, BnY, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,

> > EcPointA, EcPointB, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,

> > EcPoint, BnPScalar, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  return (BOOLEAN)EC_POINT_set_compressed_coordinates

> > (EcGroup, EcPoint, BnX, YBit, BnCtx);

> > > > > > +}

> > > > > > +

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +//    Elliptic Curve Diffie Hellman Primitives

> > > > > > +//

> > ==========================================================

> > ===========================

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid   Identifying number for the ECC curve (Defined

> > in

> > > > > > +                    BaseCryptLib.h).

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  INT32  OpenSslNid;

> > > > > > +

> > > > > > +  OpenSslNid = CryptoNidToOpensslNid (Nid);

> > > > > > +  if (OpenSslNid < 0) {

> > > > > > +    return NULL;

> > > > > > +  }

> > > > > > +

> > > > > > +  return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY_free ((EC_KEY *)EcContext);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +

> > > > > > +  // Assume RAND_seed was called

> > > > > > +  if (EC_KEY_generate_key (EcKey) != 1) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +  BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +  BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  CONST EC_POINT  *EcPoint;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  UINTN           HalfSize;

> > > > > > +  INTN            XSize;

> > > > > > +  INTN            YSize;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PublicKeySize == NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if (*PublicKeySize < HalfSize * 2) {

> > > > > > +    *PublicKeySize = HalfSize * 2;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *PublicKeySize = HalfSize * 2;

> > > > > > +

> > > > > > +  EcPoint = EC_KEY_get0_public_key (EcKey);

> > > > > > +  if (EcPoint == NULL) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = FALSE;

> > > > > > +  BnX    = BN_new ();

> > > > > > +  BnY    = BN_new ();

> > > > > > +  if ((BnX == NULL) || (BnY == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,

> > NULL) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  XSize = BN_num_bytes (BnX);

> > > > > > +  YSize = BN_num_bytes (BnY);

> > > > > > +  if ((XSize <= 0) || (YSize <= 0)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);

> > > > > > +

> > > > > > +  if (PublicKey != NULL) {

> > > > > > +    ZeroMem (PublicKey, *PublicKeySize);

> > > > > > +    BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);

> > > > > > +    BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If public key is compressed, the PeerPublic will only contain half

> > key (X).

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  EC_KEY          *EcKey;

> > > > > > +  EC_KEY          *PeerEcKey;

> > > > > > +  CONST EC_GROUP  *Group;

> > > > > > +  BOOLEAN         RetVal;

> > > > > > +  BIGNUM          *BnX;

> > > > > > +  BIGNUM          *BnY;

> > > > > > +  EC_POINT        *Point;

> > > > > > +  INT32           OpenSslNid;

> > > > > > +  UINTN           HalfSize;

> > > > > > +

> > > > > > +  if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==

> > NULL)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((Key == NULL) && (*KeySize != 0)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (PeerPublicSize > INT_MAX) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  EcKey    = (EC_KEY *)EcContext;

> > > > > > +  Group    = EC_KEY_get0_group (EcKey);

> > > > > > +  HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;

> > > > > > +  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (*KeySize < HalfSize) {

> > > > > > +    *KeySize = HalfSize;

> > > > > > +    return FALSE;

> > > > > > +  }

> > > > > > +

> > > > > > +  *KeySize = HalfSize;

> > > > > > +

> > > > > > +  RetVal    = FALSE;

> > > > > > +  Point     = NULL;

> > > > > > +  BnX       = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);

> > > > > > +  BnY       = NULL;

> > > > > > +  Point     = EC_POINT_new (Group);

> > > > > > +  PeerEcKey = NULL;

> > > > > > +  if ((BnX == NULL) || (Point == NULL)) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (CompressFlag == NULL) {

> > > > > > +    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);

> > > > > > +    if (BnY == NULL) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +

> > > > > > +    if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,

> > NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  } else {

> > > > > > +    if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,

> > *CompressFlag, NULL) != 1) {

> > > > > > +      goto fail;

> > > > > > +    }

> > > > > > +  }

> > > > > > +

> > > > > > +  // Validate NIST ECDH public key

> > > > > > +  OpenSslNid = EC_GROUP_get_curve_name (Group);

> > > > > > +  PeerEcKey  = EC_KEY_new_by_curve_name (OpenSslNid);

> > > > > > +  if (PeerEcKey == NULL) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (EC_KEY_check_key (PeerEcKey) != 1) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {

> > > > > > +    goto fail;

> > > > > > +  }

> > > > > > +

> > > > > > +  RetVal = TRUE;

> > > > > > +

> > > > > > +fail:

> > > > > > +  BN_free (BnX);

> > > > > > +  BN_free (BnY);

> > > > > > +  EC_POINT_free (Point);

> > > > > > +  EC_KEY_free (PeerEcKey);

> > > > > > +  return RetVal;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > index ce6a789dfd..4bc3063485 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf

> > > > > > @@ -59,6 +59,7 @@

> > > > > >    Pk/CryptTsNull.c

> > > > > >    Pk/CryptRsaPss.c

> > > > > >    Pk/CryptRsaPssSignNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPem.c

> > > > > >    Bn/CryptBnNull.c

> > > > > >

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > index 354f3d80aa..e1a57ef09f 100644

> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf

> > > > > > @@ -49,6 +49,7 @@

> > > > > >    Pk/CryptX509Null.c

> > > > > >    Pk/CryptAuthenticodeNull.c

> > > > > >    Pk/CryptTsNull.c

> > > > > > +  Pk/CryptEcNull.c

> > > > > >    Pem/CryptPemNull.c

> > > > > >    Rand/CryptRandNull.c

> > > > > >    Pk/CryptRsaPssNull.c

> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > new file mode 100644

> > > > > > index 0000000000..d9f1004f6c

> > > > > > --- /dev/null

> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c

> > > > > > @@ -0,0 +1,496 @@

> > > > > > +/** @file

> > > > > > +  Elliptic Curve and ECDH API implementation based on OpenSSL

> > > > > > +

> > > > > > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

> > > > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent

> > > > > > +

> > > > > > +**/

> > > > > > +

> > > > > > +#include <Library/BaseCryptLib.h>

> > > > > > +#include <Library/DebugLib.h>

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EcGroup object. This object represents an EC

> > curve and

> > > > > > +  and is used for calculation within this group. This object should be

> > freed

> > > > > > +  using EcGroupFree() function.

> > > > > > +

> > > > > > +  @param[in]  CryptoNid   Identifying number for the ECC curve

> > (Defined in

> > > > > > +                          BaseCryptLib.h).

> > > > > > +

> > > > > > +  @retval EcGroup object  On success.

> > > > > > +  @retval NULL            On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcGroupInit (

> > > > > > +  IN UINTN  CryptoNid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC curve parameters. While elliptic curve equation is Y^2 mod

> > P = (X^3 + AX + B) Mod P.

> > > > > > +  This function will set the provided Big Number objects  to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[out] BnPrime    Group prime number.

> > > > > > +  @param[out] BnA        A coefficient.

> > > > > > +  @param[out] BnB        B coefficient..

> > > > > > +  @param[in]  BnCtx      BN context.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *BnPrime,

> > > > > > +  OUT VOID       *BnA,

> > > > > > +  OUT VOID       *BnB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC group order.

> > > > > > +  This function will set the provided Big Number object to the

> > corresponding

> > > > > > +  value. The caller needs to make sure that the "out" BigNumber

> > parameter

> > > > > > +  is properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[out] BnOrder   Group prime number.

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGroupGetOrder (

> > > > > > +  IN VOID   *EcGroup,

> > > > > > +  OUT VOID  *BnOrder

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC group object using EcGroupInit().

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object to free.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcGroupFree (

> > > > > > +  IN VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Initialize new opaque EC Point object. This object represents an EC

> > point

> > > > > > +  within the given EC group (curve).

> > > > > > +

> > > > > > +  @param[in]  EC Group, properly initialized using EcGroupInit().

> > > > > > +

> > > > > > +  @retval EC Point object  On success.

> > > > > > +  @retval NULL             On failure.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcPointInit (

> > > > > > +  IN CONST VOID  *EcGroup

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Free previously allocated EC Point object using EcPointInit().

> > > > > > +

> > > > > > +  @param[in]  EcPoint   EC Point to free.

> > > > > > +  @param[in]  Clear     TRUE iff the memory should be cleared.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcPointDeInit (

> > > > > > +  IN VOID     *EcPoint,

> > > > > > +  IN BOOLEAN  Clear

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Get EC point affine (x,y) coordinates.

> > > > > > +  This function will set the provided Big Number objects to the

> > corresponding

> > > > > > +  values. The caller needs to make sure all the "out" BigNumber

> > parameters

> > > > > > +  are properly initialized.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[out] BnX        X coordinate.

> > > > > > +  @param[out] BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointGetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  OUT VOID       *BnX,

> > > > > > +  OUT VOID       *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point affine (x,y) coordinates.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC point object.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  BnY        Y coordinate.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetAffineCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN CONST VOID  *BnY,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  EC Point addition. EcPointResult = EcPointA + EcPointB.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPointA         EC Point.

> > > > > > +  @param[in]  EcPointB         EC Point.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointAdd (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Variable EC point multiplication. EcPointResult = EcPoint *

> > BnPScalar.

> > > > > > +

> > > > > > +  @param[in]  EcGroup          EC group object.

> > > > > > +  @param[out] EcPointResult    EC point to hold the result. The

> > point should

> > > > > > +                               be properly initialized.

> > > > > > +  @param[in]  EcPoint          EC Point.

> > > > > > +  @param[in]  BnPScalar        P Scalar.

> > > > > > +  @param[in]  BnCtx            BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointMul (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  OUT VOID       *EcPointResult,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN CONST VOID  *BnPScalar,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Calculate the inverse of the supplied EC point.

> > > > > > +

> > > > > > +  @param[in]     EcGroup   EC group object.

> > > > > > +  @param[in,out] EcPoint   EC point to invert.

> > > > > > +  @param[in]     BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointInvert (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN OUT VOID    *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is on EC curve.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On curve.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsOnCurve (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if the supplied point is at infinity.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPoint   EC point to check.

> > > > > > +

> > > > > > +  @retval TRUE          At infinity.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointIsAtInfinity (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPoint

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Check if EC points are equal.

> > > > > > +

> > > > > > +  @param[in]  EcGroup   EC group object.

> > > > > > +  @param[in]  EcPointA  EC point A.

> > > > > > +  @param[in]  EcPointB  EC point B.

> > > > > > +  @param[in]  BnCtx     BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          A == B.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointEqual (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN CONST VOID  *EcPointA,

> > > > > > +  IN CONST VOID  *EcPointB,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Set EC point compressed coordinates. Points can be described in

> > terms of

> > > > > > +  their compressed coordinates. For a point (x, y), for any given

> > value for x

> > > > > > +  such that the point is on the curve there will only ever be two

> > possible

> > > > > > +  values for y. Therefore, a point can be set using this function

> > where BnX is

> > > > > > +  the x coordinate and YBit is a value 0 or 1 to identify which of the

> > two

> > > > > > +  possible values for y should be used.

> > > > > > +

> > > > > > +  @param[in]  EcGroup    EC group object.

> > > > > > +  @param[in]  EcPoint    EC Point.

> > > > > > +  @param[in]  BnX        X coordinate.

> > > > > > +  @param[in]  YBit       0 or 1 to identify which Y value is used.

> > > > > > +  @param[in]  BnCtx      BN context, created with

> > BigNumNewContext().

> > > > > > +

> > > > > > +  @retval TRUE          On success.

> > > > > > +  @retval FALSE         Otherwise.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcPointSetCompressedCoordinates (

> > > > > > +  IN CONST VOID  *EcGroup,

> > > > > > +  IN VOID        *EcPoint,

> > > > > > +  IN CONST VOID  *BnX,

> > > > > > +  IN UINT8       YBit,

> > > > > > +  IN VOID        *BnCtx

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Allocates and Initializes one Elliptic Curve Context for subsequent

> > use

> > > > > > +  with the NID.

> > > > > > +

> > > > > > +  @param[in]  Nid cipher NID

> > > > > > +  @return     Pointer to the Elliptic Curve Context that has been

> > initialized.

> > > > > > +              If the allocations fails, EcNewByNid() returns NULL.

> > > > > > +**/

> > > > > > +VOID *

> > > > > > +EFIAPI

> > > > > > +EcNewByNid (

> > > > > > +  IN UINTN  Nid

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return NULL;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Release the specified EC context.

> > > > > > +

> > > > > > +  @param[in]  EcContext  Pointer to the EC context to be released.

> > > > > > +**/

> > > > > > +VOID

> > > > > > +EFIAPI

> > > > > > +EcFree (

> > > > > > +  IN  VOID  *EcContext

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Generates EC key and returns EC public key (X, Y), Please note,

> > this function uses

> > > > > > +  pseudo random number generator. The caller must make sure

> > RandomSeed()

> > > > > > +  function was properly called before.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid.

> > > > > > +  This function generates random secret, and computes the public

> > key (X, Y), which is

> > > > > > +  returned via parameter Public, PublicSize.

> > > > > > +  X is the first half of Public with size being PublicSize / 2,

> > > > > > +  Y is the second half of Public with size being PublicSize / 2.

> > > > > > +  EC context is updated accordingly.

> > > > > > +  If the Public buffer is too small to hold the public X, Y, FALSE is

> > returned and

> > > > > > +  PublicSize is set to the required buffer size to obtain the public X,

> > Y.

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PublicSize is NULL, then return FALSE.

> > > > > > +  If PublicSize is large enough but Public is NULL, then return FALSE.

> > > > > > +  @param[in, out]  EcContext      Pointer to the EC context.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC public X,Y generation succeeded.

> > > > > > +  @retval FALSE  EC public X,Y generation failed.

> > > > > > +  @retval FALSE  PublicKeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGenerateKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Gets the public key component from the established EC context.

> > > > > > +  The Ec context should be correctly initialized by EcNewByNid, and

> > successfully

> > > > > > +  generate key pair from EcGenerateKey().

> > > > > > +  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte

> > is Y.

> > > > > > +  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte

> > is Y.

> > > > > > +  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte

> > is Y.

> > > > > > +  @param[in, out]  EcContext      Pointer to EC context being set.

> > > > > > +  @param[out]      PublicKey      Pointer to t buffer to receive

> > generated public X,Y.

> > > > > > +  @param[in, out]  PublicKeySize  On input, the size of Public buffer

> > in bytes.

> > > > > > +                                  On output, the size of data returned in Public

> > buffer in bytes.

> > > > > > +  @retval  TRUE   EC key component was retrieved successfully.

> > > > > > +  @retval  FALSE  Invalid EC key component.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcGetPubKey (

> > > > > > +  IN OUT  VOID   *EcContext,

> > > > > > +  OUT     UINT8  *PublicKey,

> > > > > > +  IN OUT  UINTN  *PublicKeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > +

> > > > > > +/**

> > > > > > +  Computes exchanged common key.

> > > > > > +  Given peer's public key (X, Y), this function computes the

> > exchanged common key,

> > > > > > +  based on its own context including value of curve parameter and

> > random secret.

> > > > > > +  X is the first half of PeerPublic with size being PeerPublicSize / 2,

> > > > > > +  Y is the second half of PeerPublic with size being PeerPublicSize /

> > 2.

> > > > > > +  If EcContext is NULL, then return FALSE.

> > > > > > +  If PeerPublic is NULL, then return FALSE.

> > > > > > +  If PeerPublicSize is 0, then return FALSE.

> > > > > > +  If Key is NULL, then return FALSE.

> > > > > > +  If KeySize is not large enough, then return FALSE.

> > > > > > +  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-

> > byte is Y.

> > > > > > +  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-

> > byte is Y.

> > > > > > +  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-

> > byte is Y.

> > > > > > +  @param[in, out]  EcContext          Pointer to the EC context.

> > > > > > +  @param[in]       PeerPublic         Pointer to the peer's public X,Y.

> > > > > > +  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.

> > > > > > +  @param[in]       CompressFlag       Flag of PeerPublic is

> > compressed or not.

> > > > > > +  @param[out]      Key                Pointer to the buffer to receive

> > generated key.

> > > > > > +  @param[in, out]  KeySize            On input, the size of Key buffer in

> > bytes.

> > > > > > +                                      On output, the size of data returned in Key

> > buffer in bytes.

> > > > > > +  @retval TRUE   EC exchanged key generation succeeded.

> > > > > > +  @retval FALSE  EC exchanged key generation failed.

> > > > > > +  @retval FALSE  KeySize is not large enough.

> > > > > > +**/

> > > > > > +BOOLEAN

> > > > > > +EFIAPI

> > > > > > +EcDhComputeKey (

> > > > > > +  IN OUT  VOID         *EcContext,

> > > > > > +  IN      CONST UINT8  *PeerPublic,

> > > > > > +  IN      UINTN        PeerPublicSize,

> > > > > > +  IN      CONST INT32  *CompressFlag,

> > > > > > +  OUT     UINT8        *Key,

> > > > > > +  IN OUT  UINTN        *KeySize

> > > > > > +  )

> > > > > > +{

> > > > > > +  ASSERT (FALSE);

> > > > > > +  return FALSE;

> > > > > > +}

> > > > > > --

> > > > > > 2.31.1.windows.1

> > > > > >

> > > > > >

> > > > > >

> > > > > > 

> > > > > >



[-- Attachment #2: Type: text/html, Size: 345088 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-09-24 16:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1663735439.git.yi1.li@intel.com>
2022-09-21  4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
2022-09-21 16:21   ` [edk2-devel] " Michael D Kinney
2022-09-22  2:15     ` yi1 li
2022-09-22  3:56       ` Michael D Kinney
2022-09-22 12:54         ` yi1 li
2022-09-22 22:46           ` Michael D Kinney
2022-09-23  3:01             ` yi1 li
2022-09-23  5:25               ` Michael D Kinney
2022-09-23  7:08                 ` yi1 li
2022-09-23 22:40                   ` Yao, Jiewen
2022-09-24  2:19                     ` Michael D Kinney
2022-09-24  3:44                       ` yi1 li
2022-09-24 10:21                         ` Yao, Jiewen
2022-09-24 15:16                           ` Michael D Kinney
2022-09-24 16:03                             ` Yao, Jiewen
2022-09-21  4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
2022-09-21  4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox