public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V5 0/4] CryptoPkg: Add EC support
@ 2022-09-25  9:26 yi1 li
  2022-09-25  9:26 ` [PATCH V5 1/4] " yi1 li
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: yi1 li @ 2022-09-25  9:26 UTC (permalink / raw)
  To: devel
  Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang,
	Michael D Kinney

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

Review PR: https://github.com/tianocore/edk2/pull/3398
This patch sequence is used to add CryptEc library, which are wrapped
over OpenSSL. The implementation provides library functions for EFI
BaseCrypt protocol and EFI BaseCrypt Configuration Protocol.

All APIs passed unit test and fuzzing test, detail as:
1. Unit test:
The purpose of unit testing is to ensure that the function obtains the
expected result under specific input, that is, to ensure the correctness
of APIs.
All test case show in patch 3 :CryptoPkg/Test: Add unit test for CryptoEc.
2. Fuzzing test:
Various Fuzz Testing are employed across the all introduced APIs, and the
test is used AFL (2.52b) and Libfuzzer (clang+llvm-11.0.0) as the fuzzer,
based on HBFA.
Fuzzing Pass Rate is 100%;
The Code Coverage new APIs is 90.3%.
All test case show in:
https://github.com/liyi77/edk2-staging/tree/HBFA/HBFA/UefiHostFuzzTestCasePkg/TestCase/CryptoPkg

V2 change:
1. Squash uncrustify tool update into previous patch. 
2. Increase EDKII_CRYPTO_VERSION to 10.
V3 change:
Fix typo in comment.
V4 change:
Add ECC related usage reference
V5 change:
Optimized the description of ECC reference

Tested-by: Yi Li <yi1.li@intel.com>
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>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

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

Yi Li (4):
  CryptoPkg: Add EC support
  CryptoPkg: Add EC APIs to DXE and protocol
  CryptoPkg: Add ECC related usage reference
  CryptoPkg/Test: Add unit test for CryptoEc

 CryptoPkg/CryptoPkg.dec                       |  29 +
 CryptoPkg/CryptoPkg.dsc                       |   1 +
 CryptoPkg/Driver/Crypto.c                     | 496 +++++++++++
 CryptoPkg/Include/Library/BaseCryptLib.h      | 424 +++++++++
 .../Pcd/PcdCryptoServiceFamilyEnable.h        |  25 +
 .../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 +
 .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |   2 +
 .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
 .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 +++++++++++
 .../BaseCryptLibOnProtocolPpi/CryptLib.c      | 469 ++++++++++
 CryptoPkg/Private/Protocol/Crypto.h           | 831 +++++++++++++-----
 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 +
 21 files changed, 4137 insertions(+), 200 deletions(-)
 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
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c

-- 
2.31.1.windows.1


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

* [PATCH V5 1/4] CryptoPkg: Add EC support
  2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
@ 2022-09-25  9:26 ` yi1 li
  2022-09-25  9:26 ` [PATCH V5 2/4] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: yi1 li @ 2022-09-25  9:26 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 3026299e29..63c6228368 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
 ///
@@ -3254,4 +3261,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 0208d706b8..9634bd5fea 100644
--- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -53,6 +53,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 82b97bc6d3..3799780c9f 100644
--- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -59,6 +59,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 986581319c..9318052a51 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -60,6 +60,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 88ada0430d..9cb8d42ff4 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
+++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -50,6 +50,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] 6+ messages in thread

* [PATCH V5 2/4] CryptoPkg: Add EC APIs to DXE and protocol
  2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
  2022-09-25  9:26 ` [PATCH V5 1/4] " yi1 li
@ 2022-09-25  9:26 ` yi1 li
  2022-09-25  9:26 ` [PATCH V5 3/4] CryptoPkg: Add ECC related usage reference yi1 li
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: yi1 li @ 2022-09-25  9:26 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           | 831 +++++++++++++-----
 5 files changed, 1622 insertions(+), 200 deletions(-)

diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index 7034e8a412..e4e7bc0dbf 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -172,6 +172,7 @@
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.ParallelHash.Family                      | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.AeadAesGcm.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 9872b5bf70..7a8266aaba 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -5519,6 +5519,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,
@@ -5770,4 +6245,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 52b44ca4f8..45bafc2161 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -356,6 +356,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 ce6981f091..791e2ef599 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -4553,3 +4553,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 3bf37575e9..2f267c7f55 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  12
+#define EDKII_CRYPTO_VERSION  13
 
 ///
 /// EDK II Crypto Protocol forward declaration
@@ -4289,240 +4289,671 @@ 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;
   /// HMAC SHA256 (continued)
-  EDKII_CRYPTO_HMAC_SHA256_ALL                       HmacSha256All;
+  EDKII_CRYPTO_HMAC_SHA256_ALL                        HmacSha256All;
   /// HMAC SHA384
-  EDKII_CRYPTO_HMAC_SHA384_NEW                       HmacSha384New;
-  EDKII_CRYPTO_HMAC_SHA384_FREE                      HmacSha384Free;
-  EDKII_CRYPTO_HMAC_SHA384_SET_KEY                   HmacSha384SetKey;
-  EDKII_CRYPTO_HMAC_SHA384_DUPLICATE                 HmacSha384Duplicate;
-  EDKII_CRYPTO_HMAC_SHA384_UPDATE                    HmacSha384Update;
-  EDKII_CRYPTO_HMAC_SHA384_FINAL                     HmacSha384Final;
-  EDKII_CRYPTO_HMAC_SHA384_ALL                       HmacSha384All;
+  EDKII_CRYPTO_HMAC_SHA384_NEW                        HmacSha384New;
+  EDKII_CRYPTO_HMAC_SHA384_FREE                       HmacSha384Free;
+  EDKII_CRYPTO_HMAC_SHA384_SET_KEY                    HmacSha384SetKey;
+  EDKII_CRYPTO_HMAC_SHA384_DUPLICATE                  HmacSha384Duplicate;
+  EDKII_CRYPTO_HMAC_SHA384_UPDATE                     HmacSha384Update;
+  EDKII_CRYPTO_HMAC_SHA384_FINAL                      HmacSha384Final;
+  EDKII_CRYPTO_HMAC_SHA384_ALL                        HmacSha384All;
   /// HKDF (continued)
-  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT                  HkdfSha256Extract;
-  EDKII_CRYPTO_HKDF_SHA_256_EXPAND                   HkdfSha256Expand;
-  EDKII_CRYPTO_HKDF_SHA_384_EXTRACT_AND_EXPAND       HkdfSha384ExtractAndExpand;
-  EDKII_CRYPTO_HKDF_SHA_384_EXTRACT                  HkdfSha384Extract;
-  EDKII_CRYPTO_HKDF_SHA_384_EXPAND                   HkdfSha384Expand;
+  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT                   HkdfSha256Extract;
+  EDKII_CRYPTO_HKDF_SHA_256_EXPAND                    HkdfSha256Expand;
+  EDKII_CRYPTO_HKDF_SHA_384_EXTRACT_AND_EXPAND        HkdfSha384ExtractAndExpand;
+  EDKII_CRYPTO_HKDF_SHA_384_EXTRACT                   HkdfSha384Extract;
+  EDKII_CRYPTO_HKDF_SHA_384_EXPAND                    HkdfSha384Expand;
   /// AEAD AES-GCM
-  EDKII_AEAD_AES_GCM_ENCRYPT                         AeadAesGcmEncrypt;
-  EDKII_AEAD_AES_GCM_DECRYPT                         AeadAesGcmDecrypt;
+  EDKII_AEAD_AES_GCM_ENCRYPT                          AeadAesGcmEncrypt;
+  EDKII_AEAD_AES_GCM_DECRYPT                          AeadAesGcmDecrypt;
   /// BIGNUM
-  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] 6+ messages in thread

* [PATCH V5 3/4] CryptoPkg: Add ECC related usage reference
  2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
  2022-09-25  9:26 ` [PATCH V5 1/4] " yi1 li
  2022-09-25  9:26 ` [PATCH V5 2/4] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
@ 2022-09-25  9:26 ` yi1 li
  2022-09-25  9:26 ` [PATCH V5 4/4] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
  2022-09-26  7:11 ` [PATCH V5 0/4] CryptoPkg: Add EC support Yao, Jiewen
  4 siblings, 0 replies; 6+ messages in thread
From: yi1 li @ 2022-09-25  9:26 UTC (permalink / raw)
  To: devel
  Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang,
	Michael D Kinney

Describes the use cases under which ECC needs to be enabled,
and provides the impact on memory size for developers' reference.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/CryptoPkg.dec | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/CryptoPkg/CryptoPkg.dec b/CryptoPkg/CryptoPkg.dec
index d9b64e5763..a3716864fd 100644
--- a/CryptoPkg/CryptoPkg.dec
+++ b/CryptoPkg/CryptoPkg.dec
@@ -83,7 +83,36 @@
 
   ## Enable/Disable the ECC feature in openssl library. The default is disabled.
   #  If ECC feature is disabled, all related source files will not be compiled.
+  # @Prompt Enable/Disable ECC feature in EDK II Crypto
   gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled|FALSE|BOOLEAN|0x0000003
+  # Set it to TRUE if:
+  # 1) Platform needs ECC in TLS, or asymmetric cryptography services such as
+  #    X509 certificate or PEM format data processing.
+  # 2) Platform needs to enable PcdCryptoServiceFamilyEnable.Ec service.
+  # Please note:
+  # ECC feature will cause a significant memory increase, approximate memory impact
+  # in below table for reference by platform developers with FW size limitations.
+  #                                   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
 
 [UserExtensions.TianoCore."ExtraFiles"]
   CryptoPkgExtra.uni
-- 
2.31.1.windows.1


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

* [PATCH V5 4/4] CryptoPkg/Test: Add unit test for CryptoEc
  2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
                   ` (2 preceding siblings ...)
  2022-09-25  9:26 ` [PATCH V5 3/4] CryptoPkg: Add ECC related usage reference yi1 li
@ 2022-09-25  9:26 ` yi1 li
  2022-09-26  7:11 ` [PATCH V5 0/4] CryptoPkg: Add EC support Yao, Jiewen
  4 siblings, 0 replies; 6+ messages in thread
From: yi1 li @ 2022-09-25  9:26 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 6891db97fb..168e24e4c0 100644
--- a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
@@ -48,6 +48,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 8450e95172..63bae35b80 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
@@ -28,6 +28,7 @@ SUITE_DESC  mSuiteDesc[] = {
   { "Hkdf extract and expand tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mHkdfTestNum,           mHkdfTest           },
   { "Aead AES Gcm tests",            "CryptoPkg.BaseCryptLib", NULL, NULL, &mAeadAesGcmTestNum,     mAeadAesGcmTest     },
   { "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 fc44030ff6..3a84e63a87 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -95,6 +95,8 @@ extern TEST_DESC  mAeadAesGcmTest[];
 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 40dfade717..023b796946 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -40,6 +40,7 @@
   HkdfTests.c
   AeadAesGcmTests.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 00e6b088b8..5bfd190236 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -39,6 +39,7 @@
   HkdfTests.c
   AeadAesGcmTests.c
   BnTests.c
+  EcTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.31.1.windows.1


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

* Re: [PATCH V5 0/4] CryptoPkg: Add EC support
  2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
                   ` (3 preceding siblings ...)
  2022-09-25  9:26 ` [PATCH V5 4/4] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
@ 2022-09-26  7:11 ` Yao, Jiewen
  4 siblings, 0 replies; 6+ messages in thread
From: Yao, Jiewen @ 2022-09-26  7:11 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Kinney, Michael D

Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>

Merged https://github.com/tianocore/edk2/pull/3403, with minor typo fix.

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Sunday, September 25, 2022 5:26 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>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: [PATCH V5 0/4] CryptoPkg: Add EC support
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> 
> Review PR: https://github.com/tianocore/edk2/pull/3398
> This patch sequence is used to add CryptEc library, which are wrapped
> over OpenSSL. The implementation provides library functions for EFI
> BaseCrypt protocol and EFI BaseCrypt Configuration Protocol.
> 
> All APIs passed unit test and fuzzing test, detail as:
> 1. Unit test:
> The purpose of unit testing is to ensure that the function obtains the
> expected result under specific input, that is, to ensure the correctness
> of APIs.
> All test case show in patch 3 :CryptoPkg/Test: Add unit test for CryptoEc.
> 2. Fuzzing test:
> Various Fuzz Testing are employed across the all introduced APIs, and the
> test is used AFL (2.52b) and Libfuzzer (clang+llvm-11.0.0) as the fuzzer,
> based on HBFA.
> Fuzzing Pass Rate is 100%;
> The Code Coverage new APIs is 90.3%.
> All test case show in:
> https://github.com/liyi77/edk2-
> staging/tree/HBFA/HBFA/UefiHostFuzzTestCasePkg/TestCase/CryptoPkg
> 
> V2 change:
> 1. Squash uncrustify tool update into previous patch.
> 2. Increase EDKII_CRYPTO_VERSION to 10.
> V3 change:
> Fix typo in comment.
> V4 change:
> Add ECC related usage reference
> V5 change:
> Optimized the description of ECC reference
> 
> Tested-by: Yi Li <yi1.li@intel.com>
> 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>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> 
> Signed-off-by: Yi Li <yi1.li@intel.com>
> 
> Yi Li (4):
>   CryptoPkg: Add EC support
>   CryptoPkg: Add EC APIs to DXE and protocol
>   CryptoPkg: Add ECC related usage reference
>   CryptoPkg/Test: Add unit test for CryptoEc
> 
>  CryptoPkg/CryptoPkg.dec                       |  29 +
>  CryptoPkg/CryptoPkg.dsc                       |   1 +
>  CryptoPkg/Driver/Crypto.c                     | 496 +++++++++++
>  CryptoPkg/Include/Library/BaseCryptLib.h      | 424 +++++++++
>  .../Pcd/PcdCryptoServiceFamilyEnable.h        |  25 +
>  .../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 +
>  .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |   2 +
>  .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
>  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 +++++++++++
>  .../BaseCryptLibOnProtocolPpi/CryptLib.c      | 469 ++++++++++
>  CryptoPkg/Private/Protocol/Crypto.h           | 831 +++++++++++++-----
>  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 +
>  21 files changed, 4137 insertions(+), 200 deletions(-)
>  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
>  create mode 100644
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
> 
> --
> 2.31.1.windows.1


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

end of thread, other threads:[~2022-09-26  7:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-25  9:26 [PATCH V5 0/4] CryptoPkg: Add EC support yi1 li
2022-09-25  9:26 ` [PATCH V5 1/4] " yi1 li
2022-09-25  9:26 ` [PATCH V5 2/4] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
2022-09-25  9:26 ` [PATCH V5 3/4] CryptoPkg: Add ECC related usage reference yi1 li
2022-09-25  9:26 ` [PATCH V5 4/4] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
2022-09-26  7:11 ` [PATCH V5 0/4] CryptoPkg: Add EC support Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox