* [PATCH V2 1/3] CryptoPkg: Add EC support
[not found] <cover.1663735439.git.yi1.li@intel.com>
@ 2022-09-21 4:54 ` yi1 li
2022-09-21 16:21 ` [edk2-devel] " Michael D Kinney
2022-09-21 4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
2022-09-21 4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
2 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-21 4:54 UTC (permalink / raw)
To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
This patch is used to add CryptEc library, which is wrapped
over OpenSSL.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
.../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
.../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
.../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
.../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
.../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
.../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
8 files changed, 2186 insertions(+)
create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index b253923dd8..d74fc21c1e 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Uefi/UefiBaseType.h>
+#define CRYPTO_NID_NULL 0x0000
+
+// Key Exchange
+#define CRYPTO_NID_SECP256R1 0x0204
+#define CRYPTO_NID_SECP384R1 0x0205
+#define CRYPTO_NID_SECP521R1 0x0206
+
///
/// MD5 digest size in bytes
///
@@ -2850,4 +2857,421 @@ BigNumAddMod (
OUT VOID *BnRes
);
+// =====================================================================================
+// Basic Elliptic Curve Primitives
+// =====================================================================================
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+ IN UINTN CryptoNid
+ );
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient.
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ );
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+ IN VOID *EcGroup
+ );
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+ IN CONST VOID *EcGroup
+ );
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ );
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ );
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ );
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ );
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ );
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ );
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ );
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ );
+
+// =====================================================================================
+// Elliptic Curve Diffie Hellman Primitives
+// =====================================================================================
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+ IN UINTN Nid
+ );
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+ IN VOID *EcContext
+ );
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ );
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ );
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ );
+
#endif // __BASE_CRYPT_LIB_H__
diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
index 9e4be2fb0d..ade6ee3fdd 100644
--- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -52,6 +52,8 @@
Pk/CryptTs.c
Pk/CryptRsaPss.c
Pk/CryptRsaPssSign.c
+ Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
+ Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
Pem/CryptPem.c
Bn/CryptBn.c
diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
index 65ad23fb81..383df2b23c 100644
--- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -58,6 +58,7 @@
Pk/CryptTsNull.c
Pk/CryptRsaPss.c
Pk/CryptRsaPssSignNull.c
+ Pk/CryptEcNull.c
Pem/CryptPemNull.c
Rand/CryptRandNull.c
Bn/CryptBnNull.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
new file mode 100644
index 0000000000..396c819834
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
@@ -0,0 +1,765 @@
+/** @file
+ Elliptic Curve and ECDH API implementation based on OpenSSL
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <openssl/objects.h>
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+
+// =====================================================================================
+// Basic Elliptic Curve Primitives
+// =====================================================================================
+
+/**
+ Return the Nid of certain ECC curve.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval !=-1 On success.
+ @retval -1 ECC curve not supported.
+**/
+STATIC
+INT32
+CryptoNidToOpensslNid (
+ IN UINTN CryptoNid
+ )
+{
+ INT32 Nid;
+
+ switch (CryptoNid) {
+ case CRYPTO_NID_SECP256R1:
+ Nid = NID_X9_62_prime256v1;
+ break;
+ case CRYPTO_NID_SECP384R1:
+ Nid = NID_secp384r1;
+ break;
+ case CRYPTO_NID_SECP521R1:
+ Nid = NID_secp521r1;
+ break;
+ default:
+ return -1;
+ }
+
+ return Nid;
+}
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+ IN UINTN CryptoNid
+ )
+{
+ INT32 Nid;
+
+ Nid = CryptoNidToOpensslNid (CryptoNid);
+
+ if (Nid < 0) {
+ return NULL;
+ }
+
+ return EC_GROUP_new_by_curve_name (Nid);
+}
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient..
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
+}
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ )
+{
+ return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
+}
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+ IN VOID *EcGroup
+ )
+{
+ EC_GROUP_free (EcGroup);
+}
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+ IN CONST VOID *EcGroup
+ )
+{
+ return EC_POINT_new (EcGroup);
+}
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ )
+{
+ if (Clear) {
+ EC_POINT_clear_free (EcPoint);
+ } else {
+ EC_POINT_free (EcPoint);
+ }
+}
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
+}
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
+}
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
+}
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
+}
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
+}
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
+}
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ )
+{
+ return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
+}
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
+}
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ )
+{
+ return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
+}
+
+// =====================================================================================
+// Elliptic Curve Diffie Hellman Primitives
+// =====================================================================================
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+ IN UINTN Nid
+ )
+{
+ INT32 OpenSslNid;
+
+ OpenSslNid = CryptoNidToOpensslNid (Nid);
+ if (OpenSslNid < 0) {
+ return NULL;
+ }
+
+ return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
+}
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+ IN VOID *EcContext
+ )
+{
+ EC_KEY_free ((EC_KEY *)EcContext);
+}
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ EC_KEY *EcKey;
+ CONST EC_GROUP *Group;
+ CONST EC_POINT *EcPoint;
+ BOOLEAN RetVal;
+ BIGNUM *BnX;
+ BIGNUM *BnY;
+ UINTN HalfSize;
+ INTN XSize;
+ INTN YSize;
+
+ if ((EcContext == NULL) || (PublicKeySize == NULL)) {
+ return FALSE;
+ }
+
+ if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
+ return FALSE;
+ }
+
+ EcKey = (EC_KEY *)EcContext;
+ Group = EC_KEY_get0_group (EcKey);
+ HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
+
+ // Assume RAND_seed was called
+ if (EC_KEY_generate_key (EcKey) != 1) {
+ return FALSE;
+ }
+
+ if (*PublicKeySize < HalfSize * 2) {
+ *PublicKeySize = HalfSize * 2;
+ return FALSE;
+ }
+
+ *PublicKeySize = HalfSize * 2;
+
+ EcPoint = EC_KEY_get0_public_key (EcKey);
+ if (EcPoint == NULL) {
+ return FALSE;
+ }
+
+ RetVal = FALSE;
+ BnX = BN_new ();
+ BnY = BN_new ();
+ if ((BnX == NULL) || (BnY == NULL)) {
+ goto fail;
+ }
+
+ if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
+ goto fail;
+ }
+
+ XSize = BN_num_bytes (BnX);
+ YSize = BN_num_bytes (BnY);
+ if ((XSize <= 0) || (YSize <= 0)) {
+ goto fail;
+ }
+
+ ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
+
+ ZeroMem (PublicKey, *PublicKeySize);
+ BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
+ BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
+
+ RetVal = TRUE;
+
+fail:
+ BN_free (BnX);
+ BN_free (BnY);
+ return RetVal;
+}
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ EC_KEY *EcKey;
+ CONST EC_GROUP *Group;
+ CONST EC_POINT *EcPoint;
+ BIGNUM *BnX;
+ BIGNUM *BnY;
+ UINTN HalfSize;
+ INTN XSize;
+ INTN YSize;
+ BOOLEAN RetVal;
+
+ if ((EcContext == NULL) || (PublicKeySize == NULL)) {
+ return FALSE;
+ }
+
+ if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
+ return FALSE;
+ }
+
+ EcKey = (EC_KEY *)EcContext;
+ Group = EC_KEY_get0_group (EcKey);
+ HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
+ if (*PublicKeySize < HalfSize * 2) {
+ *PublicKeySize = HalfSize * 2;
+ return FALSE;
+ }
+
+ *PublicKeySize = HalfSize * 2;
+
+ EcPoint = EC_KEY_get0_public_key (EcKey);
+ if (EcPoint == NULL) {
+ return FALSE;
+ }
+
+ RetVal = FALSE;
+ BnX = BN_new ();
+ BnY = BN_new ();
+ if ((BnX == NULL) || (BnY == NULL)) {
+ goto fail;
+ }
+
+ if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
+ goto fail;
+ }
+
+ XSize = BN_num_bytes (BnX);
+ YSize = BN_num_bytes (BnY);
+ if ((XSize <= 0) || (YSize <= 0)) {
+ goto fail;
+ }
+
+ ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
+
+ if (PublicKey != NULL) {
+ ZeroMem (PublicKey, *PublicKeySize);
+ BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
+ BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
+ }
+
+ RetVal = TRUE;
+
+fail:
+ BN_free (BnX);
+ BN_free (BnY);
+ return RetVal;
+}
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If public key is compressed, the PeerPublic will only contain half key (X).
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ )
+{
+ EC_KEY *EcKey;
+ EC_KEY *PeerEcKey;
+ CONST EC_GROUP *Group;
+ BOOLEAN RetVal;
+ BIGNUM *BnX;
+ BIGNUM *BnY;
+ EC_POINT *Point;
+ INT32 OpenSslNid;
+ UINTN HalfSize;
+
+ if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
+ return FALSE;
+ }
+
+ if ((Key == NULL) && (*KeySize != 0)) {
+ return FALSE;
+ }
+
+ if (PeerPublicSize > INT_MAX) {
+ return FALSE;
+ }
+
+ EcKey = (EC_KEY *)EcContext;
+ Group = EC_KEY_get0_group (EcKey);
+ HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
+ if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
+ return FALSE;
+ }
+
+ if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
+ return FALSE;
+ }
+
+ if (*KeySize < HalfSize) {
+ *KeySize = HalfSize;
+ return FALSE;
+ }
+
+ *KeySize = HalfSize;
+
+ RetVal = FALSE;
+ Point = NULL;
+ BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
+ BnY = NULL;
+ Point = EC_POINT_new (Group);
+ PeerEcKey = NULL;
+ if ((BnX == NULL) || (Point == NULL)) {
+ goto fail;
+ }
+
+ if (CompressFlag == NULL) {
+ BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
+ if (BnY == NULL) {
+ goto fail;
+ }
+
+ if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
+ goto fail;
+ }
+ } else {
+ if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
+ goto fail;
+ }
+ }
+
+ // Validate NIST ECDH public key
+ OpenSslNid = EC_GROUP_get_curve_name (Group);
+ PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
+ if (PeerEcKey == NULL) {
+ goto fail;
+ }
+
+ if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
+ goto fail;
+ }
+
+ if (EC_KEY_check_key (PeerEcKey) != 1) {
+ goto fail;
+ }
+
+ if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
+ goto fail;
+ }
+
+ RetVal = TRUE;
+
+fail:
+ BN_free (BnX);
+ BN_free (BnY);
+ EC_POINT_free (Point);
+ EC_KEY_free (PeerEcKey);
+ return RetVal;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
new file mode 100644
index 0000000000..d9f1004f6c
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
@@ -0,0 +1,496 @@
+/** @file
+ Elliptic Curve and ECDH API implementation based on OpenSSL
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseCryptLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+ IN UINTN CryptoNid
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient..
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+ IN VOID *EcGroup
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+ IN CONST VOID *EcGroup
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+ IN UINTN Nid
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+ IN VOID *EcContext
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index ce6a789dfd..4bc3063485 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -59,6 +59,7 @@
Pk/CryptTsNull.c
Pk/CryptRsaPss.c
Pk/CryptRsaPssSignNull.c
+ Pk/CryptEcNull.c
Pem/CryptPem.c
Bn/CryptBnNull.c
diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
index 354f3d80aa..e1a57ef09f 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
+++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -49,6 +49,7 @@
Pk/CryptX509Null.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
+ Pk/CryptEcNull.c
Pem/CryptPemNull.c
Rand/CryptRandNull.c
Pk/CryptRsaPssNull.c
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
new file mode 100644
index 0000000000..d9f1004f6c
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
@@ -0,0 +1,496 @@
+/** @file
+ Elliptic Curve and ECDH API implementation based on OpenSSL
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseCryptLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+ IN UINTN CryptoNid
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient..
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+ IN VOID *EcGroup
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+ IN CONST VOID *EcGroup
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+ IN UINTN Nid
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+ IN VOID *EcContext
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
--
2.31.1.windows.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol
[not found] <cover.1663735439.git.yi1.li@intel.com>
2022-09-21 4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
@ 2022-09-21 4:54 ` yi1 li
2022-09-21 4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
2 siblings, 0 replies; 17+ messages in thread
From: yi1 li @ 2022-09-21 4:54 UTC (permalink / raw)
To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
The implementation provides CryptEc library functions
for EFI Driveer and EFI BaseCrypt Protocol.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
CryptoPkg/CryptoPkg.dsc | 1 +
CryptoPkg/Driver/Crypto.c | 496 +++++++++++
.../Pcd/PcdCryptoServiceFamilyEnable.h | 25 +
.../BaseCryptLibOnProtocolPpi/CryptLib.c | 469 ++++++++++
CryptoPkg/Private/Protocol/Crypto.h | 801 ++++++++++++++----
5 files changed, 1607 insertions(+), 185 deletions(-)
diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index a766851728..4f6cece6ee 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -169,6 +169,7 @@
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsSet.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsGet.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Bn.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
+ gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Ec.Family | 0
!endif
!if $(CRYPTO_SERVICES) == MIN_PEI
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index 07150ad2f2..9682a46778 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -5074,6 +5074,481 @@ CryptoServiceBigNumAddMod (
return CALL_BASECRYPTLIB (Bn.Services.AddMod, BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
}
+// =====================================================================================
+// Basic Elliptic Curve Primitives
+// =====================================================================================
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcGroupInit (
+ IN UINTN CryptoNid
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GroupInit, EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient.
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GroupGetCurve, EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GroupGetOrder, EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+CryptoServiceEcGroupFree (
+ IN VOID *EcGroup
+ )
+{
+ CALL_VOID_BASECRYPTLIB (Ec.Services.GroupFree, EcGroupFree, (EcGroup));
+}
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcPointInit (
+ IN CONST VOID *EcGroup
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointInit, EcPointInit, (EcGroup), NULL);
+}
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+CryptoServiceEcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ )
+{
+ CALL_VOID_BASECRYPTLIB (Ec.Services.PointDeInit, EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointGetAffineCoordinates, EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointSetAffineCoordinates, EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointAdd, EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointMul, EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointInvert, EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointIsOnCurve, EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointIsAtInfinity, EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointEqual, EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.PointSetCompressedCoordinates, EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+// =====================================================================================
+// Elliptic Curve Diffie Hellman Primitives
+// =====================================================================================
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcNewByNid (
+ IN UINTN Nid
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.NewByNid, EcNewByNid, (Nid), NULL);
+}
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+CryptoServiceEcFree (
+ IN VOID *EcContext
+ )
+{
+ CALL_VOID_BASECRYPTLIB (Ec.Services.Free, EcFree, (EcContext));
+}
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GenerateKey, EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GetPubKey, EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
+}
+
const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
/// Version
CryptoServiceGetCryptoVersion,
@@ -5306,4 +5781,25 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
CryptoServiceBigNumContextFree,
CryptoServiceBigNumSetUint,
CryptoServiceBigNumAddMod,
+ /// EC
+ CryptoServiceEcGroupInit,
+ CryptoServiceEcGroupGetCurve,
+ CryptoServiceEcGroupGetOrder,
+ CryptoServiceEcGroupFree,
+ CryptoServiceEcPointInit,
+ CryptoServiceEcPointDeInit,
+ CryptoServiceEcPointGetAffineCoordinates,
+ CryptoServiceEcPointSetAffineCoordinates,
+ CryptoServiceEcPointAdd,
+ CryptoServiceEcPointMul,
+ CryptoServiceEcPointInvert,
+ CryptoServiceEcPointIsOnCurve,
+ CryptoServiceEcPointIsAtInfinity,
+ CryptoServiceEcPointEqual,
+ CryptoServiceEcPointSetCompressedCoordinates,
+ CryptoServiceEcNewByNid,
+ CryptoServiceEcFree,
+ CryptoServiceEcGenerateKey,
+ CryptoServiceEcGetPubKey,
+ CryptoServiceEcDhComputeKey,
};
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 1b3c9d8f52..65ea7807dc 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -331,6 +331,31 @@ typedef struct {
} Services;
UINT32 Family;
} Bn;
+ union {
+ struct {
+ UINT8 GroupInit : 1;
+ UINT8 GroupGetCurve : 1;
+ UINT8 GroupGetOrder : 1;
+ UINT8 GroupFree : 1;
+ UINT8 PointInit : 1;
+ UINT8 PointDeInit : 1;
+ UINT8 PointGetAffineCoordinates : 1;
+ UINT8 PointSetAffineCoordinates : 1;
+ UINT8 PointAdd : 1;
+ UINT8 PointMul : 1;
+ UINT8 PointInvert : 1;
+ UINT8 PointIsOnCurve : 1;
+ UINT8 PointIsAtInfinity : 1;
+ UINT8 PointEqual : 1;
+ UINT8 PointSetCompressedCoordinates : 1;
+ UINT8 NewByNid : 1;
+ UINT8 Free : 1;
+ UINT8 GenerateKey : 1;
+ UINT8 GetPubKey : 1;
+ UINT8 DhComputeKey : 1;
+ } Services;
+ UINT32 Family;
+ } Ec;
} PCD_CRYPTO_SERVICE_FAMILY_ENABLE;
#endif
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index c5d71b5269..3746c823d9 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -4104,3 +4104,472 @@ BigNumAddMod (
{
CALL_CRYPTO_SERVICE (BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
}
+
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+ IN UINTN CryptoNid
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient.
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnOrder Group prime number.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+ Free previously allocated EC group object using EcGroupInit().
+
+ @param[in] EcGroup EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+ IN VOID *EcGroup
+ )
+{
+ CALL_VOID_CRYPTO_SERVICE (EcGroupFree, (EcGroup));
+}
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit().
+
+ @retval EC Point object On success.
+ @retval NULL On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+ IN CONST VOID *EcGroup
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointInit, (EcGroup), NULL);
+}
+
+/**
+ Free previously allocated EC Point object using EcPointInit().
+
+ @param[in] EcPoint EC Point to free.
+ @param[in] Clear TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ )
+{
+ CALL_VOID_CRYPTO_SERVICE (EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[out] BnX X coordinate.
+ @param[out] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point object.
+ @param[in] BnX X coordinate.
+ @param[in] BnY Y coordinate.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point.
+ @param[in] EcPointB EC Point.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+ @param[in] EcGroup EC group object.
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point.
+ @param[in] BnPScalar P Scalar.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object.
+ @param[in,out] EcPoint EC point to invert.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+ Check if the supplied point is on EC curve.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On curve.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+ Check if the supplied point is at infinity.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC point to check.
+
+ @retval TRUE At infinity.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+ Check if EC points are equal.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPointA EC point A.
+ @param[in] EcPointB EC point B.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE A == B.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object.
+ @param[in] EcPoint EC Point.
+ @param[in] BnX X coordinate.
+ @param[in] YBit 0 or 1 to identify which Y value is used.
+ @param[in] BnCtx BN context, created with BigNumNewContext().
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ )
+{
+ CALL_CRYPTO_SERVICE (EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+ IN UINTN Nid
+ )
+{
+ CALL_CRYPTO_SERVICE (EcNewByNid, (Nid), NULL);
+}
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+ IN VOID *EcContext
+ )
+{
+ CALL_VOID_CRYPTO_SERVICE (EcFree, (EcContext));
+}
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to the buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ )
+{
+ CALL_CRYPTO_SERVICE (EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
+}
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index 9812568cc7..aa4bfefdd2 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -21,7 +21,7 @@
/// the EDK II Crypto Protocol is extended, this version define must be
/// increased.
///
-#define EDKII_CRYPTO_VERSION 9
+#define EDKII_CRYPTO_VERSION 10
///
/// EDK II Crypto Protocol forward declaration
@@ -3887,221 +3887,652 @@ BOOLEAN
OUT VOID *BnRes
);
+/**
+ Initialize new opaque EcGroup object. This object represents an EC curve and
+ and is used for calculation within this group. This object should be freed
+ using EcGroupFree() function.
+
+ @param[in] CryptoNid Identifying number for the ECC curve (Defined in
+ BaseCryptLib.h).
+
+ @retval EcGroup object On success
+ @retval NULL On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_INIT)(
+ IN UINTN CryptoNid
+ );
+
+/**
+ Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object.
+ @param[out] BnPrime Group prime number.
+ @param[out] BnA A coefficient.
+ @param[out] BnB B coefficient.
+ @param[in] BnCtx BN context.
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_CURVE)(
+ IN CONST VOID *EcGroup,
+ OUT VOID *BnPrime,
+ OUT VOID *BnA,
+ OUT VOID *BnB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Get EC group order.
+ This function will set the provided Big Number object to the corresponding
+ value. The caller needs to make sure that the "out" BigNumber parameter
+ is properly initialized.
+
+ @param[in] EcGroup EC group object
+ @param[out] BnOrder Group prime number
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_ORDER)(
+ IN VOID *EcGroup,
+ OUT VOID *BnOrder
+ );
+
+/**
+ Free previously allocated EC group object using EcGroupInit()
+
+ @param[in] EcGroup EC group object to free
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_FREE)(
+ IN VOID *EcGroup
+ );
+
+/**
+ Initialize new opaque EC Point object. This object represents an EC point
+ within the given EC group (curve).
+
+ @param[in] EC Group, properly initialized using EcGroupInit()
+
+ @retval EC Point object On success
+ @retval NULL On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INIT)(
+ IN CONST VOID *EcGroup
+ );
+
+/**
+ Free previously allocated EC Point object using EcPointInit()
+
+ @param[in] EcPoint EC Point to free
+ @param[in] Clear TRUE iff the memory should be cleared
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_POINT_DE_INIT)(
+ IN VOID *EcPoint,
+ IN BOOLEAN Clear
+ );
+
+/**
+ Get EC point affine (x,y) coordinates.
+ This function will set the provided Big Number objects to the corresponding
+ values. The caller needs to make sure all the "out" BigNumber parameters
+ are properly initialized.
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPoint EC point object
+ @param[out] BnX X coordinate
+ @param[out] BnY Y coordinate
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES)(
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ OUT VOID *BnX,
+ OUT VOID *BnY,
+ IN VOID *BnCtx
+ );
+
+/**
+ Set EC point affine (x,y) coordinates.
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPoint EC point object
+ @param[in] BnX X coordinate
+ @param[in] BnY Y coordinate
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES)(
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN CONST VOID *BnY,
+ IN VOID *BnCtx
+ );
+
+/**
+ EC Point addition. EcPointResult = EcPointA + EcPointB
+
+ @param[in] EcGroup EC group object
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPointA EC Point
+ @param[in] EcPointB EC Point
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_ADD)(
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar
+
+ @param[in] EcGroup EC group object
+ @param[out] EcPointResult EC point to hold the result. The point should
+ be properly initialized.
+ @param[in] EcPoint EC Point
+ @param[in] BnPScalar P Scalar
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_MUL)(
+ IN CONST VOID *EcGroup,
+ OUT VOID *EcPointResult,
+ IN CONST VOID *EcPoint,
+ IN CONST VOID *BnPScalar,
+ IN VOID *BnCtx
+ );
+
+/**
+ Calculate the inverse of the supplied EC point.
+
+ @param[in] EcGroup EC group object
+ @param[in,out] EcPoint EC point to invert
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INVERT)(
+ IN CONST VOID *EcGroup,
+ IN OUT VOID *EcPoint,
+ IN VOID *BnCtx
+ );
+
+/**
+ Check if the supplied point is on EC curve
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPoint EC point to check
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On curve
+ @retval FALSE Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_ON_CURVE)(
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint,
+ IN VOID *BnCtx
+ );
+
+/**
+ Check if the supplied point is at infinity
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPoint EC point to check
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE At infinity
+ @retval FALSE Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY)(
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPoint
+ );
+
+/**
+ Check if EC points are equal
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPointA EC point A
+ @param[in] EcPointB EC point B
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE A == B
+ @retval FALSE Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_EQUAL)(
+ IN CONST VOID *EcGroup,
+ IN CONST VOID *EcPointA,
+ IN CONST VOID *EcPointB,
+ IN VOID *BnCtx
+ );
+
+/**
+ Set EC point compressed coordinates. Points can be described in terms of
+ their compressed coordinates. For a point (x, y), for any given value for x
+ such that the point is on the curve there will only ever be two possible
+ values for y. Therefore, a point can be set using this function where BnX is
+ the x coordinate and YBit is a value 0 or 1 to identify which of the two
+ possible values for y should be used.
+
+ @param[in] EcGroup EC group object
+ @param[in] EcPoint EC Point
+ @param[in] BnX X coordinate
+ @param[in] YBit 0 or 1 to identify which Y value is used
+ @param[in] BnCtx BN context, created with BigNumNewContext()
+
+ @retval TRUE On success.
+ @retval FALSE Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES)(
+ IN CONST VOID *EcGroup,
+ IN VOID *EcPoint,
+ IN CONST VOID *BnX,
+ IN UINT8 YBit,
+ IN VOID *BnCtx
+ );
+
+/**
+ Allocates and Initializes one Elliptic Curve Context for subsequent use
+ with the NID.
+
+ @param[in] Nid cipher NID
+ @return Pointer to the Elliptic Curve Context that has been initialized.
+ If the allocations fails, EcNewByNid() returns NULL.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_NEW_BY_NID)(
+ IN UINTN Nid
+ );
+
+/**
+ Release the specified EC context.
+
+ @param[in] EcContext Pointer to the EC context to be released.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_FREE)(
+ IN VOID *EcContext
+ );
+
+/**
+ Generates EC key and returns EC public key (X, Y), Please note, this function uses
+ pseudo random number generator. The caller must make sure RandomSeed()
+ function was properly called before.
+ The Ec context should be correctly initialized by EcNewByNid.
+ This function generates random secret, and computes the public key (X, Y), which is
+ returned via parameter Public, PublicSize.
+ X is the first half of Public with size being PublicSize / 2,
+ Y is the second half of Public with size being PublicSize / 2.
+ EC context is updated accordingly.
+ If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+ PublicSize is set to the required buffer size to obtain the public X, Y.
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ If EcContext is NULL, then return FALSE.
+ If PublicSize is NULL, then return FALSE.
+ If PublicSize is large enough but Public is NULL, then return FALSE.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC public X,Y generation succeeded.
+ @retval FALSE EC public X,Y generation failed.
+ @retval FALSE PublicKeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GENERATE_KEY)(
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ );
+
+/**
+ Gets the public key component from the established EC context.
+ The Ec context should be correctly initialized by EcNewByNid, and successfully
+ generate key pair from EcGenerateKey().
+ For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to EC context being set.
+ @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
+ @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
+ On output, the size of data returned in Public buffer in bytes.
+ @retval TRUE EC key component was retrieved successfully.
+ @retval FALSE Invalid EC key component.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GET_PUB_KEY)(
+ IN OUT VOID *EcContext,
+ OUT UINT8 *PublicKey,
+ IN OUT UINTN *PublicKeySize
+ );
+
+/**
+ Computes exchanged common key.
+ Given peer's public key (X, Y), this function computes the exchanged common key,
+ based on its own context including value of curve parameter and random secret.
+ X is the first half of PeerPublic with size being PeerPublicSize / 2,
+ Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+ If EcContext is NULL, then return FALSE.
+ If PeerPublic is NULL, then return FALSE.
+ If PeerPublicSize is 0, then return FALSE.
+ If Key is NULL, then return FALSE.
+ If KeySize is not large enough, then return FALSE.
+ For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+ For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+ For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+ @param[in, out] EcContext Pointer to the EC context.
+ @param[in] PeerPublic Pointer to the peer's public X,Y.
+ @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
+ @param[in] CompressFlag Flag of PeerPublic is compressed or not.
+ @param[out] Key Pointer to the buffer to receive generated key.
+ @param[in, out] KeySize On input, the size of Key buffer in bytes.
+ On output, the size of data returned in Key buffer in bytes.
+ @retval TRUE EC exchanged key generation succeeded.
+ @retval FALSE EC exchanged key generation failed.
+ @retval FALSE KeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_DH_COMPUTE_KEY)(
+ IN OUT VOID *EcContext,
+ IN CONST UINT8 *PeerPublic,
+ IN UINTN PeerPublicSize,
+ IN CONST INT32 *CompressFlag,
+ OUT UINT8 *Key,
+ IN OUT UINTN *KeySize
+ );
+
///
/// EDK II Crypto Protocol
///
struct _EDKII_CRYPTO_PROTOCOL {
/// Version
- EDKII_CRYPTO_GET_VERSION GetVersion;
+ EDKII_CRYPTO_GET_VERSION GetVersion;
/// HMAC MD5 - deprecated and unsupported
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW DeprecatedHmacMd5New;
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE DeprecatedHmacMd5Free;
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY DeprecatedHmacMd5SetKey;
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE DeprecatedHmacMd5Duplicate;
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE DeprecatedHmacMd5Update;
- DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL DeprecatedHmacMd5Final;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW DeprecatedHmacMd5New;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE DeprecatedHmacMd5Free;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY DeprecatedHmacMd5SetKey;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE DeprecatedHmacMd5Duplicate;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE DeprecatedHmacMd5Update;
+ DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL DeprecatedHmacMd5Final;
/// HMAC SHA1 - deprecated and unsupported
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW DeprecatedHmacSha1New;
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE DeprecatedHmacSha1Free;
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY DeprecatedHmacSha1SetKey;
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE DeprecatedHmacSha1Duplicate;
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE DeprecatedHmacSha1Update;
- DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL DeprecatedHmacSha1Final;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW DeprecatedHmacSha1New;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE DeprecatedHmacSha1Free;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY DeprecatedHmacSha1SetKey;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE DeprecatedHmacSha1Duplicate;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE DeprecatedHmacSha1Update;
+ DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL DeprecatedHmacSha1Final;
/// HMAC SHA256
- EDKII_CRYPTO_HMAC_SHA256_NEW HmacSha256New;
- EDKII_CRYPTO_HMAC_SHA256_FREE HmacSha256Free;
- EDKII_CRYPTO_HMAC_SHA256_SET_KEY HmacSha256SetKey;
- EDKII_CRYPTO_HMAC_SHA256_DUPLICATE HmacSha256Duplicate;
- EDKII_CRYPTO_HMAC_SHA256_UPDATE HmacSha256Update;
- EDKII_CRYPTO_HMAC_SHA256_FINAL HmacSha256Final;
+ EDKII_CRYPTO_HMAC_SHA256_NEW HmacSha256New;
+ EDKII_CRYPTO_HMAC_SHA256_FREE HmacSha256Free;
+ EDKII_CRYPTO_HMAC_SHA256_SET_KEY HmacSha256SetKey;
+ EDKII_CRYPTO_HMAC_SHA256_DUPLICATE HmacSha256Duplicate;
+ EDKII_CRYPTO_HMAC_SHA256_UPDATE HmacSha256Update;
+ EDKII_CRYPTO_HMAC_SHA256_FINAL HmacSha256Final;
/// Md4 - deprecated and unsupported
- DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE DeprecatedMd4GetContextSize;
- DEPRECATED_EDKII_CRYPTO_MD4_INIT DeprecatedMd4Init;
- DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE DeprecatedMd4Duplicate;
- DEPRECATED_EDKII_CRYPTO_MD4_UPDATE DeprecatedMd4Update;
- DEPRECATED_EDKII_CRYPTO_MD4_FINAL DeprecatedMd4Final;
- DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL DeprecatedMd4HashAll;
+ DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE DeprecatedMd4GetContextSize;
+ DEPRECATED_EDKII_CRYPTO_MD4_INIT DeprecatedMd4Init;
+ DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE DeprecatedMd4Duplicate;
+ DEPRECATED_EDKII_CRYPTO_MD4_UPDATE DeprecatedMd4Update;
+ DEPRECATED_EDKII_CRYPTO_MD4_FINAL DeprecatedMd4Final;
+ DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL DeprecatedMd4HashAll;
/// Md5
- EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE Md5GetContextSize;
- EDKII_CRYPTO_MD5_INIT Md5Init;
- EDKII_CRYPTO_MD5_DUPLICATE Md5Duplicate;
- EDKII_CRYPTO_MD5_UPDATE Md5Update;
- EDKII_CRYPTO_MD5_FINAL Md5Final;
- EDKII_CRYPTO_MD5_HASH_ALL Md5HashAll;
+ EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE Md5GetContextSize;
+ EDKII_CRYPTO_MD5_INIT Md5Init;
+ EDKII_CRYPTO_MD5_DUPLICATE Md5Duplicate;
+ EDKII_CRYPTO_MD5_UPDATE Md5Update;
+ EDKII_CRYPTO_MD5_FINAL Md5Final;
+ EDKII_CRYPTO_MD5_HASH_ALL Md5HashAll;
/// Pkcs
- EDKII_CRYPTO_PKCS1_ENCRYPT_V2 Pkcs1v2Encrypt;
- EDKII_CRYPTO_PKCS5_PW_HASH Pkcs5HashPassword;
- EDKII_CRYPTO_PKCS7_VERIFY Pkcs7Verify;
- EDKII_CRYPTO_PKCS7_VERIFY_EKU VerifyEKUsInPkcs7Signature;
- EDKII_CRYPTO_PKCS7_GET_SIGNERS Pkcs7GetSigners;
- EDKII_CRYPTO_PKCS7_FREE_SIGNERS Pkcs7FreeSigners;
- EDKII_CRYPTO_PKCS7_SIGN Pkcs7Sign;
- EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT Pkcs7GetAttachedContent;
- EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST Pkcs7GetCertificatesList;
- EDKII_CRYPTO_AUTHENTICODE_VERIFY AuthenticodeVerify;
- EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY ImageTimestampVerify;
+ EDKII_CRYPTO_PKCS1_ENCRYPT_V2 Pkcs1v2Encrypt;
+ EDKII_CRYPTO_PKCS5_PW_HASH Pkcs5HashPassword;
+ EDKII_CRYPTO_PKCS7_VERIFY Pkcs7Verify;
+ EDKII_CRYPTO_PKCS7_VERIFY_EKU VerifyEKUsInPkcs7Signature;
+ EDKII_CRYPTO_PKCS7_GET_SIGNERS Pkcs7GetSigners;
+ EDKII_CRYPTO_PKCS7_FREE_SIGNERS Pkcs7FreeSigners;
+ EDKII_CRYPTO_PKCS7_SIGN Pkcs7Sign;
+ EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT Pkcs7GetAttachedContent;
+ EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST Pkcs7GetCertificatesList;
+ EDKII_CRYPTO_AUTHENTICODE_VERIFY AuthenticodeVerify;
+ EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY ImageTimestampVerify;
/// DH
- EDKII_CRYPTO_DH_NEW DhNew;
- EDKII_CRYPTO_DH_FREE DhFree;
- EDKII_CRYPTO_DH_GENERATE_PARAMETER DhGenerateParameter;
- EDKII_CRYPTO_DH_SET_PARAMETER DhSetParameter;
- EDKII_CRYPTO_DH_GENERATE_KEY DhGenerateKey;
- EDKII_CRYPTO_DH_COMPUTE_KEY DhComputeKey;
+ EDKII_CRYPTO_DH_NEW DhNew;
+ EDKII_CRYPTO_DH_FREE DhFree;
+ EDKII_CRYPTO_DH_GENERATE_PARAMETER DhGenerateParameter;
+ EDKII_CRYPTO_DH_SET_PARAMETER DhSetParameter;
+ EDKII_CRYPTO_DH_GENERATE_KEY DhGenerateKey;
+ EDKII_CRYPTO_DH_COMPUTE_KEY DhComputeKey;
/// Random
- EDKII_CRYPTO_RANDOM_SEED RandomSeed;
- EDKII_CRYPTO_RANDOM_BYTES RandomBytes;
+ EDKII_CRYPTO_RANDOM_SEED RandomSeed;
+ EDKII_CRYPTO_RANDOM_BYTES RandomBytes;
/// RSA
- EDKII_CRYPTO_RSA_VERIFY_PKCS1 RsaVerifyPkcs1;
- EDKII_CRYPTO_RSA_NEW RsaNew;
- EDKII_CRYPTO_RSA_FREE RsaFree;
- EDKII_CRYPTO_RSA_SET_KEY RsaSetKey;
- EDKII_CRYPTO_RSA_GET_KEY RsaGetKey;
- EDKII_CRYPTO_RSA_GENERATE_KEY RsaGenerateKey;
- EDKII_CRYPTO_RSA_CHECK_KEY RsaCheckKey;
- EDKII_CRYPTO_RSA_PKCS1_SIGN RsaPkcs1Sign;
- EDKII_CRYPTO_RSA_PKCS1_VERIFY RsaPkcs1Verify;
- EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM RsaGetPrivateKeyFromPem;
- EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509 RsaGetPublicKeyFromX509;
+ EDKII_CRYPTO_RSA_VERIFY_PKCS1 RsaVerifyPkcs1;
+ EDKII_CRYPTO_RSA_NEW RsaNew;
+ EDKII_CRYPTO_RSA_FREE RsaFree;
+ EDKII_CRYPTO_RSA_SET_KEY RsaSetKey;
+ EDKII_CRYPTO_RSA_GET_KEY RsaGetKey;
+ EDKII_CRYPTO_RSA_GENERATE_KEY RsaGenerateKey;
+ EDKII_CRYPTO_RSA_CHECK_KEY RsaCheckKey;
+ EDKII_CRYPTO_RSA_PKCS1_SIGN RsaPkcs1Sign;
+ EDKII_CRYPTO_RSA_PKCS1_VERIFY RsaPkcs1Verify;
+ EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM RsaGetPrivateKeyFromPem;
+ EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509 RsaGetPublicKeyFromX509;
/// Sha1
- EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE Sha1GetContextSize;
- EDKII_CRYPTO_SHA1_INIT Sha1Init;
- EDKII_CRYPTO_SHA1_DUPLICATE Sha1Duplicate;
- EDKII_CRYPTO_SHA1_UPDATE Sha1Update;
- EDKII_CRYPTO_SHA1_FINAL Sha1Final;
- EDKII_CRYPTO_SHA1_HASH_ALL Sha1HashAll;
+ EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE Sha1GetContextSize;
+ EDKII_CRYPTO_SHA1_INIT Sha1Init;
+ EDKII_CRYPTO_SHA1_DUPLICATE Sha1Duplicate;
+ EDKII_CRYPTO_SHA1_UPDATE Sha1Update;
+ EDKII_CRYPTO_SHA1_FINAL Sha1Final;
+ EDKII_CRYPTO_SHA1_HASH_ALL Sha1HashAll;
/// Sha256
- EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE Sha256GetContextSize;
- EDKII_CRYPTO_SHA256_INIT Sha256Init;
- EDKII_CRYPTO_SHA256_DUPLICATE Sha256Duplicate;
- EDKII_CRYPTO_SHA256_UPDATE Sha256Update;
- EDKII_CRYPTO_SHA256_FINAL Sha256Final;
- EDKII_CRYPTO_SHA256_HASH_ALL Sha256HashAll;
+ EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE Sha256GetContextSize;
+ EDKII_CRYPTO_SHA256_INIT Sha256Init;
+ EDKII_CRYPTO_SHA256_DUPLICATE Sha256Duplicate;
+ EDKII_CRYPTO_SHA256_UPDATE Sha256Update;
+ EDKII_CRYPTO_SHA256_FINAL Sha256Final;
+ EDKII_CRYPTO_SHA256_HASH_ALL Sha256HashAll;
/// Sha384
- EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE Sha384GetContextSize;
- EDKII_CRYPTO_SHA384_INIT Sha384Init;
- EDKII_CRYPTO_SHA384_DUPLICATE Sha384Duplicate;
- EDKII_CRYPTO_SHA384_UPDATE Sha384Update;
- EDKII_CRYPTO_SHA384_FINAL Sha384Final;
- EDKII_CRYPTO_SHA384_HASH_ALL Sha384HashAll;
+ EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE Sha384GetContextSize;
+ EDKII_CRYPTO_SHA384_INIT Sha384Init;
+ EDKII_CRYPTO_SHA384_DUPLICATE Sha384Duplicate;
+ EDKII_CRYPTO_SHA384_UPDATE Sha384Update;
+ EDKII_CRYPTO_SHA384_FINAL Sha384Final;
+ EDKII_CRYPTO_SHA384_HASH_ALL Sha384HashAll;
/// Sha512
- EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE Sha512GetContextSize;
- EDKII_CRYPTO_SHA512_INIT Sha512Init;
- EDKII_CRYPTO_SHA512_DUPLICATE Sha512Duplicate;
- EDKII_CRYPTO_SHA512_UPDATE Sha512Update;
- EDKII_CRYPTO_SHA512_FINAL Sha512Final;
- EDKII_CRYPTO_SHA512_HASH_ALL Sha512HashAll;
+ EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE Sha512GetContextSize;
+ EDKII_CRYPTO_SHA512_INIT Sha512Init;
+ EDKII_CRYPTO_SHA512_DUPLICATE Sha512Duplicate;
+ EDKII_CRYPTO_SHA512_UPDATE Sha512Update;
+ EDKII_CRYPTO_SHA512_FINAL Sha512Final;
+ EDKII_CRYPTO_SHA512_HASH_ALL Sha512HashAll;
/// X509
- EDKII_CRYPTO_X509_GET_SUBJECT_NAME X509GetSubjectName;
- EDKII_CRYPTO_X509_GET_COMMON_NAME X509GetCommonName;
- EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME X509GetOrganizationName;
- EDKII_CRYPTO_X509_VERIFY_CERT X509VerifyCert;
- EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE X509ConstructCertificate;
- EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK X509ConstructCertificateStack;
- EDKII_CRYPTO_X509_FREE X509Free;
- EDKII_CRYPTO_X509_STACK_FREE X509StackFree;
- EDKII_CRYPTO_X509_GET_TBS_CERT X509GetTBSCert;
+ EDKII_CRYPTO_X509_GET_SUBJECT_NAME X509GetSubjectName;
+ EDKII_CRYPTO_X509_GET_COMMON_NAME X509GetCommonName;
+ EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME X509GetOrganizationName;
+ EDKII_CRYPTO_X509_VERIFY_CERT X509VerifyCert;
+ EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE X509ConstructCertificate;
+ EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK X509ConstructCertificateStack;
+ EDKII_CRYPTO_X509_FREE X509Free;
+ EDKII_CRYPTO_X509_STACK_FREE X509StackFree;
+ EDKII_CRYPTO_X509_GET_TBS_CERT X509GetTBSCert;
/// TDES - deprecated and unsupported
- DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE DeprecatedTdesGetContextSize;
- DEPRECATED_EDKII_CRYPTO_TDES_INIT DeprecatedTdesInit;
- DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT DeprecatedTdesEcbEncrypt;
- DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT DeprecatedTdesEcbDecrypt;
- DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT DeprecatedTdesCbcEncrypt;
- DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT DeprecatedTdesCbcDecrypt;
+ DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE DeprecatedTdesGetContextSize;
+ DEPRECATED_EDKII_CRYPTO_TDES_INIT DeprecatedTdesInit;
+ DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT DeprecatedTdesEcbEncrypt;
+ DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT DeprecatedTdesEcbDecrypt;
+ DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT DeprecatedTdesCbcEncrypt;
+ DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT DeprecatedTdesCbcDecrypt;
/// AES - ECB Mode is deprecated and unsupported
- EDKII_CRYPTO_AES_GET_CONTEXT_SIZE AesGetContextSize;
- EDKII_CRYPTO_AES_INIT AesInit;
- DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT DeprecatedAesEcbEncrypt;
- DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT DeprecatedAesEcbDecrypt;
- EDKII_CRYPTO_AES_CBC_ENCRYPT AesCbcEncrypt;
- EDKII_CRYPTO_AES_CBC_DECRYPT AesCbcDecrypt;
+ EDKII_CRYPTO_AES_GET_CONTEXT_SIZE AesGetContextSize;
+ EDKII_CRYPTO_AES_INIT AesInit;
+ DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT DeprecatedAesEcbEncrypt;
+ DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT DeprecatedAesEcbDecrypt;
+ EDKII_CRYPTO_AES_CBC_ENCRYPT AesCbcEncrypt;
+ EDKII_CRYPTO_AES_CBC_DECRYPT AesCbcDecrypt;
/// Arc4 - deprecated and unsupported
- DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE DeprecatedArc4GetContextSize;
- DEPRECATED_EDKII_CRYPTO_ARC4_INIT DeprecatedArc4Init;
- DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT DeprecatedArc4Encrypt;
- DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT DeprecatedArc4Decrypt;
- DEPRECATED_EDKII_CRYPTO_ARC4_RESET DeprecatedArc4Reset;
+ DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE DeprecatedArc4GetContextSize;
+ DEPRECATED_EDKII_CRYPTO_ARC4_INIT DeprecatedArc4Init;
+ DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT DeprecatedArc4Encrypt;
+ DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT DeprecatedArc4Decrypt;
+ DEPRECATED_EDKII_CRYPTO_ARC4_RESET DeprecatedArc4Reset;
/// SM3
- EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE Sm3GetContextSize;
- EDKII_CRYPTO_SM3_INIT Sm3Init;
- EDKII_CRYPTO_SM3_DUPLICATE Sm3Duplicate;
- EDKII_CRYPTO_SM3_UPDATE Sm3Update;
- EDKII_CRYPTO_SM3_FINAL Sm3Final;
- EDKII_CRYPTO_SM3_HASH_ALL Sm3HashAll;
+ EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE Sm3GetContextSize;
+ EDKII_CRYPTO_SM3_INIT Sm3Init;
+ EDKII_CRYPTO_SM3_DUPLICATE Sm3Duplicate;
+ EDKII_CRYPTO_SM3_UPDATE Sm3Update;
+ EDKII_CRYPTO_SM3_FINAL Sm3Final;
+ EDKII_CRYPTO_SM3_HASH_ALL Sm3HashAll;
/// HKDF
- EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND HkdfSha256ExtractAndExpand;
+ EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND HkdfSha256ExtractAndExpand;
/// X509 (Continued)
- EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V X509ConstructCertificateStackV;
+ EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V X509ConstructCertificateStackV;
/// TLS
- EDKII_CRYPTO_TLS_INITIALIZE TlsInitialize;
- EDKII_CRYPTO_TLS_CTX_FREE TlsCtxFree;
- EDKII_CRYPTO_TLS_CTX_NEW TlsCtxNew;
- EDKII_CRYPTO_TLS_FREE TlsFree;
- EDKII_CRYPTO_TLS_NEW TlsNew;
- EDKII_CRYPTO_TLS_IN_HANDSHAKE TlsInHandshake;
- EDKII_CRYPTO_TLS_DO_HANDSHAKE TlsDoHandshake;
- EDKII_CRYPTO_TLS_HANDLE_ALERT TlsHandleAlert;
- EDKII_CRYPTO_TLS_CLOSE_NOTIFY TlsCloseNotify;
- EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT TlsCtrlTrafficOut;
- EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN TlsCtrlTrafficIn;
- EDKII_CRYPTO_TLS_READ TlsRead;
- EDKII_CRYPTO_TLS_WRITE TlsWrite;
+ EDKII_CRYPTO_TLS_INITIALIZE TlsInitialize;
+ EDKII_CRYPTO_TLS_CTX_FREE TlsCtxFree;
+ EDKII_CRYPTO_TLS_CTX_NEW TlsCtxNew;
+ EDKII_CRYPTO_TLS_FREE TlsFree;
+ EDKII_CRYPTO_TLS_NEW TlsNew;
+ EDKII_CRYPTO_TLS_IN_HANDSHAKE TlsInHandshake;
+ EDKII_CRYPTO_TLS_DO_HANDSHAKE TlsDoHandshake;
+ EDKII_CRYPTO_TLS_HANDLE_ALERT TlsHandleAlert;
+ EDKII_CRYPTO_TLS_CLOSE_NOTIFY TlsCloseNotify;
+ EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT TlsCtrlTrafficOut;
+ EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN TlsCtrlTrafficIn;
+ EDKII_CRYPTO_TLS_READ TlsRead;
+ EDKII_CRYPTO_TLS_WRITE TlsWrite;
/// TLS Set
- EDKII_CRYPTO_TLS_SET_VERSION TlsSetVersion;
- EDKII_CRYPTO_TLS_SET_CONNECTION_END TlsSetConnectionEnd;
- EDKII_CRYPTO_TLS_SET_CIPHER_LIST TlsSetCipherList;
- EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD TlsSetCompressionMethod;
- EDKII_CRYPTO_TLS_SET_VERIFY TlsSetVerify;
- EDKII_CRYPTO_TLS_SET_VERIFY_HOST TlsSetVerifyHost;
- EDKII_CRYPTO_TLS_SET_SESSIONID TlsSetSessionId;
- EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE TlsSetCaCertificate;
- EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT TlsSetHostPublicCert;
- EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY TlsSetHostPrivateKey;
- EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST TlsSetCertRevocationList;
+ EDKII_CRYPTO_TLS_SET_VERSION TlsSetVersion;
+ EDKII_CRYPTO_TLS_SET_CONNECTION_END TlsSetConnectionEnd;
+ EDKII_CRYPTO_TLS_SET_CIPHER_LIST TlsSetCipherList;
+ EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD TlsSetCompressionMethod;
+ EDKII_CRYPTO_TLS_SET_VERIFY TlsSetVerify;
+ EDKII_CRYPTO_TLS_SET_VERIFY_HOST TlsSetVerifyHost;
+ EDKII_CRYPTO_TLS_SET_SESSIONID TlsSetSessionId;
+ EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE TlsSetCaCertificate;
+ EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT TlsSetHostPublicCert;
+ EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY TlsSetHostPrivateKey;
+ EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST TlsSetCertRevocationList;
/// TLS Get
- EDKII_CRYPTO_TLS_GET_VERSION TlsGetVersion;
- EDKII_CRYPTO_TLS_GET_CONNECTION_END TlsGetConnectionEnd;
- EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER TlsGetCurrentCipher;
- EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID TlsGetCurrentCompressionId;
- EDKII_CRYPTO_TLS_GET_VERIFY TlsGetVerify;
- EDKII_CRYPTO_TLS_GET_SESSION_ID TlsGetSessionId;
- EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM TlsGetClientRandom;
- EDKII_CRYPTO_TLS_GET_SERVER_RANDOM TlsGetServerRandom;
- EDKII_CRYPTO_TLS_GET_KEY_MATERIAL TlsGetKeyMaterial;
- EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE TlsGetCaCertificate;
- EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT TlsGetHostPublicCert;
- EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY TlsGetHostPrivateKey;
- EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST TlsGetCertRevocationList;
+ EDKII_CRYPTO_TLS_GET_VERSION TlsGetVersion;
+ EDKII_CRYPTO_TLS_GET_CONNECTION_END TlsGetConnectionEnd;
+ EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER TlsGetCurrentCipher;
+ EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID TlsGetCurrentCompressionId;
+ EDKII_CRYPTO_TLS_GET_VERIFY TlsGetVerify;
+ EDKII_CRYPTO_TLS_GET_SESSION_ID TlsGetSessionId;
+ EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM TlsGetClientRandom;
+ EDKII_CRYPTO_TLS_GET_SERVER_RANDOM TlsGetServerRandom;
+ EDKII_CRYPTO_TLS_GET_KEY_MATERIAL TlsGetKeyMaterial;
+ EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE TlsGetCaCertificate;
+ EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT TlsGetHostPublicCert;
+ EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY TlsGetHostPrivateKey;
+ EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST TlsGetCertRevocationList;
/// RSA PSS
- EDKII_CRYPTO_RSA_PSS_SIGN RsaPssSign;
- EDKII_CRYPTO_RSA_PSS_VERIFY RsaPssVerify;
+ EDKII_CRYPTO_RSA_PSS_SIGN RsaPssSign;
+ EDKII_CRYPTO_RSA_PSS_VERIFY RsaPssVerify;
/// Parallel hash
- EDKII_CRYPTO_PARALLEL_HASH_ALL ParallelHash256HashAll;
+ EDKII_CRYPTO_PARALLEL_HASH_ALL ParallelHash256HashAll;
/// Big Number
- EDKII_CRYPTO_BIGNUM_INIT BigNumInit;
- EDKII_CRYPTO_BIGNUM_FROM_BIN BigNumFromBin;
- EDKII_CRYPTO_BIGNUM_TO_BIN BigNumToBin;
- EDKII_CRYPTO_BIGNUM_FREE BigNumFree;
- EDKII_CRYPTO_BIGNUM_ADD BigNumAdd;
- EDKII_CRYPTO_BIGNUM_SUB BigNumSub;
- EDKII_CRYPTO_BIGNUM_MOD BigNumMod;
- EDKII_CRYPTO_BIGNUM_EXP_MOD BigNumExpMod;
- EDKII_CRYPTO_BIGNUM_INVERSE_MOD BigNumInverseMod;
- EDKII_CRYPTO_BIGNUM_DIV BigNumDiv;
- EDKII_CRYPTO_BIGNUM_MUL_MOD BigNumMulMod;
- EDKII_CRYPTO_BIGNUM_CMP BigNumCmp;
- EDKII_CRYPTO_BIGNUM_BITS BigNumBits;
- EDKII_CRYPTO_BIGNUM_BYTES BigNumBytes;
- EDKII_CRYPTO_BIGNUM_IS_WORD BigNumIsWord;
- EDKII_CRYPTO_BIGNUM_IS_ODD BigNumIsOdd;
- EDKII_CRYPTO_BIGNUM_COPY BigNumCopy;
- EDKII_CRYPTO_BIGNUM_VALUE_ONE BigNumValueOne;
- EDKII_CRYPTO_BIGNUM_R_SHIFT BigNumRShift;
- EDKII_CRYPTO_BIGNUM_CONST_TIME BigNumConstTime;
- EDKII_CRYPTO_BIGNUM_SQR_MOD BigNumSqrMod;
- EDKII_CRYPTO_BIGNUM_NEW_CONTEXT BigNumNewContext;
- EDKII_CRYPTO_BIGNUM_CONTEXT_FREE BigNumContextFree;
- EDKII_CRYPTO_BIGNUM_SET_UINT BigNumSetUint;
- EDKII_CRYPTO_BIGNUM_ADD_MOD BigNumAddMod;
+ EDKII_CRYPTO_BIGNUM_INIT BigNumInit;
+ EDKII_CRYPTO_BIGNUM_FROM_BIN BigNumFromBin;
+ EDKII_CRYPTO_BIGNUM_TO_BIN BigNumToBin;
+ EDKII_CRYPTO_BIGNUM_FREE BigNumFree;
+ EDKII_CRYPTO_BIGNUM_ADD BigNumAdd;
+ EDKII_CRYPTO_BIGNUM_SUB BigNumSub;
+ EDKII_CRYPTO_BIGNUM_MOD BigNumMod;
+ EDKII_CRYPTO_BIGNUM_EXP_MOD BigNumExpMod;
+ EDKII_CRYPTO_BIGNUM_INVERSE_MOD BigNumInverseMod;
+ EDKII_CRYPTO_BIGNUM_DIV BigNumDiv;
+ EDKII_CRYPTO_BIGNUM_MUL_MOD BigNumMulMod;
+ EDKII_CRYPTO_BIGNUM_CMP BigNumCmp;
+ EDKII_CRYPTO_BIGNUM_BITS BigNumBits;
+ EDKII_CRYPTO_BIGNUM_BYTES BigNumBytes;
+ EDKII_CRYPTO_BIGNUM_IS_WORD BigNumIsWord;
+ EDKII_CRYPTO_BIGNUM_IS_ODD BigNumIsOdd;
+ EDKII_CRYPTO_BIGNUM_COPY BigNumCopy;
+ EDKII_CRYPTO_BIGNUM_VALUE_ONE BigNumValueOne;
+ EDKII_CRYPTO_BIGNUM_R_SHIFT BigNumRShift;
+ EDKII_CRYPTO_BIGNUM_CONST_TIME BigNumConstTime;
+ EDKII_CRYPTO_BIGNUM_SQR_MOD BigNumSqrMod;
+ EDKII_CRYPTO_BIGNUM_NEW_CONTEXT BigNumNewContext;
+ EDKII_CRYPTO_BIGNUM_CONTEXT_FREE BigNumContextFree;
+ EDKII_CRYPTO_BIGNUM_SET_UINT BigNumSetUint;
+ EDKII_CRYPTO_BIGNUM_ADD_MOD BigNumAddMod;
+ /// EC
+ EDKII_CRYPTO_EC_GROUP_INIT EcGroupInit;
+ EDKII_CRYPTO_EC_GROUP_GET_CURVE EcGroupGetCurve;
+ EDKII_CRYPTO_EC_GROUP_GET_ORDER EcGroupGetOrder;
+ EDKII_CRYPTO_EC_GROUP_FREE EcGroupFree;
+ EDKII_CRYPTO_EC_POINT_INIT EcPointInit;
+ EDKII_CRYPTO_EC_POINT_DE_INIT EcPointDeInit;
+ EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES EcPointGetAffineCoordinates;
+ EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES EcPointSetAffineCoordinates;
+ EDKII_CRYPTO_EC_POINT_ADD EcPointAdd;
+ EDKII_CRYPTO_EC_POINT_MUL EcPointMul;
+ EDKII_CRYPTO_EC_POINT_INVERT EcPointInvert;
+ EDKII_CRYPTO_EC_POINT_IS_ON_CURVE EcPointIsOnCurve;
+ EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY EcPointIsAtInfinity;
+ EDKII_CRYPTO_EC_POINT_EQUAL EcPointEqual;
+ EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES EcPointSetCompressedCoordinates;
+ EDKII_CRYPTO_EC_NEW_BY_NID EcNewByNid;
+ EDKII_CRYPTO_EC_FREE EcFree;
+ EDKII_CRYPTO_EC_GENERATE_KEY EcGenerateKey;
+ EDKII_CRYPTO_EC_GET_PUB_KEY EcGetPubKey;
+ EDKII_CRYPTO_EC_DH_COMPUTE_KEY EcDhComputeKey;
};
extern GUID gEdkiiCryptoProtocolGuid;
--
2.31.1.windows.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc
[not found] <cover.1663735439.git.yi1.li@intel.com>
2022-09-21 4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
2022-09-21 4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
@ 2022-09-21 4:54 ` yi1 li
2 siblings, 0 replies; 17+ messages in thread
From: yi1 li @ 2022-09-21 4:54 UTC (permalink / raw)
To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
Add unit test for CryptoEc.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
.../BaseCryptLib/UnitTestHostBaseCryptLib.inf | 2 +
CryptoPkg/Test/CryptoPkgHostUnitTest.dsc | 3 +
.../BaseCryptLib/BaseCryptLibUnitTests.c | 1 +
.../UnitTest/Library/BaseCryptLib/EcTests.c | 290 ++++++++++++++++++
.../Library/BaseCryptLib/TestBaseCryptLib.h | 2 +
.../BaseCryptLib/TestBaseCryptLibHost.inf | 1 +
.../BaseCryptLib/TestBaseCryptLibShell.inf | 1 +
7 files changed, 300 insertions(+)
create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
diff --git a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
index cf8810e598..33df93c73c 100644
--- a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
@@ -47,6 +47,8 @@
Pk/CryptRsaPss.c
Pk/CryptRsaPssSign.c
Bn/CryptBn.c
+ Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
+ Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
SysCall/UnitTestHostCrtWrapper.c
diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
index 16478f4a57..b6e1a66198 100644
--- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
+++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
@@ -19,6 +19,9 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+[PcdsFixedAtBuild]
+ gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled|TRUE
+
[LibraryClasses]
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
index 792006a194..359921fd5f 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
@@ -26,6 +26,7 @@ SUITE_DESC mSuiteDesc[] = {
{ "PRNG verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mPrngTestNum, mPrngTest },
{ "OAEP encrypt verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mOaepTestNum, mOaepTest },
{ "Bn verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mBnTestNum, mBnTest },
+ { "EC verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mEcTestNum, mEcTest },
};
EFI_STATUS
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
new file mode 100644
index 0000000000..54ce0b22df
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
@@ -0,0 +1,290 @@
+/** @file
+ Application for Diffie-Hellman Primitives Validation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#define EC_CURVE_NUM_SUPPORTED 3
+UINTN EcCurveList[EC_CURVE_NUM_SUPPORTED] = { CRYPTO_NID_SECP256R1, CRYPTO_NID_SECP384R1, CRYPTO_NID_SECP521R1 };
+UINTN EcKeyHalfSize[EC_CURVE_NUM_SUPPORTED] = { 32, 48, 66 };
+
+struct Generator {
+ UINT8 X[66];
+ UINT8 Y[66];
+};
+
+// Generator points of all ec curve
+struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
+{
+ // CRYPTO_NID_SECP256R1
+ {
+ { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 },
+
+ { 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
+ 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+ 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 }
+ },
+ // CRYPTO_NID_SECP384R1
+ {
+ { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+ 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+ 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+ 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 },
+
+ { 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+ 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+ 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+ 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f }
+ },
+ // CRYPTO_NID_SECP521R1
+ {
+ { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+ 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+ 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+ 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+ 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+ 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 },
+
+ { 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
+ 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+ 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
+ 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+ 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+ 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 }
+ }
+};
+
+VOID *Ec1;
+VOID *Ec2;
+VOID *Group;
+VOID *Point1;
+VOID *Point2;
+VOID *PointRes;
+VOID *BnX;
+VOID *BnY;
+VOID *BnP;
+VOID *BnOrder;
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ Ec1 = NULL;
+ Ec2 = NULL;
+ Group = NULL;
+ Point1 = NULL;
+ Point2 = NULL;
+ PointRes = NULL;
+ BnX = NULL;
+ BnY = NULL;
+ BnP = BigNumInit ();
+ BnOrder = BigNumInit ();
+ if ((BnP == NULL) || (BnOrder == NULL)) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyEcCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ BigNumFree (BnX, TRUE);
+ BigNumFree (BnY, TRUE);
+ BigNumFree (BnP, TRUE);
+ BigNumFree (BnOrder, TRUE);
+ EcGroupFree (Group);
+ EcPointDeInit (Point1, TRUE);
+ EcPointDeInit (Point2, TRUE);
+ EcPointDeInit (PointRes, TRUE);
+ EcFree (Ec1);
+ EcFree (Ec2);
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcBasic (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ UINTN CurveCount;
+ BOOLEAN Status;
+
+ //
+ // Initialize BigNumbers
+ //
+ for (CurveCount = 0; CurveCount < EC_CURVE_NUM_SUPPORTED; CurveCount++) {
+ //
+ // Basic EC functions unit test
+ //
+ Group = EcGroupInit (EcCurveList[CurveCount]);
+ if (Group == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ Point1 = EcPointInit (Group);
+ Point2 = EcPointInit (Group);
+ PointRes = EcPointInit (Group);
+ BnX = BigNumFromBin (EcCurveGenerator[CurveCount].X, EcKeyHalfSize[CurveCount]);
+ BnY = BigNumFromBin (EcCurveGenerator[CurveCount].Y, EcKeyHalfSize[CurveCount]);
+ if ((Point1 == NULL) || (Point2 == NULL) || (PointRes == NULL) || (BnX == NULL) || (BnY == NULL)) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ Status = EcGroupGetCurve (Group, BnP, NULL, NULL, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcGroupGetOrder (Group, BnOrder);
+ UT_ASSERT_TRUE (Status);
+
+ // Point G should on curve
+ Status = EcPointSetAffineCoordinates (Group, Point1, BnX, BnY, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointSetAffineCoordinates (Group, Point2, BnX, BnY, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointEqual (Group, Point1, Point2, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointIsOnCurve (Group, Point1, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointIsAtInfinity (Group, Point1);
+ UT_ASSERT_FALSE (Status);
+
+ // Point 2G should on curve
+ Status = EcPointAdd (Group, PointRes, Point1, Point1, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointIsOnCurve (Group, PointRes, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ // Point Order * G should at infinity
+ Status = EcPointMul (Group, PointRes, Point1, BnOrder, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointIsAtInfinity (Group, PointRes);
+ UT_ASSERT_TRUE (Status);
+
+ // -(-G) == G
+ Status = EcPointInvert (Group, Point2, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointEqual (Group, Point2, Point1, NULL);
+ UT_ASSERT_FALSE (Status);
+
+ Status = EcPointInvert (Group, Point2, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointEqual (Group, Point2, Point1, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ // Compress point test
+ Status = EcPointSetCompressedCoordinates (Group, Point1, BnX, 0, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointSetCompressedCoordinates (Group, Point2, BnX, 1, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointEqual (Group, Point2, Point1, NULL);
+ UT_ASSERT_FALSE (Status);
+
+ Status = EcPointInvert (Group, Point2, NULL);
+ UT_ASSERT_TRUE (Status);
+
+ Status = EcPointEqual (Group, Point2, Point1, NULL);
+ UT_ASSERT_TRUE (Status);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcDh (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 Public1[66 * 2];
+ UINTN Public1Length;
+ UINT8 Public2[66 * 2];
+ UINTN Public2Length;
+ UINT8 Key1[66];
+ UINTN Key1Length;
+ UINT8 Key2[66];
+ UINTN Key2Length;
+ UINTN CurveCount;
+ BOOLEAN Status;
+
+ for (CurveCount = 0; CurveCount < EC_CURVE_NUM_SUPPORTED; CurveCount++) {
+ //
+ // Initial key length
+ //
+ Public1Length = sizeof (Public1);
+ Public2Length = sizeof (Public2);
+ Key1Length = sizeof (Key1);
+ Key2Length = sizeof (Key2);
+ //
+ // ECDH functions unit test
+ //
+ Ec1 = EcNewByNid (EcCurveList[CurveCount]);
+ if (Ec1 == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ Ec2 = EcNewByNid (EcCurveList[CurveCount]);
+ if (Ec2 == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ Status = EcGenerateKey (Ec1, Public1, &Public1Length);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (Public1Length, EcKeyHalfSize[CurveCount] * 2);
+
+ Status = EcGenerateKey (Ec2, Public2, &Public2Length);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (Public2Length, EcKeyHalfSize[CurveCount] * 2);
+
+ Status = EcDhComputeKey (Ec1, Public2, Public2Length, NULL, Key1, &Key1Length);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (Key1Length, EcKeyHalfSize[CurveCount]);
+
+ Status = EcDhComputeKey (Ec2, Public1, Public1Length, NULL, Key2, &Key2Length);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (Key2Length, EcKeyHalfSize[CurveCount]);
+
+ UT_ASSERT_EQUAL (Key1Length, Key2Length);
+ UT_ASSERT_MEM_EQUAL (Key1, Key2, Key1Length);
+
+ Status = EcGetPubKey (Ec1, Public2, &Public2Length);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (Public2Length, EcKeyHalfSize[CurveCount] * 2);
+
+ UT_ASSERT_EQUAL (Public1Length, Public2Length);
+ UT_ASSERT_MEM_EQUAL (Public1, Public2, Public1Length);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mEcTest[] = {
+ //
+ // -----Description-----------------Class------------------Function----Pre----Post----Context
+ //
+ { "TestVerifyEcBasic()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcBasic, TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
+ { "TestVerifyEcDh()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcDh, TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
+};
+
+UINTN mEcTestNum = ARRAY_SIZE (mEcTest);
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
index b8f0fdfd89..6b198d43b6 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -89,6 +89,8 @@ extern TEST_DESC mRsaPssTest[];
extern UINTN mBnTestNum;
extern TEST_DESC mBnTest[];
+extern UINTN mEcTestNum;
+extern TEST_DESC mEcTest[];
/** Creates a framework you can use */
EFI_STATUS
EFIAPI
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
index 1301345a13..8f96cf6c4a 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -38,6 +38,7 @@
RsaPssTests.c
ParallelhashTests.c
BnTests.c
+ EcTests.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
index 9a41dbc317..c9a86dab98 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -37,6 +37,7 @@
OaepEncryptTests.c
RsaPssTests.c
BnTests.c
+ EcTests.c
[Packages]
MdePkg/MdePkg.dec
--
2.31.1.windows.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-21 4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
@ 2022-09-21 16:21 ` Michael D Kinney
2022-09-22 2:15 ` yi1 li
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-21 16:21 UTC (permalink / raw)
To: devel@edk2.groups.io, Li, Yi1, Kinney, Michael D
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Comments embedded below.
Mike
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> Sent: Tuesday, September 20, 2022 9:55 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
>
> This patch is used to add CryptEc library, which is wrapped
> over OpenSSL.
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
>
> Signed-off-by: Yi Li <yi1.li@intel.com>
> ---
> CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> 8 files changed, 2186 insertions(+)
> create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
>
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> index b253923dd8..d74fc21c1e 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>
> #include <Uefi/UefiBaseType.h>
>
> +#define CRYPTO_NID_NULL 0x0000
> +
> +// Key Exchange
> +#define CRYPTO_NID_SECP256R1 0x0204
> +#define CRYPTO_NID_SECP384R1 0x0205
> +#define CRYPTO_NID_SECP521R1 0x0206
> +
> ///
> /// MD5 digest size in bytes
> ///
> @@ -2850,4 +2857,421 @@ BigNumAddMod (
> OUT VOID *BnRes
> );
>
> +// =====================================================================================
> +// Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + );
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient.
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + );
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + );
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + );
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + );
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + );
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + );
> +
> +// =====================================================================================
> +// Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + );
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + );
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + );
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + );
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + );
> +
> #endif // __BASE_CRYPT_LIB_H__
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 9e4be2fb0d..ade6ee3fdd 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -52,6 +52,8 @@
> Pk/CryptTs.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSign.c
> + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
The use of the PCD to select the file should not be needed here. The
Ec Family and individual service enable/disable fields in the
PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
disable the Ec services.
The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
completely as part of this patch series.
> Pem/CryptPem.c
> Bn/CryptBn.c
>
> diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> index 65ad23fb81..383df2b23c 100644
> --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> @@ -58,6 +58,7 @@
> Pk/CryptTsNull.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSignNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPemNull.c
> Rand/CryptRandNull.c
> Bn/CryptBnNull.c
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> new file mode 100644
> index 0000000000..396c819834
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> @@ -0,0 +1,765 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "InternalCryptLib.h"
> +#include <openssl/objects.h>
> +#include <openssl/bn.h>
> +#include <openssl/ec.h>
> +
> +// =====================================================================================
> +// Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> + Return the Nid of certain ECC curve.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval !=-1 On success.
> + @retval -1 ECC curve not supported.
> +**/
> +STATIC
> +INT32
> +CryptoNidToOpensslNid (
> + IN UINTN CryptoNid
> + )
> +{
> + INT32 Nid;
> +
> + switch (CryptoNid) {
> + case CRYPTO_NID_SECP256R1:
> + Nid = NID_X9_62_prime256v1;
> + break;
> + case CRYPTO_NID_SECP384R1:
> + Nid = NID_secp384r1;
> + break;
> + case CRYPTO_NID_SECP521R1:
> + Nid = NID_secp521r1;
> + break;
> + default:
> + return -1;
> + }
> +
> + return Nid;
> +}
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + INT32 Nid;
> +
> + Nid = CryptoNidToOpensslNid (CryptoNid);
> +
> + if (Nid < 0) {
> + return NULL;
> + }
> +
> + return EC_GROUP_new_by_curve_name (Nid);
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + EC_GROUP_free (EcGroup);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + return EC_POINT_new (EcGroup);
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + if (Clear) {
> + EC_POINT_clear_free (EcPoint);
> + } else {
> + EC_POINT_free (EcPoint);
> + }
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> +}
> +
> +// =====================================================================================
> +// Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + INT32 OpenSslNid;
> +
> + OpenSslNid = CryptoNidToOpensslNid (Nid);
> + if (OpenSslNid < 0) {
> + return NULL;
> + }
> +
> + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + EC_KEY_free ((EC_KEY *)EcContext);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + EC_KEY *EcKey;
> + CONST EC_GROUP *Group;
> + CONST EC_POINT *EcPoint;
> + BOOLEAN RetVal;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + UINTN HalfSize;
> + INTN XSize;
> + INTN YSize;
> +
> + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> +
> + // Assume RAND_seed was called
> + if (EC_KEY_generate_key (EcKey) != 1) {
> + return FALSE;
> + }
> +
> + if (*PublicKeySize < HalfSize * 2) {
> + *PublicKeySize = HalfSize * 2;
> + return FALSE;
> + }
> +
> + *PublicKeySize = HalfSize * 2;
> +
> + EcPoint = EC_KEY_get0_public_key (EcKey);
> + if (EcPoint == NULL) {
> + return FALSE;
> + }
> +
> + RetVal = FALSE;
> + BnX = BN_new ();
> + BnY = BN_new ();
> + if ((BnX == NULL) || (BnY == NULL)) {
> + goto fail;
> + }
> +
> + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> +
> + XSize = BN_num_bytes (BnX);
> + YSize = BN_num_bytes (BnY);
> + if ((XSize <= 0) || (YSize <= 0)) {
> + goto fail;
> + }
> +
> + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> +
> + ZeroMem (PublicKey, *PublicKeySize);
> + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + return RetVal;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + EC_KEY *EcKey;
> + CONST EC_GROUP *Group;
> + CONST EC_POINT *EcPoint;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + UINTN HalfSize;
> + INTN XSize;
> + INTN YSize;
> + BOOLEAN RetVal;
> +
> + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> + if (*PublicKeySize < HalfSize * 2) {
> + *PublicKeySize = HalfSize * 2;
> + return FALSE;
> + }
> +
> + *PublicKeySize = HalfSize * 2;
> +
> + EcPoint = EC_KEY_get0_public_key (EcKey);
> + if (EcPoint == NULL) {
> + return FALSE;
> + }
> +
> + RetVal = FALSE;
> + BnX = BN_new ();
> + BnY = BN_new ();
> + if ((BnX == NULL) || (BnY == NULL)) {
> + goto fail;
> + }
> +
> + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> +
> + XSize = BN_num_bytes (BnX);
> + YSize = BN_num_bytes (BnY);
> + if ((XSize <= 0) || (YSize <= 0)) {
> + goto fail;
> + }
> +
> + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> +
> + if (PublicKey != NULL) {
> + ZeroMem (PublicKey, *PublicKeySize);
> + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> + }
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + return RetVal;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If public key is compressed, the PeerPublic will only contain half key (X).
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + EC_KEY *EcKey;
> + EC_KEY *PeerEcKey;
> + CONST EC_GROUP *Group;
> + BOOLEAN RetVal;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + EC_POINT *Point;
> + INT32 OpenSslNid;
> + UINTN HalfSize;
> +
> + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((Key == NULL) && (*KeySize != 0)) {
> + return FALSE;
> + }
> +
> + if (PeerPublicSize > INT_MAX) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> + return FALSE;
> + }
> +
> + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> + return FALSE;
> + }
> +
> + if (*KeySize < HalfSize) {
> + *KeySize = HalfSize;
> + return FALSE;
> + }
> +
> + *KeySize = HalfSize;
> +
> + RetVal = FALSE;
> + Point = NULL;
> + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> + BnY = NULL;
> + Point = EC_POINT_new (Group);
> + PeerEcKey = NULL;
> + if ((BnX == NULL) || (Point == NULL)) {
> + goto fail;
> + }
> +
> + if (CompressFlag == NULL) {
> + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> + if (BnY == NULL) {
> + goto fail;
> + }
> +
> + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> + } else {
> + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> + goto fail;
> + }
> + }
> +
> + // Validate NIST ECDH public key
> + OpenSslNid = EC_GROUP_get_curve_name (Group);
> + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> + if (PeerEcKey == NULL) {
> + goto fail;
> + }
> +
> + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> + goto fail;
> + }
> +
> + if (EC_KEY_check_key (PeerEcKey) != 1) {
> + goto fail;
> + }
> +
> + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> + goto fail;
> + }
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + EC_POINT_free (Point);
> + EC_KEY_free (PeerEcKey);
> + return RetVal;
> +}
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> new file mode 100644
> index 0000000000..d9f1004f6c
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> @@ -0,0 +1,496 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseCryptLib.h>
> +#include <Library/DebugLib.h>
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index ce6a789dfd..4bc3063485 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> @@ -59,6 +59,7 @@
> Pk/CryptTsNull.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSignNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPem.c
> Bn/CryptBnNull.c
>
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> index 354f3d80aa..e1a57ef09f 100644
> --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> @@ -49,6 +49,7 @@
> Pk/CryptX509Null.c
> Pk/CryptAuthenticodeNull.c
> Pk/CryptTsNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPemNull.c
> Rand/CryptRandNull.c
> Pk/CryptRsaPssNull.c
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> new file mode 100644
> index 0000000000..d9f1004f6c
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> @@ -0,0 +1,496 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseCryptLib.h>
> +#include <Library/DebugLib.h>
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> --
> 2.31.1.windows.1
>
>
>
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-21 16:21 ` [edk2-devel] " Michael D Kinney
@ 2022-09-22 2:15 ` yi1 li
2022-09-22 3:56 ` Michael D Kinney
0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-22 2:15 UTC (permalink / raw)
To: Kinney, Michael D, devel@edk2.groups.io
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Hi Mike,
Thanks for review.
Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as an error
1 file(s) copied.
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name' undefined; assuming extern returning int
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in levels of indirection from 'int'
d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined; assuming extern returning int
I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L202-L238
if PcdOpensslEcEnabled not true, all ec files will not be compiled.
This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are welcome.
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Thursday, September 22, 2022 12:22 AM
To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Comments embedded below.
Mike
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> Sent: Tuesday, September 20, 2022 9:55 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
>
> This patch is used to add CryptEc library, which is wrapped
> over OpenSSL.
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
>
> Signed-off-by: Yi Li <yi1.li@intel.com>
> ---
> CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> 8 files changed, 2186 insertions(+)
> create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
>
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> index b253923dd8..d74fc21c1e 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>
> #include <Uefi/UefiBaseType.h>
>
> +#define CRYPTO_NID_NULL 0x0000
> +
> +// Key Exchange
> +#define CRYPTO_NID_SECP256R1 0x0204
> +#define CRYPTO_NID_SECP384R1 0x0205
> +#define CRYPTO_NID_SECP521R1 0x0206
> +
> ///
> /// MD5 digest size in bytes
> ///
> @@ -2850,4 +2857,421 @@ BigNumAddMod (
> OUT VOID *BnRes
> );
>
> +// =====================================================================================
> +// Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + );
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient.
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + );
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + );
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + );
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + );
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + );
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + );
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + );
> +
> +// =====================================================================================
> +// Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + );
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + );
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + );
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + );
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + );
> +
> #endif // __BASE_CRYPT_LIB_H__
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 9e4be2fb0d..ade6ee3fdd 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -52,6 +52,8 @@
> Pk/CryptTs.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSign.c
> + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
The use of the PCD to select the file should not be needed here. The
Ec Family and individual service enable/disable fields in the
PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
disable the Ec services.
The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
completely as part of this patch series.
> Pem/CryptPem.c
> Bn/CryptBn.c
>
> diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> index 65ad23fb81..383df2b23c 100644
> --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> @@ -58,6 +58,7 @@
> Pk/CryptTsNull.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSignNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPemNull.c
> Rand/CryptRandNull.c
> Bn/CryptBnNull.c
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> new file mode 100644
> index 0000000000..396c819834
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> @@ -0,0 +1,765 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "InternalCryptLib.h"
> +#include <openssl/objects.h>
> +#include <openssl/bn.h>
> +#include <openssl/ec.h>
> +
> +// =====================================================================================
> +// Basic Elliptic Curve Primitives
> +// =====================================================================================
> +
> +/**
> + Return the Nid of certain ECC curve.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval !=-1 On success.
> + @retval -1 ECC curve not supported.
> +**/
> +STATIC
> +INT32
> +CryptoNidToOpensslNid (
> + IN UINTN CryptoNid
> + )
> +{
> + INT32 Nid;
> +
> + switch (CryptoNid) {
> + case CRYPTO_NID_SECP256R1:
> + Nid = NID_X9_62_prime256v1;
> + break;
> + case CRYPTO_NID_SECP384R1:
> + Nid = NID_secp384r1;
> + break;
> + case CRYPTO_NID_SECP521R1:
> + Nid = NID_secp521r1;
> + break;
> + default:
> + return -1;
> + }
> +
> + return Nid;
> +}
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + INT32 Nid;
> +
> + Nid = CryptoNidToOpensslNid (CryptoNid);
> +
> + if (Nid < 0) {
> + return NULL;
> + }
> +
> + return EC_GROUP_new_by_curve_name (Nid);
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + EC_GROUP_free (EcGroup);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + return EC_POINT_new (EcGroup);
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + if (Clear) {
> + EC_POINT_clear_free (EcPoint);
> + } else {
> + EC_POINT_free (EcPoint);
> + }
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> +}
> +
> +// =====================================================================================
> +// Elliptic Curve Diffie Hellman Primitives
> +// =====================================================================================
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + INT32 OpenSslNid;
> +
> + OpenSslNid = CryptoNidToOpensslNid (Nid);
> + if (OpenSslNid < 0) {
> + return NULL;
> + }
> +
> + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + EC_KEY_free ((EC_KEY *)EcContext);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + EC_KEY *EcKey;
> + CONST EC_GROUP *Group;
> + CONST EC_POINT *EcPoint;
> + BOOLEAN RetVal;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + UINTN HalfSize;
> + INTN XSize;
> + INTN YSize;
> +
> + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> +
> + // Assume RAND_seed was called
> + if (EC_KEY_generate_key (EcKey) != 1) {
> + return FALSE;
> + }
> +
> + if (*PublicKeySize < HalfSize * 2) {
> + *PublicKeySize = HalfSize * 2;
> + return FALSE;
> + }
> +
> + *PublicKeySize = HalfSize * 2;
> +
> + EcPoint = EC_KEY_get0_public_key (EcKey);
> + if (EcPoint == NULL) {
> + return FALSE;
> + }
> +
> + RetVal = FALSE;
> + BnX = BN_new ();
> + BnY = BN_new ();
> + if ((BnX == NULL) || (BnY == NULL)) {
> + goto fail;
> + }
> +
> + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> +
> + XSize = BN_num_bytes (BnX);
> + YSize = BN_num_bytes (BnY);
> + if ((XSize <= 0) || (YSize <= 0)) {
> + goto fail;
> + }
> +
> + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> +
> + ZeroMem (PublicKey, *PublicKeySize);
> + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + return RetVal;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + EC_KEY *EcKey;
> + CONST EC_GROUP *Group;
> + CONST EC_POINT *EcPoint;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + UINTN HalfSize;
> + INTN XSize;
> + INTN YSize;
> + BOOLEAN RetVal;
> +
> + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> + if (*PublicKeySize < HalfSize * 2) {
> + *PublicKeySize = HalfSize * 2;
> + return FALSE;
> + }
> +
> + *PublicKeySize = HalfSize * 2;
> +
> + EcPoint = EC_KEY_get0_public_key (EcKey);
> + if (EcPoint == NULL) {
> + return FALSE;
> + }
> +
> + RetVal = FALSE;
> + BnX = BN_new ();
> + BnY = BN_new ();
> + if ((BnX == NULL) || (BnY == NULL)) {
> + goto fail;
> + }
> +
> + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> +
> + XSize = BN_num_bytes (BnX);
> + YSize = BN_num_bytes (BnY);
> + if ((XSize <= 0) || (YSize <= 0)) {
> + goto fail;
> + }
> +
> + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> +
> + if (PublicKey != NULL) {
> + ZeroMem (PublicKey, *PublicKeySize);
> + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> + }
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + return RetVal;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If public key is compressed, the PeerPublic will only contain half key (X).
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + EC_KEY *EcKey;
> + EC_KEY *PeerEcKey;
> + CONST EC_GROUP *Group;
> + BOOLEAN RetVal;
> + BIGNUM *BnX;
> + BIGNUM *BnY;
> + EC_POINT *Point;
> + INT32 OpenSslNid;
> + UINTN HalfSize;
> +
> + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> + return FALSE;
> + }
> +
> + if ((Key == NULL) && (*KeySize != 0)) {
> + return FALSE;
> + }
> +
> + if (PeerPublicSize > INT_MAX) {
> + return FALSE;
> + }
> +
> + EcKey = (EC_KEY *)EcContext;
> + Group = EC_KEY_get0_group (EcKey);
> + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> + return FALSE;
> + }
> +
> + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> + return FALSE;
> + }
> +
> + if (*KeySize < HalfSize) {
> + *KeySize = HalfSize;
> + return FALSE;
> + }
> +
> + *KeySize = HalfSize;
> +
> + RetVal = FALSE;
> + Point = NULL;
> + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> + BnY = NULL;
> + Point = EC_POINT_new (Group);
> + PeerEcKey = NULL;
> + if ((BnX == NULL) || (Point == NULL)) {
> + goto fail;
> + }
> +
> + if (CompressFlag == NULL) {
> + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> + if (BnY == NULL) {
> + goto fail;
> + }
> +
> + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> + goto fail;
> + }
> + } else {
> + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> + goto fail;
> + }
> + }
> +
> + // Validate NIST ECDH public key
> + OpenSslNid = EC_GROUP_get_curve_name (Group);
> + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> + if (PeerEcKey == NULL) {
> + goto fail;
> + }
> +
> + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> + goto fail;
> + }
> +
> + if (EC_KEY_check_key (PeerEcKey) != 1) {
> + goto fail;
> + }
> +
> + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> + goto fail;
> + }
> +
> + RetVal = TRUE;
> +
> +fail:
> + BN_free (BnX);
> + BN_free (BnY);
> + EC_POINT_free (Point);
> + EC_KEY_free (PeerEcKey);
> + return RetVal;
> +}
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> new file mode 100644
> index 0000000000..d9f1004f6c
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> @@ -0,0 +1,496 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseCryptLib.h>
> +#include <Library/DebugLib.h>
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index ce6a789dfd..4bc3063485 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> @@ -59,6 +59,7 @@
> Pk/CryptTsNull.c
> Pk/CryptRsaPss.c
> Pk/CryptRsaPssSignNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPem.c
> Bn/CryptBnNull.c
>
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> index 354f3d80aa..e1a57ef09f 100644
> --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> @@ -49,6 +49,7 @@
> Pk/CryptX509Null.c
> Pk/CryptAuthenticodeNull.c
> Pk/CryptTsNull.c
> + Pk/CryptEcNull.c
> Pem/CryptPemNull.c
> Rand/CryptRandNull.c
> Pk/CryptRsaPssNull.c
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> new file mode 100644
> index 0000000000..d9f1004f6c
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> @@ -0,0 +1,496 @@
> +/** @file
> + Elliptic Curve and ECDH API implementation based on OpenSSL
> +
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/BaseCryptLib.h>
> +#include <Library/DebugLib.h>
> +
> +/**
> + Initialize new opaque EcGroup object. This object represents an EC curve and
> + and is used for calculation within this group. This object should be freed
> + using EcGroupFree() function.
> +
> + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> + BaseCryptLib.h).
> +
> + @retval EcGroup object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcGroupInit (
> + IN UINTN CryptoNid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnPrime Group prime number.
> + @param[out] BnA A coefficient.
> + @param[out] BnB B coefficient..
> + @param[in] BnCtx BN context.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetCurve (
> + IN CONST VOID *EcGroup,
> + OUT VOID *BnPrime,
> + OUT VOID *BnA,
> + OUT VOID *BnB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Get EC group order.
> + This function will set the provided Big Number object to the corresponding
> + value. The caller needs to make sure that the "out" BigNumber parameter
> + is properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] BnOrder Group prime number.
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGroupGetOrder (
> + IN VOID *EcGroup,
> + OUT VOID *BnOrder
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Free previously allocated EC group object using EcGroupInit().
> +
> + @param[in] EcGroup EC group object to free.
> +**/
> +VOID
> +EFIAPI
> +EcGroupFree (
> + IN VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Initialize new opaque EC Point object. This object represents an EC point
> + within the given EC group (curve).
> +
> + @param[in] EC Group, properly initialized using EcGroupInit().
> +
> + @retval EC Point object On success.
> + @retval NULL On failure.
> +**/
> +VOID *
> +EFIAPI
> +EcPointInit (
> + IN CONST VOID *EcGroup
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Free previously allocated EC Point object using EcPointInit().
> +
> + @param[in] EcPoint EC Point to free.
> + @param[in] Clear TRUE iff the memory should be cleared.
> +**/
> +VOID
> +EFIAPI
> +EcPointDeInit (
> + IN VOID *EcPoint,
> + IN BOOLEAN Clear
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Get EC point affine (x,y) coordinates.
> + This function will set the provided Big Number objects to the corresponding
> + values. The caller needs to make sure all the "out" BigNumber parameters
> + are properly initialized.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[out] BnX X coordinate.
> + @param[out] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointGetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + OUT VOID *BnX,
> + OUT VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point affine (x,y) coordinates.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point object.
> + @param[in] BnX X coordinate.
> + @param[in] BnY Y coordinate.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetAffineCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN CONST VOID *BnY,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + EC Point addition. EcPointResult = EcPointA + EcPointB.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPointA EC Point.
> + @param[in] EcPointB EC Point.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointAdd (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> +
> + @param[in] EcGroup EC group object.
> + @param[out] EcPointResult EC point to hold the result. The point should
> + be properly initialized.
> + @param[in] EcPoint EC Point.
> + @param[in] BnPScalar P Scalar.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointMul (
> + IN CONST VOID *EcGroup,
> + OUT VOID *EcPointResult,
> + IN CONST VOID *EcPoint,
> + IN CONST VOID *BnPScalar,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Calculate the inverse of the supplied EC point.
> +
> + @param[in] EcGroup EC group object.
> + @param[in,out] EcPoint EC point to invert.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointInvert (
> + IN CONST VOID *EcGroup,
> + IN OUT VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is on EC curve.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On curve.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsOnCurve (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if the supplied point is at infinity.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC point to check.
> +
> + @retval TRUE At infinity.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointIsAtInfinity (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPoint
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Check if EC points are equal.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPointA EC point A.
> + @param[in] EcPointB EC point B.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE A == B.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointEqual (
> + IN CONST VOID *EcGroup,
> + IN CONST VOID *EcPointA,
> + IN CONST VOID *EcPointB,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Set EC point compressed coordinates. Points can be described in terms of
> + their compressed coordinates. For a point (x, y), for any given value for x
> + such that the point is on the curve there will only ever be two possible
> + values for y. Therefore, a point can be set using this function where BnX is
> + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> + possible values for y should be used.
> +
> + @param[in] EcGroup EC group object.
> + @param[in] EcPoint EC Point.
> + @param[in] BnX X coordinate.
> + @param[in] YBit 0 or 1 to identify which Y value is used.
> + @param[in] BnCtx BN context, created with BigNumNewContext().
> +
> + @retval TRUE On success.
> + @retval FALSE Otherwise.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcPointSetCompressedCoordinates (
> + IN CONST VOID *EcGroup,
> + IN VOID *EcPoint,
> + IN CONST VOID *BnX,
> + IN UINT8 YBit,
> + IN VOID *BnCtx
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Allocates and Initializes one Elliptic Curve Context for subsequent use
> + with the NID.
> +
> + @param[in] Nid cipher NID
> + @return Pointer to the Elliptic Curve Context that has been initialized.
> + If the allocations fails, EcNewByNid() returns NULL.
> +**/
> +VOID *
> +EFIAPI
> +EcNewByNid (
> + IN UINTN Nid
> + )
> +{
> + ASSERT (FALSE);
> + return NULL;
> +}
> +
> +/**
> + Release the specified EC context.
> +
> + @param[in] EcContext Pointer to the EC context to be released.
> +**/
> +VOID
> +EFIAPI
> +EcFree (
> + IN VOID *EcContext
> + )
> +{
> + ASSERT (FALSE);
> +}
> +
> +/**
> + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> + pseudo random number generator. The caller must make sure RandomSeed()
> + function was properly called before.
> + The Ec context should be correctly initialized by EcNewByNid.
> + This function generates random secret, and computes the public key (X, Y), which is
> + returned via parameter Public, PublicSize.
> + X is the first half of Public with size being PublicSize / 2,
> + Y is the second half of Public with size being PublicSize / 2.
> + EC context is updated accordingly.
> + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> + PublicSize is set to the required buffer size to obtain the public X, Y.
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + If EcContext is NULL, then return FALSE.
> + If PublicSize is NULL, then return FALSE.
> + If PublicSize is large enough but Public is NULL, then return FALSE.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC public X,Y generation succeeded.
> + @retval FALSE EC public X,Y generation failed.
> + @retval FALSE PublicKeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGenerateKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Gets the public key component from the established EC context.
> + The Ec context should be correctly initialized by EcNewByNid, and successfully
> + generate key pair from EcGenerateKey().
> + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to EC context being set.
> + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> + On output, the size of data returned in Public buffer in bytes.
> + @retval TRUE EC key component was retrieved successfully.
> + @retval FALSE Invalid EC key component.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcGetPubKey (
> + IN OUT VOID *EcContext,
> + OUT UINT8 *PublicKey,
> + IN OUT UINTN *PublicKeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> +
> +/**
> + Computes exchanged common key.
> + Given peer's public key (X, Y), this function computes the exchanged common key,
> + based on its own context including value of curve parameter and random secret.
> + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> + If EcContext is NULL, then return FALSE.
> + If PeerPublic is NULL, then return FALSE.
> + If PeerPublicSize is 0, then return FALSE.
> + If Key is NULL, then return FALSE.
> + If KeySize is not large enough, then return FALSE.
> + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> + @param[in, out] EcContext Pointer to the EC context.
> + @param[in] PeerPublic Pointer to the peer's public X,Y.
> + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> + @param[out] Key Pointer to the buffer to receive generated key.
> + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> + On output, the size of data returned in Key buffer in bytes.
> + @retval TRUE EC exchanged key generation succeeded.
> + @retval FALSE EC exchanged key generation failed.
> + @retval FALSE KeySize is not large enough.
> +**/
> +BOOLEAN
> +EFIAPI
> +EcDhComputeKey (
> + IN OUT VOID *EcContext,
> + IN CONST UINT8 *PeerPublic,
> + IN UINTN PeerPublicSize,
> + IN CONST INT32 *CompressFlag,
> + OUT UINT8 *Key,
> + IN OUT UINTN *KeySize
> + )
> +{
> + ASSERT (FALSE);
> + return FALSE;
> +}
> --
> 2.31.1.windows.1
>
>
>
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-22 2:15 ` yi1 li
@ 2022-09-22 3:56 ` Michael D Kinney
2022-09-22 12:54 ` yi1 li
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-22 3:56 UTC (permalink / raw)
To: Li, Yi1, devel@edk2.groups.io, Kishore, Shelly
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
That change to OpensslLib.inf should not have been done either.
Looks like this EC feature needs more evaluation to fit into the
structured PCD control of the lib sizes.
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 21, 2022 7:16 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
> Thanks for review.
>
> Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
>
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as
> an error
> 1 file(s) copied.
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> undefined; assuming extern returning int
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> levels of indirection from 'int'
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> assuming extern returning int
>
> I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> 02-L238
> if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
>
> So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> welcome.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 12:22 AM
> To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Comments embedded below.
>
> Mike
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > Sent: Tuesday, September 20, 2022 9:55 PM
> > To: devel@edk2.groups.io
> > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> >
> > This patch is used to add CryptEc library, which is wrapped
> > over OpenSSL.
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > Cc: Guomin Jiang <guomin.jiang@intel.com>
> >
> > Signed-off-by: Yi Li <yi1.li@intel.com>
> > ---
> > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > 8 files changed, 2186 insertions(+)
> > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index b253923dd8..d74fc21c1e 100644
> > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > #include <Uefi/UefiBaseType.h>
> >
> > +#define CRYPTO_NID_NULL 0x0000
> > +
> > +// Key Exchange
> > +#define CRYPTO_NID_SECP256R1 0x0204
> > +#define CRYPTO_NID_SECP384R1 0x0205
> > +#define CRYPTO_NID_SECP521R1 0x0206
> > +
> > ///
> > /// MD5 digest size in bytes
> > ///
> > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > OUT VOID *BnRes
> > );
> >
> > +// =====================================================================================
> > +// Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + );
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient.
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + );
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + );
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + );
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + );
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + );
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + );
> > +
> > +// =====================================================================================
> > +// Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + );
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + );
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + );
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + );
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + );
> > +
> > #endif // __BASE_CRYPT_LIB_H__
> > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > index 9e4be2fb0d..ade6ee3fdd 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > @@ -52,6 +52,8 @@
> > Pk/CryptTs.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSign.c
> > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
>
> The use of the PCD to select the file should not be needed here. The
> Ec Family and individual service enable/disable fields in the
> PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> disable the Ec services.
>
> The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> completely as part of this patch series.
>
> > Pem/CryptPem.c
> > Bn/CryptBn.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > index 65ad23fb81..383df2b23c 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > @@ -58,6 +58,7 @@
> > Pk/CryptTsNull.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSignNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPemNull.c
> > Rand/CryptRandNull.c
> > Bn/CryptBnNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > new file mode 100644
> > index 0000000000..396c819834
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > @@ -0,0 +1,765 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "InternalCryptLib.h"
> > +#include <openssl/objects.h>
> > +#include <openssl/bn.h>
> > +#include <openssl/ec.h>
> > +
> > +// =====================================================================================
> > +// Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Return the Nid of certain ECC curve.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval !=-1 On success.
> > + @retval -1 ECC curve not supported.
> > +**/
> > +STATIC
> > +INT32
> > +CryptoNidToOpensslNid (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + INT32 Nid;
> > +
> > + switch (CryptoNid) {
> > + case CRYPTO_NID_SECP256R1:
> > + Nid = NID_X9_62_prime256v1;
> > + break;
> > + case CRYPTO_NID_SECP384R1:
> > + Nid = NID_secp384r1;
> > + break;
> > + case CRYPTO_NID_SECP521R1:
> > + Nid = NID_secp521r1;
> > + break;
> > + default:
> > + return -1;
> > + }
> > +
> > + return Nid;
> > +}
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + INT32 Nid;
> > +
> > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > +
> > + if (Nid < 0) {
> > + return NULL;
> > + }
> > +
> > + return EC_GROUP_new_by_curve_name (Nid);
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + EC_GROUP_free (EcGroup);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + return EC_POINT_new (EcGroup);
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + if (Clear) {
> > + EC_POINT_clear_free (EcPoint);
> > + } else {
> > + EC_POINT_free (EcPoint);
> > + }
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > +}
> > +
> > +// =====================================================================================
> > +// Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + INT32 OpenSslNid;
> > +
> > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > + if (OpenSslNid < 0) {
> > + return NULL;
> > + }
> > +
> > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + EC_KEY_free ((EC_KEY *)EcContext);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + CONST EC_GROUP *Group;
> > + CONST EC_POINT *EcPoint;
> > + BOOLEAN RetVal;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + UINTN HalfSize;
> > + INTN XSize;
> > + INTN YSize;
> > +
> > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +
> > + // Assume RAND_seed was called
> > + if (EC_KEY_generate_key (EcKey) != 1) {
> > + return FALSE;
> > + }
> > +
> > + if (*PublicKeySize < HalfSize * 2) {
> > + *PublicKeySize = HalfSize * 2;
> > + return FALSE;
> > + }
> > +
> > + *PublicKeySize = HalfSize * 2;
> > +
> > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > + if (EcPoint == NULL) {
> > + return FALSE;
> > + }
> > +
> > + RetVal = FALSE;
> > + BnX = BN_new ();
> > + BnY = BN_new ();
> > + if ((BnX == NULL) || (BnY == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > +
> > + XSize = BN_num_bytes (BnX);
> > + YSize = BN_num_bytes (BnY);
> > + if ((XSize <= 0) || (YSize <= 0)) {
> > + goto fail;
> > + }
> > +
> > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > + ZeroMem (PublicKey, *PublicKeySize);
> > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + return RetVal;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + CONST EC_GROUP *Group;
> > + CONST EC_POINT *EcPoint;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + UINTN HalfSize;
> > + INTN XSize;
> > + INTN YSize;
> > + BOOLEAN RetVal;
> > +
> > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > + if (*PublicKeySize < HalfSize * 2) {
> > + *PublicKeySize = HalfSize * 2;
> > + return FALSE;
> > + }
> > +
> > + *PublicKeySize = HalfSize * 2;
> > +
> > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > + if (EcPoint == NULL) {
> > + return FALSE;
> > + }
> > +
> > + RetVal = FALSE;
> > + BnX = BN_new ();
> > + BnY = BN_new ();
> > + if ((BnX == NULL) || (BnY == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > +
> > + XSize = BN_num_bytes (BnX);
> > + YSize = BN_num_bytes (BnY);
> > + if ((XSize <= 0) || (YSize <= 0)) {
> > + goto fail;
> > + }
> > +
> > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > + if (PublicKey != NULL) {
> > + ZeroMem (PublicKey, *PublicKeySize);
> > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > + }
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + return RetVal;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If public key is compressed, the PeerPublic will only contain half key (X).
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + EC_KEY *PeerEcKey;
> > + CONST EC_GROUP *Group;
> > + BOOLEAN RetVal;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + EC_POINT *Point;
> > + INT32 OpenSslNid;
> > + UINTN HalfSize;
> > +
> > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((Key == NULL) && (*KeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + if (PeerPublicSize > INT_MAX) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > + return FALSE;
> > + }
> > +
> > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > + return FALSE;
> > + }
> > +
> > + if (*KeySize < HalfSize) {
> > + *KeySize = HalfSize;
> > + return FALSE;
> > + }
> > +
> > + *KeySize = HalfSize;
> > +
> > + RetVal = FALSE;
> > + Point = NULL;
> > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > + BnY = NULL;
> > + Point = EC_POINT_new (Group);
> > + PeerEcKey = NULL;
> > + if ((BnX == NULL) || (Point == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (CompressFlag == NULL) {
> > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > + if (BnY == NULL) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > + } else {
> > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > + goto fail;
> > + }
> > + }
> > +
> > + // Validate NIST ECDH public key
> > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > + if (PeerEcKey == NULL) {
> > + goto fail;
> > + }
> > +
> > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > + goto fail;
> > + }
> > +
> > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > + goto fail;
> > + }
> > +
> > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > + goto fail;
> > + }
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + EC_POINT_free (Point);
> > + EC_KEY_free (PeerEcKey);
> > + return RetVal;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index ce6a789dfd..4bc3063485 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > @@ -59,6 +59,7 @@
> > Pk/CryptTsNull.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSignNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPem.c
> > Bn/CryptBnNull.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > index 354f3d80aa..e1a57ef09f 100644
> > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > @@ -49,6 +49,7 @@
> > Pk/CryptX509Null.c
> > Pk/CryptAuthenticodeNull.c
> > Pk/CryptTsNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPemNull.c
> > Rand/CryptRandNull.c
> > Pk/CryptRsaPssNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > --
> > 2.31.1.windows.1
> >
> >
> >
> >
> >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-22 3:56 ` Michael D Kinney
@ 2022-09-22 12:54 ` yi1 li
2022-09-22 22:46 ` Michael D Kinney
0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-22 12:54 UTC (permalink / raw)
To: Kinney, Michael D, devel@edk2.groups.io, Kishore, Shelly
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Hi Mike,
I have did some POC that seems existed structured PCD is hard to control binary size,
Here is the previous discussion for reference.
https://bugzilla.tianocore.org/show_bug.cgi?id=3679
https://edk2.groups.io/g/devel/topic/86257810#81814
https://bugzilla.tianocore.org/show_bug.cgi?id=1446
Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Thursday, September 22, 2022 11:56 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
That change to OpensslLib.inf should not have been done either.
Looks like this EC feature needs more evaluation to fit into the
structured PCD control of the lib sizes.
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 21, 2022 7:16 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
> Thanks for review.
>
> Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
>
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated as
> an error
> 1 file(s) copied.
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> undefined; assuming extern returning int
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> levels of indirection from 'int'
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> assuming extern returning int
>
> I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> 02-L238
> if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
>
> So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> welcome.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 12:22 AM
> To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Comments embedded below.
>
> Mike
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > Sent: Tuesday, September 20, 2022 9:55 PM
> > To: devel@edk2.groups.io
> > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> >
> > This patch is used to add CryptEc library, which is wrapped
> > over OpenSSL.
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > Cc: Guomin Jiang <guomin.jiang@intel.com>
> >
> > Signed-off-by: Yi Li <yi1.li@intel.com>
> > ---
> > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > 8 files changed, 2186 insertions(+)
> > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index b253923dd8..d74fc21c1e 100644
> > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > #include <Uefi/UefiBaseType.h>
> >
> > +#define CRYPTO_NID_NULL 0x0000
> > +
> > +// Key Exchange
> > +#define CRYPTO_NID_SECP256R1 0x0204
> > +#define CRYPTO_NID_SECP384R1 0x0205
> > +#define CRYPTO_NID_SECP521R1 0x0206
> > +
> > ///
> > /// MD5 digest size in bytes
> > ///
> > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > OUT VOID *BnRes
> > );
> >
> > +// =====================================================================================
> > +// Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + );
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient.
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + );
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + );
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + );
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + );
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + );
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + );
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + );
> > +
> > +// =====================================================================================
> > +// Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + );
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + );
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + );
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + );
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + );
> > +
> > #endif // __BASE_CRYPT_LIB_H__
> > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > index 9e4be2fb0d..ade6ee3fdd 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > @@ -52,6 +52,8 @@
> > Pk/CryptTs.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSign.c
> > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
>
> The use of the PCD to select the file should not be needed here. The
> Ec Family and individual service enable/disable fields in the
> PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> disable the Ec services.
>
> The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> completely as part of this patch series.
>
> > Pem/CryptPem.c
> > Bn/CryptBn.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > index 65ad23fb81..383df2b23c 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > @@ -58,6 +58,7 @@
> > Pk/CryptTsNull.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSignNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPemNull.c
> > Rand/CryptRandNull.c
> > Bn/CryptBnNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > new file mode 100644
> > index 0000000000..396c819834
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > @@ -0,0 +1,765 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "InternalCryptLib.h"
> > +#include <openssl/objects.h>
> > +#include <openssl/bn.h>
> > +#include <openssl/ec.h>
> > +
> > +// =====================================================================================
> > +// Basic Elliptic Curve Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Return the Nid of certain ECC curve.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval !=-1 On success.
> > + @retval -1 ECC curve not supported.
> > +**/
> > +STATIC
> > +INT32
> > +CryptoNidToOpensslNid (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + INT32 Nid;
> > +
> > + switch (CryptoNid) {
> > + case CRYPTO_NID_SECP256R1:
> > + Nid = NID_X9_62_prime256v1;
> > + break;
> > + case CRYPTO_NID_SECP384R1:
> > + Nid = NID_secp384r1;
> > + break;
> > + case CRYPTO_NID_SECP521R1:
> > + Nid = NID_secp521r1;
> > + break;
> > + default:
> > + return -1;
> > + }
> > +
> > + return Nid;
> > +}
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + INT32 Nid;
> > +
> > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > +
> > + if (Nid < 0) {
> > + return NULL;
> > + }
> > +
> > + return EC_GROUP_new_by_curve_name (Nid);
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + EC_GROUP_free (EcGroup);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + return EC_POINT_new (EcGroup);
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + if (Clear) {
> > + EC_POINT_clear_free (EcPoint);
> > + } else {
> > + EC_POINT_free (EcPoint);
> > + }
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > +}
> > +
> > +// =====================================================================================
> > +// Elliptic Curve Diffie Hellman Primitives
> > +// =====================================================================================
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + INT32 OpenSslNid;
> > +
> > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > + if (OpenSslNid < 0) {
> > + return NULL;
> > + }
> > +
> > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + EC_KEY_free ((EC_KEY *)EcContext);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + CONST EC_GROUP *Group;
> > + CONST EC_POINT *EcPoint;
> > + BOOLEAN RetVal;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + UINTN HalfSize;
> > + INTN XSize;
> > + INTN YSize;
> > +
> > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > +
> > + // Assume RAND_seed was called
> > + if (EC_KEY_generate_key (EcKey) != 1) {
> > + return FALSE;
> > + }
> > +
> > + if (*PublicKeySize < HalfSize * 2) {
> > + *PublicKeySize = HalfSize * 2;
> > + return FALSE;
> > + }
> > +
> > + *PublicKeySize = HalfSize * 2;
> > +
> > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > + if (EcPoint == NULL) {
> > + return FALSE;
> > + }
> > +
> > + RetVal = FALSE;
> > + BnX = BN_new ();
> > + BnY = BN_new ();
> > + if ((BnX == NULL) || (BnY == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > +
> > + XSize = BN_num_bytes (BnX);
> > + YSize = BN_num_bytes (BnY);
> > + if ((XSize <= 0) || (YSize <= 0)) {
> > + goto fail;
> > + }
> > +
> > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > + ZeroMem (PublicKey, *PublicKeySize);
> > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + return RetVal;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + CONST EC_GROUP *Group;
> > + CONST EC_POINT *EcPoint;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + UINTN HalfSize;
> > + INTN XSize;
> > + INTN YSize;
> > + BOOLEAN RetVal;
> > +
> > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > + if (*PublicKeySize < HalfSize * 2) {
> > + *PublicKeySize = HalfSize * 2;
> > + return FALSE;
> > + }
> > +
> > + *PublicKeySize = HalfSize * 2;
> > +
> > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > + if (EcPoint == NULL) {
> > + return FALSE;
> > + }
> > +
> > + RetVal = FALSE;
> > + BnX = BN_new ();
> > + BnY = BN_new ();
> > + if ((BnX == NULL) || (BnY == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > +
> > + XSize = BN_num_bytes (BnX);
> > + YSize = BN_num_bytes (BnY);
> > + if ((XSize <= 0) || (YSize <= 0)) {
> > + goto fail;
> > + }
> > +
> > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > +
> > + if (PublicKey != NULL) {
> > + ZeroMem (PublicKey, *PublicKeySize);
> > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > + }
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + return RetVal;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If public key is compressed, the PeerPublic will only contain half key (X).
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + EC_KEY *EcKey;
> > + EC_KEY *PeerEcKey;
> > + CONST EC_GROUP *Group;
> > + BOOLEAN RetVal;
> > + BIGNUM *BnX;
> > + BIGNUM *BnY;
> > + EC_POINT *Point;
> > + INT32 OpenSslNid;
> > + UINTN HalfSize;
> > +
> > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > + return FALSE;
> > + }
> > +
> > + if ((Key == NULL) && (*KeySize != 0)) {
> > + return FALSE;
> > + }
> > +
> > + if (PeerPublicSize > INT_MAX) {
> > + return FALSE;
> > + }
> > +
> > + EcKey = (EC_KEY *)EcContext;
> > + Group = EC_KEY_get0_group (EcKey);
> > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > + return FALSE;
> > + }
> > +
> > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > + return FALSE;
> > + }
> > +
> > + if (*KeySize < HalfSize) {
> > + *KeySize = HalfSize;
> > + return FALSE;
> > + }
> > +
> > + *KeySize = HalfSize;
> > +
> > + RetVal = FALSE;
> > + Point = NULL;
> > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > + BnY = NULL;
> > + Point = EC_POINT_new (Group);
> > + PeerEcKey = NULL;
> > + if ((BnX == NULL) || (Point == NULL)) {
> > + goto fail;
> > + }
> > +
> > + if (CompressFlag == NULL) {
> > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > + if (BnY == NULL) {
> > + goto fail;
> > + }
> > +
> > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > + goto fail;
> > + }
> > + } else {
> > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > + goto fail;
> > + }
> > + }
> > +
> > + // Validate NIST ECDH public key
> > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > + if (PeerEcKey == NULL) {
> > + goto fail;
> > + }
> > +
> > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > + goto fail;
> > + }
> > +
> > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > + goto fail;
> > + }
> > +
> > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > + goto fail;
> > + }
> > +
> > + RetVal = TRUE;
> > +
> > +fail:
> > + BN_free (BnX);
> > + BN_free (BnY);
> > + EC_POINT_free (Point);
> > + EC_KEY_free (PeerEcKey);
> > + return RetVal;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index ce6a789dfd..4bc3063485 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > @@ -59,6 +59,7 @@
> > Pk/CryptTsNull.c
> > Pk/CryptRsaPss.c
> > Pk/CryptRsaPssSignNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPem.c
> > Bn/CryptBnNull.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > index 354f3d80aa..e1a57ef09f 100644
> > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > @@ -49,6 +49,7 @@
> > Pk/CryptX509Null.c
> > Pk/CryptAuthenticodeNull.c
> > Pk/CryptTsNull.c
> > + Pk/CryptEcNull.c
> > Pem/CryptPemNull.c
> > Rand/CryptRandNull.c
> > Pk/CryptRsaPssNull.c
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > new file mode 100644
> > index 0000000000..d9f1004f6c
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > @@ -0,0 +1,496 @@
> > +/** @file
> > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > +
> > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Library/BaseCryptLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +/**
> > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > + and is used for calculation within this group. This object should be freed
> > + using EcGroupFree() function.
> > +
> > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > + BaseCryptLib.h).
> > +
> > + @retval EcGroup object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcGroupInit (
> > + IN UINTN CryptoNid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnPrime Group prime number.
> > + @param[out] BnA A coefficient.
> > + @param[out] BnB B coefficient..
> > + @param[in] BnCtx BN context.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetCurve (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *BnPrime,
> > + OUT VOID *BnA,
> > + OUT VOID *BnB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get EC group order.
> > + This function will set the provided Big Number object to the corresponding
> > + value. The caller needs to make sure that the "out" BigNumber parameter
> > + is properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] BnOrder Group prime number.
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGroupGetOrder (
> > + IN VOID *EcGroup,
> > + OUT VOID *BnOrder
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Free previously allocated EC group object using EcGroupInit().
> > +
> > + @param[in] EcGroup EC group object to free.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcGroupFree (
> > + IN VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Initialize new opaque EC Point object. This object represents an EC point
> > + within the given EC group (curve).
> > +
> > + @param[in] EC Group, properly initialized using EcGroupInit().
> > +
> > + @retval EC Point object On success.
> > + @retval NULL On failure.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcPointInit (
> > + IN CONST VOID *EcGroup
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Free previously allocated EC Point object using EcPointInit().
> > +
> > + @param[in] EcPoint EC Point to free.
> > + @param[in] Clear TRUE iff the memory should be cleared.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcPointDeInit (
> > + IN VOID *EcPoint,
> > + IN BOOLEAN Clear
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Get EC point affine (x,y) coordinates.
> > + This function will set the provided Big Number objects to the corresponding
> > + values. The caller needs to make sure all the "out" BigNumber parameters
> > + are properly initialized.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[out] BnX X coordinate.
> > + @param[out] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointGetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + OUT VOID *BnX,
> > + OUT VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point affine (x,y) coordinates.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point object.
> > + @param[in] BnX X coordinate.
> > + @param[in] BnY Y coordinate.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetAffineCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN CONST VOID *BnY,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPointA EC Point.
> > + @param[in] EcPointB EC Point.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointAdd (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[out] EcPointResult EC point to hold the result. The point should
> > + be properly initialized.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnPScalar P Scalar.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointMul (
> > + IN CONST VOID *EcGroup,
> > + OUT VOID *EcPointResult,
> > + IN CONST VOID *EcPoint,
> > + IN CONST VOID *BnPScalar,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Calculate the inverse of the supplied EC point.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in,out] EcPoint EC point to invert.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointInvert (
> > + IN CONST VOID *EcGroup,
> > + IN OUT VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is on EC curve.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On curve.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsOnCurve (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if the supplied point is at infinity.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC point to check.
> > +
> > + @retval TRUE At infinity.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointIsAtInfinity (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPoint
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Check if EC points are equal.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPointA EC point A.
> > + @param[in] EcPointB EC point B.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE A == B.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointEqual (
> > + IN CONST VOID *EcGroup,
> > + IN CONST VOID *EcPointA,
> > + IN CONST VOID *EcPointB,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Set EC point compressed coordinates. Points can be described in terms of
> > + their compressed coordinates. For a point (x, y), for any given value for x
> > + such that the point is on the curve there will only ever be two possible
> > + values for y. Therefore, a point can be set using this function where BnX is
> > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > + possible values for y should be used.
> > +
> > + @param[in] EcGroup EC group object.
> > + @param[in] EcPoint EC Point.
> > + @param[in] BnX X coordinate.
> > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > +
> > + @retval TRUE On success.
> > + @retval FALSE Otherwise.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcPointSetCompressedCoordinates (
> > + IN CONST VOID *EcGroup,
> > + IN VOID *EcPoint,
> > + IN CONST VOID *BnX,
> > + IN UINT8 YBit,
> > + IN VOID *BnCtx
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > + with the NID.
> > +
> > + @param[in] Nid cipher NID
> > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > + If the allocations fails, EcNewByNid() returns NULL.
> > +**/
> > +VOID *
> > +EFIAPI
> > +EcNewByNid (
> > + IN UINTN Nid
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return NULL;
> > +}
> > +
> > +/**
> > + Release the specified EC context.
> > +
> > + @param[in] EcContext Pointer to the EC context to be released.
> > +**/
> > +VOID
> > +EFIAPI
> > +EcFree (
> > + IN VOID *EcContext
> > + )
> > +{
> > + ASSERT (FALSE);
> > +}
> > +
> > +/**
> > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > + pseudo random number generator. The caller must make sure RandomSeed()
> > + function was properly called before.
> > + The Ec context should be correctly initialized by EcNewByNid.
> > + This function generates random secret, and computes the public key (X, Y), which is
> > + returned via parameter Public, PublicSize.
> > + X is the first half of Public with size being PublicSize / 2,
> > + Y is the second half of Public with size being PublicSize / 2.
> > + EC context is updated accordingly.
> > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + If EcContext is NULL, then return FALSE.
> > + If PublicSize is NULL, then return FALSE.
> > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC public X,Y generation succeeded.
> > + @retval FALSE EC public X,Y generation failed.
> > + @retval FALSE PublicKeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGenerateKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Gets the public key component from the established EC context.
> > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > + generate key pair from EcGenerateKey().
> > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to EC context being set.
> > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > + On output, the size of data returned in Public buffer in bytes.
> > + @retval TRUE EC key component was retrieved successfully.
> > + @retval FALSE Invalid EC key component.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcGetPubKey (
> > + IN OUT VOID *EcContext,
> > + OUT UINT8 *PublicKey,
> > + IN OUT UINTN *PublicKeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Computes exchanged common key.
> > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > + based on its own context including value of curve parameter and random secret.
> > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > + If EcContext is NULL, then return FALSE.
> > + If PeerPublic is NULL, then return FALSE.
> > + If PeerPublicSize is 0, then return FALSE.
> > + If Key is NULL, then return FALSE.
> > + If KeySize is not large enough, then return FALSE.
> > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > + @param[in, out] EcContext Pointer to the EC context.
> > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > + @param[out] Key Pointer to the buffer to receive generated key.
> > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > + On output, the size of data returned in Key buffer in bytes.
> > + @retval TRUE EC exchanged key generation succeeded.
> > + @retval FALSE EC exchanged key generation failed.
> > + @retval FALSE KeySize is not large enough.
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +EcDhComputeKey (
> > + IN OUT VOID *EcContext,
> > + IN CONST UINT8 *PeerPublic,
> > + IN UINTN PeerPublicSize,
> > + IN CONST INT32 *CompressFlag,
> > + OUT UINT8 *Key,
> > + IN OUT UINTN *KeySize
> > + )
> > +{
> > + ASSERT (FALSE);
> > + return FALSE;
> > +}
> > --
> > 2.31.1.windows.1
> >
> >
> >
> >
> >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-22 12:54 ` yi1 li
@ 2022-09-22 22:46 ` Michael D Kinney
2022-09-23 3:01 ` yi1 li
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-22 22:46 UTC (permalink / raw)
To: Li, Yi1, devel@edk2.groups.io, Kinney, Michael D
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Hi Yi,
I agree EC is an important feature.
I did some analysis of the size impact to the CryptoPkg modules on current trunk
with EC on and off. Uncompressed size is important for PEI Phase. For DXE and
SMM phase, the Crypto services can always be compressed. From the table below,
building all the EC services in the OpensslLib has no size impact to the NONE
profile and the MIN_PEI profile. It has ~105 KB impact to compressed DXE/SMM
usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
Uncompressed LZMA Compressed
CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE EC=TRUE Increase
==== =============== ======== ======== ======= ======== ======= ========
IA32 NONE CryptoPei 21536 21568 0 KB
IA32 NONE CryptoDxe 21632 21696 0 KB
IA32 NONE CryptoSmm 22976 23072 0 KB
IA32 MIN_PEI CryptoPei 248992 249120 0 KB
IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520 401034 113 KB
IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517 296022 105 KB
IA32 ALL CryptoPei 423840 598976 189047 293759 104 KB
IA32 ALL CryptoDxe 645280 838144 292955 405277 113 KB
IA32 ALL CryptoSmm 441888 617184 198779 303628 105 KB
X64 NONE CryptoPei 29632 29664 0 KB
X64 NONE CryptoDxe 29792 29792 0 KB
X64 NONE CryptoSmm 31296 31296 0 KB
X64 MIN_PEI CryptoPei 310784 310848 0 KB
X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436 426596 115 KB
X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483 310775 106 KB
X64 ALL CryptoPei 540384 730240 202494 308467 106 KB
X64 ALL CryptoDxe 815392 1027296 316228 431321 115 KB
X64 ALL CryptoSmm 563648 753696 213488 319644 106 KB
NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
entire FV is compressed, the total size impact is typically the size of a
single instance of a compressed CryptoLib. The sizes of the Crypto* modules
in the table above should be a close approximation of the size impact to a
single FV.
Does this match your previous size analysis?
The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
causes the modules that do not use any EC services to grow by ~105KB. Has any
detailed analysis of the final linked images been performed to see where this
additional size is coming from?
Thanks,
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 5:54 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
> I have did some POC that seems existed structured PCD is hard to control binary size,
> Here is the previous discussion for reference.
> https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> https://edk2.groups.io/g/devel/topic/86257810#81814
> https://bugzilla.tianocore.org/show_bug.cgi?id=1446
>
> Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 11:56 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> That change to OpensslLib.inf should not have been done either.
>
> Looks like this EC feature needs more evaluation to fit into the
> structured PCD control of the lib sizes.
>
> Mike
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Wednesday, September 21, 2022 7:16 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > Thanks for review.
> >
> > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> as
> > an error
> > 1 file(s) copied.
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > undefined; assuming extern returning int
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > levels of indirection from 'int'
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> > assuming extern returning int
> >
> > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > 02-L238
> > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> >
> > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> > welcome.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 12:22 AM
> > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Comments embedded below.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > To: devel@edk2.groups.io
> > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > >
> > > This patch is used to add CryptEc library, which is wrapped
> > > over OpenSSL.
> > >
> > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > >
> > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > ---
> > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > 8 files changed, 2186 insertions(+)
> > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > >
> > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > index b253923dd8..d74fc21c1e 100644
> > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > #include <Uefi/UefiBaseType.h>
> > >
> > > +#define CRYPTO_NID_NULL 0x0000
> > > +
> > > +// Key Exchange
> > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > +
> > > ///
> > > /// MD5 digest size in bytes
> > > ///
> > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > OUT VOID *BnRes
> > > );
> > >
> > > +// =====================================================================================
> > > +// Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + );
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient.
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + );
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + );
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + );
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + );
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + );
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +// =====================================================================================
> > > +// Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + );
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + );
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + );
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + );
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + );
> > > +
> > > #endif // __BASE_CRYPT_LIB_H__
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > @@ -52,6 +52,8 @@
> > > Pk/CryptTs.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSign.c
> > > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> >
> > The use of the PCD to select the file should not be needed here. The
> > Ec Family and individual service enable/disable fields in the
> > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > disable the Ec services.
> >
> > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > completely as part of this patch series.
> >
> > > Pem/CryptPem.c
> > > Bn/CryptBn.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > index 65ad23fb81..383df2b23c 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > @@ -58,6 +58,7 @@
> > > Pk/CryptTsNull.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSignNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPemNull.c
> > > Rand/CryptRandNull.c
> > > Bn/CryptBnNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > new file mode 100644
> > > index 0000000000..396c819834
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > @@ -0,0 +1,765 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "InternalCryptLib.h"
> > > +#include <openssl/objects.h>
> > > +#include <openssl/bn.h>
> > > +#include <openssl/ec.h>
> > > +
> > > +// =====================================================================================
> > > +// Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Return the Nid of certain ECC curve.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval !=-1 On success.
> > > + @retval -1 ECC curve not supported.
> > > +**/
> > > +STATIC
> > > +INT32
> > > +CryptoNidToOpensslNid (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + INT32 Nid;
> > > +
> > > + switch (CryptoNid) {
> > > + case CRYPTO_NID_SECP256R1:
> > > + Nid = NID_X9_62_prime256v1;
> > > + break;
> > > + case CRYPTO_NID_SECP384R1:
> > > + Nid = NID_secp384r1;
> > > + break;
> > > + case CRYPTO_NID_SECP521R1:
> > > + Nid = NID_secp521r1;
> > > + break;
> > > + default:
> > > + return -1;
> > > + }
> > > +
> > > + return Nid;
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + INT32 Nid;
> > > +
> > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > +
> > > + if (Nid < 0) {
> > > + return NULL;
> > > + }
> > > +
> > > + return EC_GROUP_new_by_curve_name (Nid);
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + EC_GROUP_free (EcGroup);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + return EC_POINT_new (EcGroup);
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + if (Clear) {
> > > + EC_POINT_clear_free (EcPoint);
> > > + } else {
> > > + EC_POINT_free (EcPoint);
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > +}
> > > +
> > > +// =====================================================================================
> > > +// Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + INT32 OpenSslNid;
> > > +
> > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > + if (OpenSslNid < 0) {
> > > + return NULL;
> > > + }
> > > +
> > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + CONST EC_GROUP *Group;
> > > + CONST EC_POINT *EcPoint;
> > > + BOOLEAN RetVal;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + UINTN HalfSize;
> > > + INTN XSize;
> > > + INTN YSize;
> > > +
> > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +
> > > + // Assume RAND_seed was called
> > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (*PublicKeySize < HalfSize * 2) {
> > > + *PublicKeySize = HalfSize * 2;
> > > + return FALSE;
> > > + }
> > > +
> > > + *PublicKeySize = HalfSize * 2;
> > > +
> > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > + if (EcPoint == NULL) {
> > > + return FALSE;
> > > + }
> > > +
> > > + RetVal = FALSE;
> > > + BnX = BN_new ();
> > > + BnY = BN_new ();
> > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + XSize = BN_num_bytes (BnX);
> > > + YSize = BN_num_bytes (BnY);
> > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > + goto fail;
> > > + }
> > > +
> > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > + ZeroMem (PublicKey, *PublicKeySize);
> > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + return RetVal;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + CONST EC_GROUP *Group;
> > > + CONST EC_POINT *EcPoint;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + UINTN HalfSize;
> > > + INTN XSize;
> > > + INTN YSize;
> > > + BOOLEAN RetVal;
> > > +
> > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > + if (*PublicKeySize < HalfSize * 2) {
> > > + *PublicKeySize = HalfSize * 2;
> > > + return FALSE;
> > > + }
> > > +
> > > + *PublicKeySize = HalfSize * 2;
> > > +
> > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > + if (EcPoint == NULL) {
> > > + return FALSE;
> > > + }
> > > +
> > > + RetVal = FALSE;
> > > + BnX = BN_new ();
> > > + BnY = BN_new ();
> > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + XSize = BN_num_bytes (BnX);
> > > + YSize = BN_num_bytes (BnY);
> > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > + goto fail;
> > > + }
> > > +
> > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > + if (PublicKey != NULL) {
> > > + ZeroMem (PublicKey, *PublicKeySize);
> > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > + }
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + return RetVal;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If public key is compressed, the PeerPublic will only contain half key (X).
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + EC_KEY *PeerEcKey;
> > > + CONST EC_GROUP *Group;
> > > + BOOLEAN RetVal;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + EC_POINT *Point;
> > > + INT32 OpenSslNid;
> > > + UINTN HalfSize;
> > > +
> > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (PeerPublicSize > INT_MAX) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (*KeySize < HalfSize) {
> > > + *KeySize = HalfSize;
> > > + return FALSE;
> > > + }
> > > +
> > > + *KeySize = HalfSize;
> > > +
> > > + RetVal = FALSE;
> > > + Point = NULL;
> > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > + BnY = NULL;
> > > + Point = EC_POINT_new (Group);
> > > + PeerEcKey = NULL;
> > > + if ((BnX == NULL) || (Point == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (CompressFlag == NULL) {
> > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > + if (BnY == NULL) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > + } else {
> > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > + }
> > > +
> > > + // Validate NIST ECDH public key
> > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > + if (PeerEcKey == NULL) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > + goto fail;
> > > + }
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + EC_POINT_free (Point);
> > > + EC_KEY_free (PeerEcKey);
> > > + return RetVal;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > index ce6a789dfd..4bc3063485 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > @@ -59,6 +59,7 @@
> > > Pk/CryptTsNull.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSignNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPem.c
> > > Bn/CryptBnNull.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > index 354f3d80aa..e1a57ef09f 100644
> > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > @@ -49,6 +49,7 @@
> > > Pk/CryptX509Null.c
> > > Pk/CryptAuthenticodeNull.c
> > > Pk/CryptTsNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPemNull.c
> > > Rand/CryptRandNull.c
> > > Pk/CryptRsaPssNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > --
> > > 2.31.1.windows.1
> > >
> > >
> > >
> > >
> > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-22 22:46 ` Michael D Kinney
@ 2022-09-23 3:01 ` yi1 li
2022-09-23 5:25 ` Michael D Kinney
0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-23 3:01 UTC (permalink / raw)
To: Kinney, Michael D, devel@edk2.groups.io
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Hi Mike,
1. Yes, it matches.
By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.
2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509 ...
If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary size,
This an example from x509/x_pubkey.c , other modules is similar:
#ifndef OPENSSL_NO_EC
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
EC_KEY *key = NULL;
//.... call EC functions
}
#endif
If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but not another.
This an example from ec/ec_local.h , other error is similar:
#ifndef OPENSSL_NO_EC
typedef struct ec_group_st EC_GROUP;
typedef struct ec_point_st EC_POINT;
#endif
// but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
EC_POINT *, const BIGNUM *x,
const BIGNUM *y,
const BIGNUM *z, BN_CTX *);
To avoid this annoying openssl error, we introduced conditional EC.
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Friday, September 23, 2022 6:47 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Yi,
I agree EC is an important feature.
I did some analysis of the size impact to the CryptoPkg modules on current trunk
with EC on and off. Uncompressed size is important for PEI Phase. For DXE and
SMM phase, the Crypto services can always be compressed. From the table below,
building all the EC services in the OpensslLib has no size impact to the NONE
profile and the MIN_PEI profile. It has ~105 KB impact to compressed DXE/SMM
usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
Uncompressed LZMA Compressed
CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE EC=TRUE Increase
==== =============== ======== ======== ======= ======== ======= ========
IA32 NONE CryptoPei 21536 21568 0 KB
IA32 NONE CryptoDxe 21632 21696 0 KB
IA32 NONE CryptoSmm 22976 23072 0 KB
IA32 MIN_PEI CryptoPei 248992 249120 0 KB
IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520 401034 113 KB
IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517 296022 105 KB
IA32 ALL CryptoPei 423840 598976 189047 293759 104 KB
IA32 ALL CryptoDxe 645280 838144 292955 405277 113 KB
IA32 ALL CryptoSmm 441888 617184 198779 303628 105 KB
X64 NONE CryptoPei 29632 29664 0 KB
X64 NONE CryptoDxe 29792 29792 0 KB
X64 NONE CryptoSmm 31296 31296 0 KB
X64 MIN_PEI CryptoPei 310784 310848 0 KB
X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436 426596 115 KB
X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483 310775 106 KB
X64 ALL CryptoPei 540384 730240 202494 308467 106 KB
X64 ALL CryptoDxe 815392 1027296 316228 431321 115 KB
X64 ALL CryptoSmm 563648 753696 213488 319644 106 KB
NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
entire FV is compressed, the total size impact is typically the size of a
single instance of a compressed CryptoLib. The sizes of the Crypto* modules
in the table above should be a close approximation of the size impact to a
single FV.
Does this match your previous size analysis?
The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
causes the modules that do not use any EC services to grow by ~105KB. Has any
detailed analysis of the final linked images been performed to see where this
additional size is coming from?
Thanks,
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 5:54 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
> I have did some POC that seems existed structured PCD is hard to control binary size,
> Here is the previous discussion for reference.
> https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> https://edk2.groups.io/g/devel/topic/86257810#81814
> https://bugzilla.tianocore.org/show_bug.cgi?id=1446
>
> Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, September 22, 2022 11:56 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> That change to OpensslLib.inf should not have been done either.
>
> Looks like this EC feature needs more evaluation to fit into the
> structured PCD control of the lib sizes.
>
> Mike
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Wednesday, September 21, 2022 7:16 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > Thanks for review.
> >
> > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> as
> > an error
> > 1 file(s) copied.
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > undefined; assuming extern returning int
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > levels of indirection from 'int'
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve' undefined;
> > assuming extern returning int
> >
> > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > 02-L238
> > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> >
> > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas are
> > welcome.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 12:22 AM
> > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Comments embedded below.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > To: devel@edk2.groups.io
> > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > >
> > > This patch is used to add CryptEc library, which is wrapped
> > > over OpenSSL.
> > >
> > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > >
> > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > ---
> > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > 8 files changed, 2186 insertions(+)
> > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > >
> > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > index b253923dd8..d74fc21c1e 100644
> > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > #include <Uefi/UefiBaseType.h>
> > >
> > > +#define CRYPTO_NID_NULL 0x0000
> > > +
> > > +// Key Exchange
> > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > +
> > > ///
> > > /// MD5 digest size in bytes
> > > ///
> > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > OUT VOID *BnRes
> > > );
> > >
> > > +// =====================================================================================
> > > +// Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + );
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient.
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + );
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + );
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + );
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + );
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + );
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + );
> > > +
> > > +// =====================================================================================
> > > +// Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + );
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + );
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + );
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + );
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + );
> > > +
> > > #endif // __BASE_CRYPT_LIB_H__
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > @@ -52,6 +52,8 @@
> > > Pk/CryptTs.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSign.c
> > > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> >
> > The use of the PCD to select the file should not be needed here. The
> > Ec Family and individual service enable/disable fields in the
> > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > disable the Ec services.
> >
> > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > completely as part of this patch series.
> >
> > > Pem/CryptPem.c
> > > Bn/CryptBn.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > index 65ad23fb81..383df2b23c 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > @@ -58,6 +58,7 @@
> > > Pk/CryptTsNull.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSignNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPemNull.c
> > > Rand/CryptRandNull.c
> > > Bn/CryptBnNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > new file mode 100644
> > > index 0000000000..396c819834
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > @@ -0,0 +1,765 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "InternalCryptLib.h"
> > > +#include <openssl/objects.h>
> > > +#include <openssl/bn.h>
> > > +#include <openssl/ec.h>
> > > +
> > > +// =====================================================================================
> > > +// Basic Elliptic Curve Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Return the Nid of certain ECC curve.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval !=-1 On success.
> > > + @retval -1 ECC curve not supported.
> > > +**/
> > > +STATIC
> > > +INT32
> > > +CryptoNidToOpensslNid (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + INT32 Nid;
> > > +
> > > + switch (CryptoNid) {
> > > + case CRYPTO_NID_SECP256R1:
> > > + Nid = NID_X9_62_prime256v1;
> > > + break;
> > > + case CRYPTO_NID_SECP384R1:
> > > + Nid = NID_secp384r1;
> > > + break;
> > > + case CRYPTO_NID_SECP521R1:
> > > + Nid = NID_secp521r1;
> > > + break;
> > > + default:
> > > + return -1;
> > > + }
> > > +
> > > + return Nid;
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + INT32 Nid;
> > > +
> > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > +
> > > + if (Nid < 0) {
> > > + return NULL;
> > > + }
> > > +
> > > + return EC_GROUP_new_by_curve_name (Nid);
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + EC_GROUP_free (EcGroup);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + return EC_POINT_new (EcGroup);
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + if (Clear) {
> > > + EC_POINT_clear_free (EcPoint);
> > > + } else {
> > > + EC_POINT_free (EcPoint);
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > +}
> > > +
> > > +// =====================================================================================
> > > +// Elliptic Curve Diffie Hellman Primitives
> > > +// =====================================================================================
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + INT32 OpenSslNid;
> > > +
> > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > + if (OpenSslNid < 0) {
> > > + return NULL;
> > > + }
> > > +
> > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + CONST EC_GROUP *Group;
> > > + CONST EC_POINT *EcPoint;
> > > + BOOLEAN RetVal;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + UINTN HalfSize;
> > > + INTN XSize;
> > > + INTN YSize;
> > > +
> > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > +
> > > + // Assume RAND_seed was called
> > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (*PublicKeySize < HalfSize * 2) {
> > > + *PublicKeySize = HalfSize * 2;
> > > + return FALSE;
> > > + }
> > > +
> > > + *PublicKeySize = HalfSize * 2;
> > > +
> > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > + if (EcPoint == NULL) {
> > > + return FALSE;
> > > + }
> > > +
> > > + RetVal = FALSE;
> > > + BnX = BN_new ();
> > > + BnY = BN_new ();
> > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + XSize = BN_num_bytes (BnX);
> > > + YSize = BN_num_bytes (BnY);
> > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > + goto fail;
> > > + }
> > > +
> > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > + ZeroMem (PublicKey, *PublicKeySize);
> > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + return RetVal;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + CONST EC_GROUP *Group;
> > > + CONST EC_POINT *EcPoint;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + UINTN HalfSize;
> > > + INTN XSize;
> > > + INTN YSize;
> > > + BOOLEAN RetVal;
> > > +
> > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > + if (*PublicKeySize < HalfSize * 2) {
> > > + *PublicKeySize = HalfSize * 2;
> > > + return FALSE;
> > > + }
> > > +
> > > + *PublicKeySize = HalfSize * 2;
> > > +
> > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > + if (EcPoint == NULL) {
> > > + return FALSE;
> > > + }
> > > +
> > > + RetVal = FALSE;
> > > + BnX = BN_new ();
> > > + BnY = BN_new ();
> > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + XSize = BN_num_bytes (BnX);
> > > + YSize = BN_num_bytes (BnY);
> > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > + goto fail;
> > > + }
> > > +
> > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > +
> > > + if (PublicKey != NULL) {
> > > + ZeroMem (PublicKey, *PublicKeySize);
> > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > + }
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + return RetVal;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If public key is compressed, the PeerPublic will only contain half key (X).
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + EC_KEY *EcKey;
> > > + EC_KEY *PeerEcKey;
> > > + CONST EC_GROUP *Group;
> > > + BOOLEAN RetVal;
> > > + BIGNUM *BnX;
> > > + BIGNUM *BnY;
> > > + EC_POINT *Point;
> > > + INT32 OpenSslNid;
> > > + UINTN HalfSize;
> > > +
> > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (PeerPublicSize > INT_MAX) {
> > > + return FALSE;
> > > + }
> > > +
> > > + EcKey = (EC_KEY *)EcContext;
> > > + Group = EC_KEY_get0_group (EcKey);
> > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > + return FALSE;
> > > + }
> > > +
> > > + if (*KeySize < HalfSize) {
> > > + *KeySize = HalfSize;
> > > + return FALSE;
> > > + }
> > > +
> > > + *KeySize = HalfSize;
> > > +
> > > + RetVal = FALSE;
> > > + Point = NULL;
> > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > + BnY = NULL;
> > > + Point = EC_POINT_new (Group);
> > > + PeerEcKey = NULL;
> > > + if ((BnX == NULL) || (Point == NULL)) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (CompressFlag == NULL) {
> > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > + if (BnY == NULL) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > + } else {
> > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > + goto fail;
> > > + }
> > > + }
> > > +
> > > + // Validate NIST ECDH public key
> > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > + if (PeerEcKey == NULL) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > + goto fail;
> > > + }
> > > +
> > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > + goto fail;
> > > + }
> > > +
> > > + RetVal = TRUE;
> > > +
> > > +fail:
> > > + BN_free (BnX);
> > > + BN_free (BnY);
> > > + EC_POINT_free (Point);
> > > + EC_KEY_free (PeerEcKey);
> > > + return RetVal;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > index ce6a789dfd..4bc3063485 100644
> > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > @@ -59,6 +59,7 @@
> > > Pk/CryptTsNull.c
> > > Pk/CryptRsaPss.c
> > > Pk/CryptRsaPssSignNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPem.c
> > > Bn/CryptBnNull.c
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > index 354f3d80aa..e1a57ef09f 100644
> > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > @@ -49,6 +49,7 @@
> > > Pk/CryptX509Null.c
> > > Pk/CryptAuthenticodeNull.c
> > > Pk/CryptTsNull.c
> > > + Pk/CryptEcNull.c
> > > Pem/CryptPemNull.c
> > > Rand/CryptRandNull.c
> > > Pk/CryptRsaPssNull.c
> > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > new file mode 100644
> > > index 0000000000..d9f1004f6c
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > @@ -0,0 +1,496 @@
> > > +/** @file
> > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > +
> > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseCryptLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +/**
> > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > + and is used for calculation within this group. This object should be freed
> > > + using EcGroupFree() function.
> > > +
> > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > + BaseCryptLib.h).
> > > +
> > > + @retval EcGroup object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcGroupInit (
> > > + IN UINTN CryptoNid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnPrime Group prime number.
> > > + @param[out] BnA A coefficient.
> > > + @param[out] BnB B coefficient..
> > > + @param[in] BnCtx BN context.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetCurve (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *BnPrime,
> > > + OUT VOID *BnA,
> > > + OUT VOID *BnB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get EC group order.
> > > + This function will set the provided Big Number object to the corresponding
> > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > + is properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] BnOrder Group prime number.
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGroupGetOrder (
> > > + IN VOID *EcGroup,
> > > + OUT VOID *BnOrder
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC group object using EcGroupInit().
> > > +
> > > + @param[in] EcGroup EC group object to free.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcGroupFree (
> > > + IN VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Initialize new opaque EC Point object. This object represents an EC point
> > > + within the given EC group (curve).
> > > +
> > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > +
> > > + @retval EC Point object On success.
> > > + @retval NULL On failure.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcPointInit (
> > > + IN CONST VOID *EcGroup
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Free previously allocated EC Point object using EcPointInit().
> > > +
> > > + @param[in] EcPoint EC Point to free.
> > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcPointDeInit (
> > > + IN VOID *EcPoint,
> > > + IN BOOLEAN Clear
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Get EC point affine (x,y) coordinates.
> > > + This function will set the provided Big Number objects to the corresponding
> > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > + are properly initialized.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[out] BnX X coordinate.
> > > + @param[out] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointGetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + OUT VOID *BnX,
> > > + OUT VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point affine (x,y) coordinates.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point object.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] BnY Y coordinate.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetAffineCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN CONST VOID *BnY,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPointA EC Point.
> > > + @param[in] EcPointB EC Point.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointAdd (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > + be properly initialized.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnPScalar P Scalar.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointMul (
> > > + IN CONST VOID *EcGroup,
> > > + OUT VOID *EcPointResult,
> > > + IN CONST VOID *EcPoint,
> > > + IN CONST VOID *BnPScalar,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Calculate the inverse of the supplied EC point.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in,out] EcPoint EC point to invert.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointInvert (
> > > + IN CONST VOID *EcGroup,
> > > + IN OUT VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is on EC curve.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On curve.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsOnCurve (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if the supplied point is at infinity.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC point to check.
> > > +
> > > + @retval TRUE At infinity.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointIsAtInfinity (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPoint
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Check if EC points are equal.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPointA EC point A.
> > > + @param[in] EcPointB EC point B.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE A == B.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointEqual (
> > > + IN CONST VOID *EcGroup,
> > > + IN CONST VOID *EcPointA,
> > > + IN CONST VOID *EcPointB,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Set EC point compressed coordinates. Points can be described in terms of
> > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > + such that the point is on the curve there will only ever be two possible
> > > + values for y. Therefore, a point can be set using this function where BnX is
> > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > + possible values for y should be used.
> > > +
> > > + @param[in] EcGroup EC group object.
> > > + @param[in] EcPoint EC Point.
> > > + @param[in] BnX X coordinate.
> > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > +
> > > + @retval TRUE On success.
> > > + @retval FALSE Otherwise.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcPointSetCompressedCoordinates (
> > > + IN CONST VOID *EcGroup,
> > > + IN VOID *EcPoint,
> > > + IN CONST VOID *BnX,
> > > + IN UINT8 YBit,
> > > + IN VOID *BnCtx
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > + with the NID.
> > > +
> > > + @param[in] Nid cipher NID
> > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > + If the allocations fails, EcNewByNid() returns NULL.
> > > +**/
> > > +VOID *
> > > +EFIAPI
> > > +EcNewByNid (
> > > + IN UINTN Nid
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return NULL;
> > > +}
> > > +
> > > +/**
> > > + Release the specified EC context.
> > > +
> > > + @param[in] EcContext Pointer to the EC context to be released.
> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +EcFree (
> > > + IN VOID *EcContext
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > +}
> > > +
> > > +/**
> > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > + function was properly called before.
> > > + The Ec context should be correctly initialized by EcNewByNid.
> > > + This function generates random secret, and computes the public key (X, Y), which is
> > > + returned via parameter Public, PublicSize.
> > > + X is the first half of Public with size being PublicSize / 2,
> > > + Y is the second half of Public with size being PublicSize / 2.
> > > + EC context is updated accordingly.
> > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PublicSize is NULL, then return FALSE.
> > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC public X,Y generation succeeded.
> > > + @retval FALSE EC public X,Y generation failed.
> > > + @retval FALSE PublicKeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGenerateKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Gets the public key component from the established EC context.
> > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > + generate key pair from EcGenerateKey().
> > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to EC context being set.
> > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > + On output, the size of data returned in Public buffer in bytes.
> > > + @retval TRUE EC key component was retrieved successfully.
> > > + @retval FALSE Invalid EC key component.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcGetPubKey (
> > > + IN OUT VOID *EcContext,
> > > + OUT UINT8 *PublicKey,
> > > + IN OUT UINTN *PublicKeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Computes exchanged common key.
> > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > + based on its own context including value of curve parameter and random secret.
> > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > + If EcContext is NULL, then return FALSE.
> > > + If PeerPublic is NULL, then return FALSE.
> > > + If PeerPublicSize is 0, then return FALSE.
> > > + If Key is NULL, then return FALSE.
> > > + If KeySize is not large enough, then return FALSE.
> > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > + @param[in, out] EcContext Pointer to the EC context.
> > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > + On output, the size of data returned in Key buffer in bytes.
> > > + @retval TRUE EC exchanged key generation succeeded.
> > > + @retval FALSE EC exchanged key generation failed.
> > > + @retval FALSE KeySize is not large enough.
> > > +**/
> > > +BOOLEAN
> > > +EFIAPI
> > > +EcDhComputeKey (
> > > + IN OUT VOID *EcContext,
> > > + IN CONST UINT8 *PeerPublic,
> > > + IN UINTN PeerPublicSize,
> > > + IN CONST INT32 *CompressFlag,
> > > + OUT UINT8 *Key,
> > > + IN OUT UINTN *KeySize
> > > + )
> > > +{
> > > + ASSERT (FALSE);
> > > + return FALSE;
> > > +}
> > > --
> > > 2.31.1.windows.1
> > >
> > >
> > >
> > >
> > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-23 3:01 ` yi1 li
@ 2022-09-23 5:25 ` Michael D Kinney
2022-09-23 7:08 ` yi1 li
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-23 5:25 UTC (permalink / raw)
To: Li, Yi1, devel@edk2.groups.io, Chen, Christine, Feng, Bob C,
Kinney, Michael D
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Hi Yi,
I agree there are some complex interactions in the opensll sources.
Since you are defining a family for EC, can we use the EC Family != 0 instead of
PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
I want to make sure developers do not run into strange build failures if
they do not keep the 2 different PCDs aligned. I prefer a single PCD
setting to enable use of EC services.
I also noticed that the use of a PCD expression in an INF to select source
files does not work if the PCD value is specified with the --pcd flag on
the build command line. This looks like a significant bug with the PCD
expression in an INF file. This also needs to be fixed.
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 8:02 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
>
> 1. Yes, it matches.
> By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.
>
> 2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509 ...
>
> If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> size,
> This an example from x509/x_pubkey.c , other modules is similar:
> #ifndef OPENSSL_NO_EC
> EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
> {
> EVP_PKEY *pkey;
> EC_KEY *key = NULL;
> //.... call EC functions
> }
> #endif
>
> If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
> Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but not another.
> This an example from ec/ec_local.h , other error is similar:
>
> #ifndef OPENSSL_NO_EC
> typedef struct ec_group_st EC_GROUP;
> typedef struct ec_point_st EC_POINT;
> #endif
>
> // but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
> int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> EC_POINT *, const BIGNUM *x,
> const BIGNUM *y,
> const BIGNUM *z, BN_CTX *);
>
> To avoid this annoying openssl error, we introduced conditional EC.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 6:47 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Yi,
>
> I agree EC is an important feature.
>
> I did some analysis of the size impact to the CryptoPkg modules on current trunk
> with EC on and off. Uncompressed size is important for PEI Phase. For DXE and
> SMM phase, the Crypto services can always be compressed. From the table below,
> building all the EC services in the OpensslLib has no size impact to the NONE
> profile and the MIN_PEI profile. It has ~105 KB impact to compressed DXE/SMM
> usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
>
> Uncompressed LZMA Compressed
> CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE EC=TRUE Increase
> ==== =============== ======== ======== ======= ======== ======= ========
> IA32 NONE CryptoPei 21536 21568 0 KB
> IA32 NONE CryptoDxe 21632 21696 0 KB
> IA32 NONE CryptoSmm 22976 23072 0 KB
> IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520 401034 113 KB
> IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517 296022 105 KB
> IA32 ALL CryptoPei 423840 598976 189047 293759 104 KB
> IA32 ALL CryptoDxe 645280 838144 292955 405277 113 KB
> IA32 ALL CryptoSmm 441888 617184 198779 303628 105 KB
> X64 NONE CryptoPei 29632 29664 0 KB
> X64 NONE CryptoDxe 29792 29792 0 KB
> X64 NONE CryptoSmm 31296 31296 0 KB
> X64 MIN_PEI CryptoPei 310784 310848 0 KB
> X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436 426596 115 KB
> X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483 310775 106 KB
> X64 ALL CryptoPei 540384 730240 202494 308467 106 KB
> X64 ALL CryptoDxe 815392 1027296 316228 431321 115 KB
> X64 ALL CryptoSmm 563648 753696 213488 319644 106 KB
>
> NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
> entire FV is compressed, the total size impact is typically the size of a
> single instance of a compressed CryptoLib. The sizes of the Crypto* modules
> in the table above should be a close approximation of the size impact to a
> single FV.
>
> Does this match your previous size analysis?
>
> The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
> causes the modules that do not use any EC services to grow by ~105KB. Has any
> detailed analysis of the final linked images been performed to see where this
> additional size is coming from?
>
> Thanks,
>
> Mike
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 5:54 AM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > I have did some POC that seems existed structured PCD is hard to control binary size,
> > Here is the previous discussion for reference.
> > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > https://edk2.groups.io/g/devel/topic/86257810#81814
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> >
> > Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> > Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 11:56 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > That change to OpensslLib.inf should not have been done either.
> >
> > Looks like this EC feature needs more evaluation to fit into the
> > structured PCD control of the lib sizes.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > Thanks for review.
> > >
> > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> > >
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> > as
> > > an error
> > > 1 file(s) copied.
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > undefined; assuming extern returning int
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > > levels of indirection from 'int'
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve'
> undefined;
> > > assuming extern returning int
> > >
> > > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > 02-L238
> > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> > >
> > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas
> are
> > > welcome.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 12:22 AM
> > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Comments embedded below.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > >
> > > > This patch is used to add CryptEc library, which is wrapped
> > > > over OpenSSL.
> > > >
> > > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > > >
> > > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > > ---
> > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > 8 files changed, 2186 insertions(+)
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index b253923dd8..d74fc21c1e 100644
> > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > #include <Uefi/UefiBaseType.h>
> > > >
> > > > +#define CRYPTO_NID_NULL 0x0000
> > > > +
> > > > +// Key Exchange
> > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > +
> > > > ///
> > > > /// MD5 digest size in bytes
> > > > ///
> > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > OUT VOID *BnRes
> > > > );
> > > >
> > > > +// =====================================================================================
> > > > +// Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient.
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + );
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + );
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + );
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +// =====================================================================================
> > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + );
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + );
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + );
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + );
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + );
> > > > +
> > > > #endif // __BASE_CRYPT_LIB_H__
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > @@ -52,6 +52,8 @@
> > > > Pk/CryptTs.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSign.c
> > > > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > >
> > > The use of the PCD to select the file should not be needed here. The
> > > Ec Family and individual service enable/disable fields in the
> > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > > disable the Ec services.
> > >
> > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > > completely as part of this patch series.
> > >
> > > > Pem/CryptPem.c
> > > > Bn/CryptBn.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > index 65ad23fb81..383df2b23c 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > @@ -58,6 +58,7 @@
> > > > Pk/CryptTsNull.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSignNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPemNull.c
> > > > Rand/CryptRandNull.c
> > > > Bn/CryptBnNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > new file mode 100644
> > > > index 0000000000..396c819834
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > @@ -0,0 +1,765 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include "InternalCryptLib.h"
> > > > +#include <openssl/objects.h>
> > > > +#include <openssl/bn.h>
> > > > +#include <openssl/ec.h>
> > > > +
> > > > +// =====================================================================================
> > > > +// Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Return the Nid of certain ECC curve.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval !=-1 On success.
> > > > + @retval -1 ECC curve not supported.
> > > > +**/
> > > > +STATIC
> > > > +INT32
> > > > +CryptoNidToOpensslNid (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + INT32 Nid;
> > > > +
> > > > + switch (CryptoNid) {
> > > > + case CRYPTO_NID_SECP256R1:
> > > > + Nid = NID_X9_62_prime256v1;
> > > > + break;
> > > > + case CRYPTO_NID_SECP384R1:
> > > > + Nid = NID_secp384r1;
> > > > + break;
> > > > + case CRYPTO_NID_SECP521R1:
> > > > + Nid = NID_secp521r1;
> > > > + break;
> > > > + default:
> > > > + return -1;
> > > > + }
> > > > +
> > > > + return Nid;
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + INT32 Nid;
> > > > +
> > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > +
> > > > + if (Nid < 0) {
> > > > + return NULL;
> > > > + }
> > > > +
> > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + EC_GROUP_free (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + return EC_POINT_new (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + if (Clear) {
> > > > + EC_POINT_clear_free (EcPoint);
> > > > + } else {
> > > > + EC_POINT_free (EcPoint);
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > +}
> > > > +
> > > > +// =====================================================================================
> > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + INT32 OpenSslNid;
> > > > +
> > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > + if (OpenSslNid < 0) {
> > > > + return NULL;
> > > > + }
> > > > +
> > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + CONST EC_POINT *EcPoint;
> > > > + BOOLEAN RetVal;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + UINTN HalfSize;
> > > > + INTN XSize;
> > > > + INTN YSize;
> > > > +
> > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +
> > > > + // Assume RAND_seed was called
> > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > + *PublicKeySize = HalfSize * 2;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *PublicKeySize = HalfSize * 2;
> > > > +
> > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > + if (EcPoint == NULL) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + RetVal = FALSE;
> > > > + BnX = BN_new ();
> > > > + BnY = BN_new ();
> > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + XSize = BN_num_bytes (BnX);
> > > > + YSize = BN_num_bytes (BnY);
> > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + CONST EC_POINT *EcPoint;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + UINTN HalfSize;
> > > > + INTN XSize;
> > > > + INTN YSize;
> > > > + BOOLEAN RetVal;
> > > > +
> > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > + *PublicKeySize = HalfSize * 2;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *PublicKeySize = HalfSize * 2;
> > > > +
> > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > + if (EcPoint == NULL) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + RetVal = FALSE;
> > > > + BnX = BN_new ();
> > > > + BnY = BN_new ();
> > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + XSize = BN_num_bytes (BnX);
> > > > + YSize = BN_num_bytes (BnY);
> > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > + if (PublicKey != NULL) {
> > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > + }
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If public key is compressed, the PeerPublic will only contain half key (X).
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + EC_KEY *PeerEcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + BOOLEAN RetVal;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + EC_POINT *Point;
> > > > + INT32 OpenSslNid;
> > > > + UINTN HalfSize;
> > > > +
> > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (PeerPublicSize > INT_MAX) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (*KeySize < HalfSize) {
> > > > + *KeySize = HalfSize;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *KeySize = HalfSize;
> > > > +
> > > > + RetVal = FALSE;
> > > > + Point = NULL;
> > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > + BnY = NULL;
> > > > + Point = EC_POINT_new (Group);
> > > > + PeerEcKey = NULL;
> > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (CompressFlag == NULL) {
> > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > + if (BnY == NULL) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > + } else {
> > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > + }
> > > > +
> > > > + // Validate NIST ECDH public key
> > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > + if (PeerEcKey == NULL) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + EC_POINT_free (Point);
> > > > + EC_KEY_free (PeerEcKey);
> > > > + return RetVal;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index ce6a789dfd..4bc3063485 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > @@ -59,6 +59,7 @@
> > > > Pk/CryptTsNull.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSignNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPem.c
> > > > Bn/CryptBnNull.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > index 354f3d80aa..e1a57ef09f 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > @@ -49,6 +49,7 @@
> > > > Pk/CryptX509Null.c
> > > > Pk/CryptAuthenticodeNull.c
> > > > Pk/CryptTsNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPemNull.c
> > > > Rand/CryptRandNull.c
> > > > Pk/CryptRsaPssNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > --
> > > > 2.31.1.windows.1
> > > >
> > > >
> > > >
> > > >
> > > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-23 5:25 ` Michael D Kinney
@ 2022-09-23 7:08 ` yi1 li
2022-09-23 22:40 ` Yao, Jiewen
0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-23 7:08 UTC (permalink / raw)
To: Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C
Cc: Yao, Jiewen, Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
Hi Mike,
I did make some attempts with it, but it doesn't work, two troubles here:
Bob and Yuwei, please point out if I'm wrong:
1. Using member of structure PCD in INF isn’t supported by Basetools currently,
At least it cannot be used as FeatureFlag Expression.
2. As far as I know, structure PCD actually is a const array in code,
I afraid it will not work fine with precompile but we do have this need:
#if !FixedPcdGetBool (PcdOpensslEcEnabled)
# ifndef OPENSSL_NO_EC
# define OPENSSL_NO_EC
# endif
#endif
This is really caused by the bad structure of openssl,
maybe we use more detailed comments to remind developers to sync the two PCDs?
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Friday, September 23, 2022 1:25 PM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Yi,
I agree there are some complex interactions in the opensll sources.
Since you are defining a family for EC, can we use the EC Family != 0 instead of
PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
I want to make sure developers do not run into strange build failures if
they do not keep the 2 different PCDs aligned. I prefer a single PCD
setting to enable use of EC services.
I also noticed that the use of a PCD expression in an INF to select source
files does not work if the PCD value is specified with the --pcd flag on
the build command line. This looks like a significant bug with the PCD
expression in an INF file. This also needs to be fixed.
Mike
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Thursday, September 22, 2022 8:02 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
>
> 1. Yes, it matches.
> By Intel side, 100+kb(20%+) FV size increase will be a big concern, please refer to another internal email.
>
> 2. Additional size is coming from modules may consumed EC APIs, eg. TLS PEM X509 ...
>
> If we added EC source to OpensslLib.inf and disabled macro OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> size,
> This an example from x509/x_pubkey.c , other modules is similar:
> #ifndef OPENSSL_NO_EC
> EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
> {
> EVP_PKEY *pkey;
> EC_KEY *key = NULL;
> //.... call EC functions
> }
> #endif
>
> If we added EC source to OpensslLib.inf and enable macro OPENSSL_NO_EC, EC module will throw build error,
> Since some EC internal APIs or structs have been disabled by OPENSSL_NO_EC but not another.
> This an example from ec/ec_local.h , other error is similar:
>
> #ifndef OPENSSL_NO_EC
> typedef struct ec_group_st EC_GROUP;
> typedef struct ec_point_st EC_POINT;
> #endif
>
> // but this function not been enclosed by OPENSSL_NO_EC, and will throw build error
> int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> EC_POINT *, const BIGNUM *x,
> const BIGNUM *y,
> const BIGNUM *z, BN_CTX *);
>
> To avoid this annoying openssl error, we introduced conditional EC.
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 6:47 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Yi,
>
> I agree EC is an important feature.
>
> I did some analysis of the size impact to the CryptoPkg modules on current trunk
> with EC on and off. Uncompressed size is important for PEI Phase. For DXE and
> SMM phase, the Crypto services can always be compressed. From the table below,
> building all the EC services in the OpensslLib has no size impact to the NONE
> profile and the MIN_PEI profile. It has ~105 KB impact to compressed DXE/SMM
> usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
>
> Uncompressed LZMA Compressed
> CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE EC=TRUE Increase
> ==== =============== ======== ======== ======= ======== ======= ========
> IA32 NONE CryptoPei 21536 21568 0 KB
> IA32 NONE CryptoDxe 21632 21696 0 KB
> IA32 NONE CryptoSmm 22976 23072 0 KB
> IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520 401034 113 KB
> IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517 296022 105 KB
> IA32 ALL CryptoPei 423840 598976 189047 293759 104 KB
> IA32 ALL CryptoDxe 645280 838144 292955 405277 113 KB
> IA32 ALL CryptoSmm 441888 617184 198779 303628 105 KB
> X64 NONE CryptoPei 29632 29664 0 KB
> X64 NONE CryptoDxe 29792 29792 0 KB
> X64 NONE CryptoSmm 31296 31296 0 KB
> X64 MIN_PEI CryptoPei 310784 310848 0 KB
> X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436 426596 115 KB
> X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483 310775 106 KB
> X64 ALL CryptoPei 540384 730240 202494 308467 106 KB
> X64 ALL CryptoDxe 815392 1027296 316228 431321 115 KB
> X64 ALL CryptoSmm 563648 753696 213488 319644 106 KB
>
> NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if the
> entire FV is compressed, the total size impact is typically the size of a
> single instance of a compressed CryptoLib. The sizes of the Crypto* modules
> in the table above should be a close approximation of the size impact to a
> single FV.
>
> Does this match your previous size analysis?
>
> The critical issue to evaluate here is why adding the EC sources to OpensllLib.inf
> causes the modules that do not use any EC services to grow by ~105KB. Has any
> detailed analysis of the final linked images been performed to see where this
> additional size is coming from?
>
> Thanks,
>
> Mike
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 5:54 AM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> > I have did some POC that seems existed structured PCD is hard to control binary size,
> > Here is the previous discussion for reference.
> > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > https://edk2.groups.io/g/devel/topic/86257810#81814
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> >
> > Anyway EC is an important feature which consumed by vary modern security features such WPA3 , SPDM, TLS1.3 etc.
> > Hope it can be added to edk2, and I am glad to take the code and test work if there are other ways to control the size.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Thursday, September 22, 2022 11:56 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > That change to OpensslLib.inf should not have been done either.
> >
> > Looks like this EC feature needs more evaluation to fit into the
> > structured PCD control of the lib sizes.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > Thanks for review.
> > >
> > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c will also be compiled and throw build error:
> > >
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): error C2220: the following warning is treated
> > as
> > > an error
> > > 1 file(s) copied.
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > undefined; assuming extern returning int
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(77): warning C4047: 'return': 'void *' differs in
> > > levels of indirection from 'int'
> > > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.c(105): warning C4013: 'EC_GROUP_get_curve'
> undefined;
> > > assuming extern returning int
> > >
> > > I think the root cause is that we have enabled conditional ec in OpensslLib.inf before by PcdOpensslEcEnabled,
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a674499342f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > 02-L238
> > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > This will save 200+kb memory on platforms which use dxe driver but do not need ec feature.
> > >
> > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not sure if there is any other way, other better ideas
> are
> > > welcome.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 12:22 AM
> > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Comments embedded below.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of yi1 li
> > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > >
> > > > This patch is used to add CryptEc library, which is wrapped
> > > > over OpenSSL.
> > > >
> > > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > > >
> > > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > > ---
> > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765 ++++++++++++++++++
> > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > 8 files changed, 2186 insertions(+)
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index b253923dd8..d74fc21c1e 100644
> > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > #include <Uefi/UefiBaseType.h>
> > > >
> > > > +#define CRYPTO_NID_NULL 0x0000
> > > > +
> > > > +// Key Exchange
> > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > +
> > > > ///
> > > > /// MD5 digest size in bytes
> > > > ///
> > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > OUT VOID *BnRes
> > > > );
> > > >
> > > > +// =====================================================================================
> > > > +// Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient.
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + );
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + );
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + );
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + );
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + );
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + );
> > > > +
> > > > +// =====================================================================================
> > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + );
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + );
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + );
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + );
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + );
> > > > +
> > > > #endif // __BASE_CRYPT_LIB_H__
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > @@ -52,6 +52,8 @@
> > > > Pk/CryptTs.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSign.c
> > > > + Pk/CryptEcNull.c |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > + Pk/CryptEc.c |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > >
> > > The use of the PCD to select the file should not be needed here. The
> > > Ec Family and individual service enable/disable fields in the
> > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is needed to
> > > disable the Ec services.
> > >
> > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should be removed
> > > completely as part of this patch series.
> > >
> > > > Pem/CryptPem.c
> > > > Bn/CryptBn.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > index 65ad23fb81..383df2b23c 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > @@ -58,6 +58,7 @@
> > > > Pk/CryptTsNull.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSignNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPemNull.c
> > > > Rand/CryptRandNull.c
> > > > Bn/CryptBnNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > new file mode 100644
> > > > index 0000000000..396c819834
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > @@ -0,0 +1,765 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include "InternalCryptLib.h"
> > > > +#include <openssl/objects.h>
> > > > +#include <openssl/bn.h>
> > > > +#include <openssl/ec.h>
> > > > +
> > > > +// =====================================================================================
> > > > +// Basic Elliptic Curve Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Return the Nid of certain ECC curve.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval !=-1 On success.
> > > > + @retval -1 ECC curve not supported.
> > > > +**/
> > > > +STATIC
> > > > +INT32
> > > > +CryptoNidToOpensslNid (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + INT32 Nid;
> > > > +
> > > > + switch (CryptoNid) {
> > > > + case CRYPTO_NID_SECP256R1:
> > > > + Nid = NID_X9_62_prime256v1;
> > > > + break;
> > > > + case CRYPTO_NID_SECP384R1:
> > > > + Nid = NID_secp384r1;
> > > > + break;
> > > > + case CRYPTO_NID_SECP521R1:
> > > > + Nid = NID_secp521r1;
> > > > + break;
> > > > + default:
> > > > + return -1;
> > > > + }
> > > > +
> > > > + return Nid;
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + INT32 Nid;
> > > > +
> > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > +
> > > > + if (Nid < 0) {
> > > > + return NULL;
> > > > + }
> > > > +
> > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + EC_GROUP_free (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + return EC_POINT_new (EcGroup);
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + if (Clear) {
> > > > + EC_POINT_clear_free (EcPoint);
> > > > + } else {
> > > > + EC_POINT_free (EcPoint);
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > +}
> > > > +
> > > > +// =====================================================================================
> > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > +// =====================================================================================
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + INT32 OpenSslNid;
> > > > +
> > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > + if (OpenSslNid < 0) {
> > > > + return NULL;
> > > > + }
> > > > +
> > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + CONST EC_POINT *EcPoint;
> > > > + BOOLEAN RetVal;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + UINTN HalfSize;
> > > > + INTN XSize;
> > > > + INTN YSize;
> > > > +
> > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > +
> > > > + // Assume RAND_seed was called
> > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > + *PublicKeySize = HalfSize * 2;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *PublicKeySize = HalfSize * 2;
> > > > +
> > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > + if (EcPoint == NULL) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + RetVal = FALSE;
> > > > + BnX = BN_new ();
> > > > + BnY = BN_new ();
> > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + XSize = BN_num_bytes (BnX);
> > > > + YSize = BN_num_bytes (BnY);
> > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + CONST EC_POINT *EcPoint;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + UINTN HalfSize;
> > > > + INTN XSize;
> > > > + INTN YSize;
> > > > + BOOLEAN RetVal;
> > > > +
> > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > + *PublicKeySize = HalfSize * 2;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *PublicKeySize = HalfSize * 2;
> > > > +
> > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > + if (EcPoint == NULL) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + RetVal = FALSE;
> > > > + BnX = BN_new ();
> > > > + BnY = BN_new ();
> > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + XSize = BN_num_bytes (BnX);
> > > > + YSize = BN_num_bytes (BnY);
> > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > +
> > > > + if (PublicKey != NULL) {
> > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > + }
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + return RetVal;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If public key is compressed, the PeerPublic will only contain half key (X).
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + EC_KEY *EcKey;
> > > > + EC_KEY *PeerEcKey;
> > > > + CONST EC_GROUP *Group;
> > > > + BOOLEAN RetVal;
> > > > + BIGNUM *BnX;
> > > > + BIGNUM *BnY;
> > > > + EC_POINT *Point;
> > > > + INT32 OpenSslNid;
> > > > + UINTN HalfSize;
> > > > +
> > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (PeerPublicSize > INT_MAX) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + EcKey = (EC_KEY *)EcContext;
> > > > + Group = EC_KEY_get0_group (EcKey);
> > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + if (*KeySize < HalfSize) {
> > > > + *KeySize = HalfSize;
> > > > + return FALSE;
> > > > + }
> > > > +
> > > > + *KeySize = HalfSize;
> > > > +
> > > > + RetVal = FALSE;
> > > > + Point = NULL;
> > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > + BnY = NULL;
> > > > + Point = EC_POINT_new (Group);
> > > > + PeerEcKey = NULL;
> > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (CompressFlag == NULL) {
> > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > + if (BnY == NULL) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > + } else {
> > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) {
> > > > + goto fail;
> > > > + }
> > > > + }
> > > > +
> > > > + // Validate NIST ECDH public key
> > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > + if (PeerEcKey == NULL) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > + goto fail;
> > > > + }
> > > > +
> > > > + RetVal = TRUE;
> > > > +
> > > > +fail:
> > > > + BN_free (BnX);
> > > > + BN_free (BnY);
> > > > + EC_POINT_free (Point);
> > > > + EC_KEY_free (PeerEcKey);
> > > > + return RetVal;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index ce6a789dfd..4bc3063485 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > @@ -59,6 +59,7 @@
> > > > Pk/CryptTsNull.c
> > > > Pk/CryptRsaPss.c
> > > > Pk/CryptRsaPssSignNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPem.c
> > > > Bn/CryptBnNull.c
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > index 354f3d80aa..e1a57ef09f 100644
> > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > @@ -49,6 +49,7 @@
> > > > Pk/CryptX509Null.c
> > > > Pk/CryptAuthenticodeNull.c
> > > > Pk/CryptTsNull.c
> > > > + Pk/CryptEcNull.c
> > > > Pem/CryptPemNull.c
> > > > Rand/CryptRandNull.c
> > > > Pk/CryptRsaPssNull.c
> > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > new file mode 100644
> > > > index 0000000000..d9f1004f6c
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > @@ -0,0 +1,496 @@
> > > > +/** @file
> > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > +
> > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Library/BaseCryptLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +/**
> > > > + Initialize new opaque EcGroup object. This object represents an EC curve and
> > > > + and is used for calculation within this group. This object should be freed
> > > > + using EcGroupFree() function.
> > > > +
> > > > + @param[in] CryptoNid Identifying number for the ECC curve (Defined in
> > > > + BaseCryptLib.h).
> > > > +
> > > > + @retval EcGroup object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcGroupInit (
> > > > + IN UINTN CryptoNid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnPrime Group prime number.
> > > > + @param[out] BnA A coefficient.
> > > > + @param[out] BnB B coefficient..
> > > > + @param[in] BnCtx BN context.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *BnPrime,
> > > > + OUT VOID *BnA,
> > > > + OUT VOID *BnB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC group order.
> > > > + This function will set the provided Big Number object to the corresponding
> > > > + value. The caller needs to make sure that the "out" BigNumber parameter
> > > > + is properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] BnOrder Group prime number.
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGroupGetOrder (
> > > > + IN VOID *EcGroup,
> > > > + OUT VOID *BnOrder
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC group object using EcGroupInit().
> > > > +
> > > > + @param[in] EcGroup EC group object to free.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcGroupFree (
> > > > + IN VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Initialize new opaque EC Point object. This object represents an EC point
> > > > + within the given EC group (curve).
> > > > +
> > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > +
> > > > + @retval EC Point object On success.
> > > > + @retval NULL On failure.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcPointInit (
> > > > + IN CONST VOID *EcGroup
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Free previously allocated EC Point object using EcPointInit().
> > > > +
> > > > + @param[in] EcPoint EC Point to free.
> > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcPointDeInit (
> > > > + IN VOID *EcPoint,
> > > > + IN BOOLEAN Clear
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Get EC point affine (x,y) coordinates.
> > > > + This function will set the provided Big Number objects to the corresponding
> > > > + values. The caller needs to make sure all the "out" BigNumber parameters
> > > > + are properly initialized.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[out] BnX X coordinate.
> > > > + @param[out] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointGetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + OUT VOID *BnX,
> > > > + OUT VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point affine (x,y) coordinates.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point object.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] BnY Y coordinate.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetAffineCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN CONST VOID *BnY,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPointA EC Point.
> > > > + @param[in] EcPointB EC Point.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointAdd (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[out] EcPointResult EC point to hold the result. The point should
> > > > + be properly initialized.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnPScalar P Scalar.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointMul (
> > > > + IN CONST VOID *EcGroup,
> > > > + OUT VOID *EcPointResult,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN CONST VOID *BnPScalar,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Calculate the inverse of the supplied EC point.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in,out] EcPoint EC point to invert.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointInvert (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN OUT VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is on EC curve.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On curve.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsOnCurve (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the supplied point is at infinity.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC point to check.
> > > > +
> > > > + @retval TRUE At infinity.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointIsAtInfinity (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPoint
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if EC points are equal.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPointA EC point A.
> > > > + @param[in] EcPointB EC point B.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE A == B.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointEqual (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN CONST VOID *EcPointA,
> > > > + IN CONST VOID *EcPointB,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Set EC point compressed coordinates. Points can be described in terms of
> > > > + their compressed coordinates. For a point (x, y), for any given value for x
> > > > + such that the point is on the curve there will only ever be two possible
> > > > + values for y. Therefore, a point can be set using this function where BnX is
> > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the two
> > > > + possible values for y should be used.
> > > > +
> > > > + @param[in] EcGroup EC group object.
> > > > + @param[in] EcPoint EC Point.
> > > > + @param[in] BnX X coordinate.
> > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > + @param[in] BnCtx BN context, created with BigNumNewContext().
> > > > +
> > > > + @retval TRUE On success.
> > > > + @retval FALSE Otherwise.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcPointSetCompressedCoordinates (
> > > > + IN CONST VOID *EcGroup,
> > > > + IN VOID *EcPoint,
> > > > + IN CONST VOID *BnX,
> > > > + IN UINT8 YBit,
> > > > + IN VOID *BnCtx
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Allocates and Initializes one Elliptic Curve Context for subsequent use
> > > > + with the NID.
> > > > +
> > > > + @param[in] Nid cipher NID
> > > > + @return Pointer to the Elliptic Curve Context that has been initialized.
> > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > +**/
> > > > +VOID *
> > > > +EFIAPI
> > > > +EcNewByNid (
> > > > + IN UINTN Nid
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > + Release the specified EC context.
> > > > +
> > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > +**/
> > > > +VOID
> > > > +EFIAPI
> > > > +EcFree (
> > > > + IN VOID *EcContext
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > +}
> > > > +
> > > > +/**
> > > > + Generates EC key and returns EC public key (X, Y), Please note, this function uses
> > > > + pseudo random number generator. The caller must make sure RandomSeed()
> > > > + function was properly called before.
> > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > + This function generates random secret, and computes the public key (X, Y), which is
> > > > + returned via parameter Public, PublicSize.
> > > > + X is the first half of Public with size being PublicSize / 2,
> > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > + EC context is updated accordingly.
> > > > + If the Public buffer is too small to hold the public X, Y, FALSE is returned and
> > > > + PublicSize is set to the required buffer size to obtain the public X, Y.
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PublicSize is NULL, then return FALSE.
> > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > + @retval FALSE EC public X,Y generation failed.
> > > > + @retval FALSE PublicKeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGenerateKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Gets the public key component from the established EC context.
> > > > + The Ec context should be correctly initialized by EcNewByNid, and successfully
> > > > + generate key pair from EcGenerateKey().
> > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > + @param[out] PublicKey Pointer to t buffer to receive generated public X,Y.
> > > > + @param[in, out] PublicKeySize On input, the size of Public buffer in bytes.
> > > > + On output, the size of data returned in Public buffer in bytes.
> > > > + @retval TRUE EC key component was retrieved successfully.
> > > > + @retval FALSE Invalid EC key component.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcGetPubKey (
> > > > + IN OUT VOID *EcContext,
> > > > + OUT UINT8 *PublicKey,
> > > > + IN OUT UINTN *PublicKeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Computes exchanged common key.
> > > > + Given peer's public key (X, Y), this function computes the exchanged common key,
> > > > + based on its own context including value of curve parameter and random secret.
> > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > + Y is the second half of PeerPublic with size being PeerPublicSize / 2.
> > > > + If EcContext is NULL, then return FALSE.
> > > > + If PeerPublic is NULL, then return FALSE.
> > > > + If PeerPublicSize is 0, then return FALSE.
> > > > + If Key is NULL, then return FALSE.
> > > > + If KeySize is not large enough, then return FALSE.
> > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
> > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
> > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
> > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > + @param[in] CompressFlag Flag of PeerPublic is compressed or not.
> > > > + @param[out] Key Pointer to the buffer to receive generated key.
> > > > + @param[in, out] KeySize On input, the size of Key buffer in bytes.
> > > > + On output, the size of data returned in Key buffer in bytes.
> > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > + @retval FALSE EC exchanged key generation failed.
> > > > + @retval FALSE KeySize is not large enough.
> > > > +**/
> > > > +BOOLEAN
> > > > +EFIAPI
> > > > +EcDhComputeKey (
> > > > + IN OUT VOID *EcContext,
> > > > + IN CONST UINT8 *PeerPublic,
> > > > + IN UINTN PeerPublicSize,
> > > > + IN CONST INT32 *CompressFlag,
> > > > + OUT UINT8 *Key,
> > > > + IN OUT UINTN *KeySize
> > > > + )
> > > > +{
> > > > + ASSERT (FALSE);
> > > > + return FALSE;
> > > > +}
> > > > --
> > > > 2.31.1.windows.1
> > > >
> > > >
> > > >
> > > >
> > > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-23 7:08 ` yi1 li
@ 2022-09-23 22:40 ` Yao, Jiewen
2022-09-24 2:19 ` Michael D Kinney
0 siblings, 1 reply; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-23 22:40 UTC (permalink / raw)
To: Li, Yi1, Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
Hi Mike
This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do enhancement for PCD related stuff later?
Or if you have any other idea, please let us know.
Thank you
Yao Jiewen
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Friday, September 23, 2022 3:09 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob
> C <bob.c.feng@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike,
>
> I did make some attempts with it, but it doesn't work, two troubles here:
>
> Bob and Yuwei, please point out if I'm wrong:
> 1. Using member of structure PCD in INF isn’t supported by Basetools
> currently,
> At least it cannot be used as FeatureFlag Expression.
>
> 2. As far as I know, structure PCD actually is a const array in code,
> I afraid it will not work fine with precompile but we do have this need:
> #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> # ifndef OPENSSL_NO_EC
> # define OPENSSL_NO_EC
> # endif
> #endif
>
> This is really caused by the bad structure of openssl,
> maybe we use more detailed comments to remind developers to sync the
> two PCDs?
>
> Thanks,
> Yi
>
> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Friday, September 23, 2022 1:25 PM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine
> <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Yi,
>
> I agree there are some complex interactions in the opensll sources.
>
> Since you are defining a family for EC, can we use the EC Family != 0 instead
> of
> PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
>
> I want to make sure developers do not run into strange build failures if
> they do not keep the 2 different PCDs aligned. I prefer a single PCD
> setting to enable use of EC services.
>
> I also noticed that the use of a PCD expression in an INF to select source
> files does not work if the PCD value is specified with the --pcd flag on
> the build command line. This looks like a significant bug with the PCD
> expression in an INF file. This also needs to be fixed.
>
> Mike
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Thursday, September 22, 2022 8:02 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > 1. Yes, it matches.
> > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> refer to another internal email.
> >
> > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> PEM X509 ...
> >
> > If we added EC source to OpensslLib.inf and disabled macro
> OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > size,
> > This an example from x509/x_pubkey.c , other modules is similar:
> > #ifndef OPENSSL_NO_EC
> > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> length)
> > {
> > EVP_PKEY *pkey;
> > EC_KEY *key = NULL;
> > //.... call EC functions
> > }
> > #endif
> >
> > If we added EC source to OpensslLib.inf and enable macro
> OPENSSL_NO_EC, EC module will throw build error,
> > Since some EC internal APIs or structs have been disabled by
> OPENSSL_NO_EC but not another.
> > This an example from ec/ec_local.h , other error is similar:
> >
> > #ifndef OPENSSL_NO_EC
> > typedef struct ec_group_st EC_GROUP;
> > typedef struct ec_point_st EC_POINT;
> > #endif
> >
> > // but this function not been enclosed by OPENSSL_NO_EC, and will
> throw build error
> > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > EC_POINT *, const BIGNUM *x,
> > const BIGNUM *y,
> > const BIGNUM *z, BN_CTX *);
> >
> > To avoid this annoying openssl error, we introduced conditional EC.
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Friday, September 23, 2022 6:47 AM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D
> <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree EC is an important feature.
> >
> > I did some analysis of the size impact to the CryptoPkg modules on
> current trunk
> > with EC on and off. Uncompressed size is important for PEI Phase. For
> DXE and
> > SMM phase, the Crypto services can always be compressed. From the
> table below,
> > building all the EC services in the OpensslLib has no size impact to the
> NONE
> > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> DXE/SMM
> > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> >
> > Uncompressed LZMA Compressed
> > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> EC=TRUE Increase
> > ==== =============== ======== ======== ======= ========
> ======= ========
> > IA32 NONE CryptoPei 21536 21568 0 KB
> > IA32 NONE CryptoDxe 21632 21696 0 KB
> > IA32 NONE CryptoSmm 22976 23072 0 KB
> > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> 401034 113 KB
> > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> 296022 105 KB
> > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> KB
> > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> KB
> > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> KB
> > X64 NONE CryptoPei 29632 29664 0 KB
> > X64 NONE CryptoDxe 29792 29792 0 KB
> > X64 NONE CryptoSmm 31296 31296 0 KB
> > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> 426596 115 KB
> > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> 310775 106 KB
> > X64 ALL CryptoPei 540384 730240 202494 308467 106
> KB
> > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> KB
> > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> KB
> >
> > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> the
> > entire FV is compressed, the total size impact is typically the size of a
> > single instance of a compressed CryptoLib. The sizes of the Crypto*
> modules
> > in the table above should be a close approximation of the size impact
> to a
> > single FV.
> >
> > Does this match your previous size analysis?
> >
> > The critical issue to evaluate here is why adding the EC sources to
> OpensllLib.inf
> > causes the modules that do not use any EC services to grow by ~105KB.
> Has any
> > detailed analysis of the final linked images been performed to see where
> this
> > additional size is coming from?
> >
> > Thanks,
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Thursday, September 22, 2022 5:54 AM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > > I have did some POC that seems existed structured PCD is hard to
> control binary size,
> > > Here is the previous discussion for reference.
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > >
> > > Anyway EC is an important feature which consumed by vary modern
> security features such WPA3 , SPDM, TLS1.3 etc.
> > > Hope it can be added to edk2, and I am glad to take the code and test
> work if there are other ways to control the size.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Thursday, September 22, 2022 11:56 AM
> > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly
> <shelly.kishore@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > That change to OpensslLib.inf should not have been done either.
> > >
> > > Looks like this EC feature needs more evaluation to fit into the
> > > structured PCD control of the lib sizes.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > Thanks for review.
> > > >
> > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> will also be compiled and throw build error:
> > > >
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): error C2220: the following warning is treated
> > > as
> > > > an error
> > > > 1 file(s) copied.
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > undefined; assuming extern returning int
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(77): warning C4047: 'return': 'void *' differs in
> > > > levels of indirection from 'int'
> > > >
> d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> c(105): warning C4013: 'EC_GROUP_get_curve'
> > undefined;
> > > > assuming extern returning int
> > > >
> > > > I think the root cause is that we have enabled conditional ec in
> OpensslLib.inf before by PcdOpensslEcEnabled,
> > > >
> > >
> >
> https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > 02-L238
> > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > This will save 200+kb memory on platforms which use dxe driver but
> do not need ec feature.
> > > >
> > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> sure if there is any other way, other better ideas
> > are
> > > > welcome.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael
> D <michael.d.kinney@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Comments embedded below.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> yi1 li
> > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > To: devel@edk2.groups.io
> > > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > >
> > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > over OpenSSL.
> > > > >
> > > > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > > > >
> > > > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > > > ---
> > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> ++++++++++++++++++
> > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > 8 files changed, 2186 insertions(+)
> > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > create mode 100644
> CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > create mode 100644
> CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > >
> > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > index b253923dd8..d74fc21c1e 100644
> > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > > #include <Uefi/UefiBaseType.h>
> > > > >
> > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > +
> > > > > +// Key Exchange
> > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > +
> > > > > ///
> > > > > /// MD5 digest size in bytes
> > > > > ///
> > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > OUT VOID *BnRes
> > > > > );
> > > > >
> > > > > +//
> ==========================================================
> ===========================
> > > > > +// Basic Elliptic Curve Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > + and is used for calculation within this group. This object should be
> freed
> > > > > + using EcGroupFree() function.
> > > > > +
> > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> (Defined in
> > > > > + BaseCryptLib.h).
> > > > > +
> > > > > + @retval EcGroup object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > + IN UINTN CryptoNid
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnPrime Group prime number.
> > > > > + @param[out] BnA A coefficient.
> > > > > + @param[out] BnB B coefficient.
> > > > > + @param[in] BnCtx BN context.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *BnPrime,
> > > > > + OUT VOID *BnA,
> > > > > + OUT VOID *BnB,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Get EC group order.
> > > > > + This function will set the provided Big Number object to the
> corresponding
> > > > > + value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > + is properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnOrder Group prime number.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > + IN VOID *EcGroup,
> > > > > + OUT VOID *BnOrder
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > + @param[in] EcGroup EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > + IN VOID *EcGroup
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > + within the given EC group (curve).
> > > > > +
> > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > + @retval EC Point object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > + IN CONST VOID *EcGroup
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > + @param[in] EcPoint EC Point to free.
> > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > + IN VOID *EcPoint,
> > > > > + IN BOOLEAN Clear
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Get EC point affine (x,y) coordinates.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[out] BnX X coordinate.
> > > > > + @param[out] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + OUT VOID *BnX,
> > > > > + OUT VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN CONST VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPointA EC Point.
> > > > > + @param[in] EcPointB EC Point.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnPScalar P Scalar.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN CONST VOID *BnPScalar,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN OUT VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is on EC curve.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On curve.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is at infinity.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > +
> > > > > + @retval TRUE At infinity.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Check if EC points are equal.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPointA EC point A.
> > > > > + @param[in] EcPointB EC point B.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE A == B.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > + their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > + such that the point is on the curve there will only ever be two
> possible
> > > > > + values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > + possible values for y should be used.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN UINT8 YBit,
> > > > > + IN VOID *BnCtx
> > > > > + );
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > + with the NID.
> > > > > +
> > > > > + @param[in] Nid cipher NID
> > > > > + @return Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > + IN UINTN Nid
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Release the specified EC context.
> > > > > +
> > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > + IN VOID *EcContext
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > + pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > + function was properly called before.
> > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > + This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > + returned via parameter Public, PublicSize.
> > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > + EC context is updated accordingly.
> > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > + PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PublicSize is NULL, then return FALSE.
> > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Gets the public key component from the established EC context.
> > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > + generate key pair from EcGenerateKey().
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > + @retval FALSE Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + );
> > > > > +
> > > > > +/**
> > > > > + Computes exchanged common key.
> > > > > + Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > + based on its own context including value of curve parameter and
> random secret.
> > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > + If Key is NULL, then return FALSE.
> > > > > + If KeySize is not large enough, then return FALSE.
> > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > + @param[in] CompressFlag Flag of PeerPublic is
> compressed or not.
> > > > > + @param[out] Key Pointer to the buffer to receive
> generated key.
> > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> bytes.
> > > > > + On output, the size of data returned in Key
> buffer in bytes.
> > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > + @retval FALSE KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + IN CONST UINT8 *PeerPublic,
> > > > > + IN UINTN PeerPublicSize,
> > > > > + IN CONST INT32 *CompressFlag,
> > > > > + OUT UINT8 *Key,
> > > > > + IN OUT UINTN *KeySize
> > > > > + );
> > > > > +
> > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > @@ -52,6 +52,8 @@
> > > > > Pk/CryptTs.c
> > > > > Pk/CryptRsaPss.c
> > > > > Pk/CryptRsaPssSign.c
> > > > > + Pk/CryptEcNull.c
> |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > + Pk/CryptEc.c
> |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > >
> > > > The use of the PCD to select the file should not be needed here. The
> > > > Ec Family and individual service enable/disable fields in the
> > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> needed to
> > > > disable the Ec services.
> > > >
> > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> be removed
> > > > completely as part of this patch series.
> > > >
> > > > > Pem/CryptPem.c
> > > > > Bn/CryptBn.c
> > > > >
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > index 65ad23fb81..383df2b23c 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > @@ -58,6 +58,7 @@
> > > > > Pk/CryptTsNull.c
> > > > > Pk/CryptRsaPss.c
> > > > > Pk/CryptRsaPssSignNull.c
> > > > > + Pk/CryptEcNull.c
> > > > > Pem/CryptPemNull.c
> > > > > Rand/CryptRandNull.c
> > > > > Bn/CryptBnNull.c
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > new file mode 100644
> > > > > index 0000000000..396c819834
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > @@ -0,0 +1,765 @@
> > > > > +/** @file
> > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include "InternalCryptLib.h"
> > > > > +#include <openssl/objects.h>
> > > > > +#include <openssl/bn.h>
> > > > > +#include <openssl/ec.h>
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +// Basic Elliptic Curve Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > + Return the Nid of certain ECC curve.
> > > > > +
> > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> (Defined in
> > > > > + BaseCryptLib.h).
> > > > > +
> > > > > + @retval !=-1 On success.
> > > > > + @retval -1 ECC curve not supported.
> > > > > +**/
> > > > > +STATIC
> > > > > +INT32
> > > > > +CryptoNidToOpensslNid (
> > > > > + IN UINTN CryptoNid
> > > > > + )
> > > > > +{
> > > > > + INT32 Nid;
> > > > > +
> > > > > + switch (CryptoNid) {
> > > > > + case CRYPTO_NID_SECP256R1:
> > > > > + Nid = NID_X9_62_prime256v1;
> > > > > + break;
> > > > > + case CRYPTO_NID_SECP384R1:
> > > > > + Nid = NID_secp384r1;
> > > > > + break;
> > > > > + case CRYPTO_NID_SECP521R1:
> > > > > + Nid = NID_secp521r1;
> > > > > + break;
> > > > > + default:
> > > > > + return -1;
> > > > > + }
> > > > > +
> > > > > + return Nid;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > + and is used for calculation within this group. This object should be
> freed
> > > > > + using EcGroupFree() function.
> > > > > +
> > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> (Defined in
> > > > > + BaseCryptLib.h).
> > > > > +
> > > > > + @retval EcGroup object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > + IN UINTN CryptoNid
> > > > > + )
> > > > > +{
> > > > > + INT32 Nid;
> > > > > +
> > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > +
> > > > > + if (Nid < 0) {
> > > > > + return NULL;
> > > > > + }
> > > > > +
> > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnPrime Group prime number.
> > > > > + @param[out] BnA A coefficient.
> > > > > + @param[out] BnB B coefficient..
> > > > > + @param[in] BnCtx BN context.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *BnPrime,
> > > > > + OUT VOID *BnA,
> > > > > + OUT VOID *BnB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> BnB, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC group order.
> > > > > + This function will set the provided Big Number object to the
> corresponding
> > > > > + value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > + is properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnOrder Group prime number.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > + IN VOID *EcGroup,
> > > > > + OUT VOID *BnOrder
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> NULL);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > + @param[in] EcGroup EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > + IN VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + EC_GROUP_free (EcGroup);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > + within the given EC group (curve).
> > > > > +
> > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > + @retval EC Point object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > + IN CONST VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + return EC_POINT_new (EcGroup);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > + @param[in] EcPoint EC Point to free.
> > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > + IN VOID *EcPoint,
> > > > > + IN BOOLEAN Clear
> > > > > + )
> > > > > +{
> > > > > + if (Clear) {
> > > > > + EC_POINT_clear_free (EcPoint);
> > > > > + } else {
> > > > > + EC_POINT_free (EcPoint);
> > > > > + }
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC point affine (x,y) coordinates.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[out] BnX X coordinate.
> > > > > + @param[out] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + OUT VOID *BnX,
> > > > > + OUT VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> EcPoint, BnX, BnY, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN CONST VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> EcPoint, BnX, BnY, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPointA EC Point.
> > > > > + @param[in] EcPointB EC Point.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> EcPointA, EcPointB, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnPScalar P Scalar.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN CONST VOID *BnPScalar,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> EcPoint, BnPScalar, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN OUT VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is on EC curve.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On curve.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is at infinity.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > +
> > > > > + @retval TRUE At infinity.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint
> > > > > + )
> > > > > +{
> > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if EC points are equal.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPointA EC point A.
> > > > > + @param[in] EcPointB EC point B.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE A == B.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > + their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > + such that the point is on the curve there will only ever be two
> possible
> > > > > + values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > + possible values for y should be used.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN UINT8 YBit,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > +}
> > > > > +
> > > > > +//
> ==========================================================
> ===========================
> > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > +//
> ==========================================================
> ===========================
> > > > > +
> > > > > +/**
> > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > + with the NID.
> > > > > +
> > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> in
> > > > > + BaseCryptLib.h).
> > > > > + @return Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > + IN UINTN Nid
> > > > > + )
> > > > > +{
> > > > > + INT32 OpenSslNid;
> > > > > +
> > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > + if (OpenSslNid < 0) {
> > > > > + return NULL;
> > > > > + }
> > > > > +
> > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Release the specified EC context.
> > > > > +
> > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > + IN VOID *EcContext
> > > > > + )
> > > > > +{
> > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > + pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > + function was properly called before.
> > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > + This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > + returned via parameter Public, PublicSize.
> > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > + EC context is updated accordingly.
> > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > + PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PublicSize is NULL, then return FALSE.
> > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + EC_KEY *EcKey;
> > > > > + CONST EC_GROUP *Group;
> > > > > + CONST EC_POINT *EcPoint;
> > > > > + BOOLEAN RetVal;
> > > > > + BIGNUM *BnX;
> > > > > + BIGNUM *BnY;
> > > > > + UINTN HalfSize;
> > > > > + INTN XSize;
> > > > > + INTN YSize;
> > > > > +
> > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > +
> > > > > + // Assume RAND_seed was called
> > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > + *PublicKeySize = HalfSize * 2;
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + *PublicKeySize = HalfSize * 2;
> > > > > +
> > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > + if (EcPoint == NULL) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + RetVal = FALSE;
> > > > > + BnX = BN_new ();
> > > > > + BnY = BN_new ();
> > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> NULL) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + XSize = BN_num_bytes (BnX);
> > > > > + YSize = BN_num_bytes (BnY);
> > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > +
> > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > +
> > > > > + RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > + BN_free (BnX);
> > > > > + BN_free (BnY);
> > > > > + return RetVal;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Gets the public key component from the established EC context.
> > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > + generate key pair from EcGenerateKey().
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > + @retval FALSE Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + EC_KEY *EcKey;
> > > > > + CONST EC_GROUP *Group;
> > > > > + CONST EC_POINT *EcPoint;
> > > > > + BIGNUM *BnX;
> > > > > + BIGNUM *BnY;
> > > > > + UINTN HalfSize;
> > > > > + INTN XSize;
> > > > > + INTN YSize;
> > > > > + BOOLEAN RetVal;
> > > > > +
> > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > + *PublicKeySize = HalfSize * 2;
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + *PublicKeySize = HalfSize * 2;
> > > > > +
> > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > + if (EcPoint == NULL) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + RetVal = FALSE;
> > > > > + BnX = BN_new ();
> > > > > + BnY = BN_new ();
> > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> NULL) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + XSize = BN_num_bytes (BnX);
> > > > > + YSize = BN_num_bytes (BnY);
> > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > +
> > > > > + if (PublicKey != NULL) {
> > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > + }
> > > > > +
> > > > > + RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > + BN_free (BnX);
> > > > > + BN_free (BnY);
> > > > > + return RetVal;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Computes exchanged common key.
> > > > > + Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > + based on its own context including value of curve parameter and
> random secret.
> > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > + If public key is compressed, the PeerPublic will only contain half
> key (X).
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > + If Key is NULL, then return FALSE.
> > > > > + If KeySize is not large enough, then return FALSE.
> > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > + @param[in] CompressFlag Flag of PeerPublic is
> compressed or not.
> > > > > + @param[out] Key Pointer to the buffer to receive
> generated key.
> > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> bytes.
> > > > > + On output, the size of data returned in Key
> buffer in bytes.
> > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > + @retval FALSE KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + IN CONST UINT8 *PeerPublic,
> > > > > + IN UINTN PeerPublicSize,
> > > > > + IN CONST INT32 *CompressFlag,
> > > > > + OUT UINT8 *Key,
> > > > > + IN OUT UINTN *KeySize
> > > > > + )
> > > > > +{
> > > > > + EC_KEY *EcKey;
> > > > > + EC_KEY *PeerEcKey;
> > > > > + CONST EC_GROUP *Group;
> > > > > + BOOLEAN RetVal;
> > > > > + BIGNUM *BnX;
> > > > > + BIGNUM *BnY;
> > > > > + EC_POINT *Point;
> > > > > + INT32 OpenSslNid;
> > > > > + UINTN HalfSize;
> > > > > +
> > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> NULL)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + if (*KeySize < HalfSize) {
> > > > > + *KeySize = HalfSize;
> > > > > + return FALSE;
> > > > > + }
> > > > > +
> > > > > + *KeySize = HalfSize;
> > > > > +
> > > > > + RetVal = FALSE;
> > > > > + Point = NULL;
> > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > + BnY = NULL;
> > > > > + Point = EC_POINT_new (Group);
> > > > > + PeerEcKey = NULL;
> > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (CompressFlag == NULL) {
> > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > + if (BnY == NULL) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> NULL) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > + } else {
> > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> *CompressFlag, NULL) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + // Validate NIST ECDH public key
> > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > + if (PeerEcKey == NULL) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > + goto fail;
> > > > > + }
> > > > > +
> > > > > + RetVal = TRUE;
> > > > > +
> > > > > +fail:
> > > > > + BN_free (BnX);
> > > > > + BN_free (BnY);
> > > > > + EC_POINT_free (Point);
> > > > > + EC_KEY_free (PeerEcKey);
> > > > > + return RetVal;
> > > > > +}
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > new file mode 100644
> > > > > index 0000000000..d9f1004f6c
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > @@ -0,0 +1,496 @@
> > > > > +/** @file
> > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include <Library/BaseCryptLib.h>
> > > > > +#include <Library/DebugLib.h>
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > + and is used for calculation within this group. This object should be
> freed
> > > > > + using EcGroupFree() function.
> > > > > +
> > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> (Defined in
> > > > > + BaseCryptLib.h).
> > > > > +
> > > > > + @retval EcGroup object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > + IN UINTN CryptoNid
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnPrime Group prime number.
> > > > > + @param[out] BnA A coefficient.
> > > > > + @param[out] BnB B coefficient..
> > > > > + @param[in] BnCtx BN context.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *BnPrime,
> > > > > + OUT VOID *BnA,
> > > > > + OUT VOID *BnB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC group order.
> > > > > + This function will set the provided Big Number object to the
> corresponding
> > > > > + value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > + is properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnOrder Group prime number.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > + IN VOID *EcGroup,
> > > > > + OUT VOID *BnOrder
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > + @param[in] EcGroup EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > + IN VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > + within the given EC group (curve).
> > > > > +
> > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > + @retval EC Point object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > + IN CONST VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > + @param[in] EcPoint EC Point to free.
> > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > + IN VOID *EcPoint,
> > > > > + IN BOOLEAN Clear
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC point affine (x,y) coordinates.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[out] BnX X coordinate.
> > > > > + @param[out] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + OUT VOID *BnX,
> > > > > + OUT VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN CONST VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPointA EC Point.
> > > > > + @param[in] EcPointB EC Point.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnPScalar P Scalar.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN CONST VOID *BnPScalar,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN OUT VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is on EC curve.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On curve.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is at infinity.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > +
> > > > > + @retval TRUE At infinity.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if EC points are equal.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPointA EC point A.
> > > > > + @param[in] EcPointB EC point B.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE A == B.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > + their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > + such that the point is on the curve there will only ever be two
> possible
> > > > > + values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > + possible values for y should be used.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN UINT8 YBit,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > + with the NID.
> > > > > +
> > > > > + @param[in] Nid cipher NID
> > > > > + @return Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > + IN UINTN Nid
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Release the specified EC context.
> > > > > +
> > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > + IN VOID *EcContext
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > + pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > + function was properly called before.
> > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > + This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > + returned via parameter Public, PublicSize.
> > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > + EC context is updated accordingly.
> > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > + PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PublicSize is NULL, then return FALSE.
> > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Gets the public key component from the established EC context.
> > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > + generate key pair from EcGenerateKey().
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > + @retval FALSE Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Computes exchanged common key.
> > > > > + Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > + based on its own context including value of curve parameter and
> random secret.
> > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > + If Key is NULL, then return FALSE.
> > > > > + If KeySize is not large enough, then return FALSE.
> > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > + @param[in] CompressFlag Flag of PeerPublic is
> compressed or not.
> > > > > + @param[out] Key Pointer to the buffer to receive
> generated key.
> > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> bytes.
> > > > > + On output, the size of data returned in Key
> buffer in bytes.
> > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > + @retval FALSE KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + IN CONST UINT8 *PeerPublic,
> > > > > + IN UINTN PeerPublicSize,
> > > > > + IN CONST INT32 *CompressFlag,
> > > > > + OUT UINT8 *Key,
> > > > > + IN OUT UINTN *KeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > index ce6a789dfd..4bc3063485 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > @@ -59,6 +59,7 @@
> > > > > Pk/CryptTsNull.c
> > > > > Pk/CryptRsaPss.c
> > > > > Pk/CryptRsaPssSignNull.c
> > > > > + Pk/CryptEcNull.c
> > > > > Pem/CryptPem.c
> > > > > Bn/CryptBnNull.c
> > > > >
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > @@ -49,6 +49,7 @@
> > > > > Pk/CryptX509Null.c
> > > > > Pk/CryptAuthenticodeNull.c
> > > > > Pk/CryptTsNull.c
> > > > > + Pk/CryptEcNull.c
> > > > > Pem/CryptPemNull.c
> > > > > Rand/CryptRandNull.c
> > > > > Pk/CryptRsaPssNull.c
> > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > new file mode 100644
> > > > > index 0000000000..d9f1004f6c
> > > > > --- /dev/null
> > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > @@ -0,0 +1,496 @@
> > > > > +/** @file
> > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > +
> > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > +
> > > > > +**/
> > > > > +
> > > > > +#include <Library/BaseCryptLib.h>
> > > > > +#include <Library/DebugLib.h>
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EcGroup object. This object represents an EC
> curve and
> > > > > + and is used for calculation within this group. This object should be
> freed
> > > > > + using EcGroupFree() function.
> > > > > +
> > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> (Defined in
> > > > > + BaseCryptLib.h).
> > > > > +
> > > > > + @retval EcGroup object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcGroupInit (
> > > > > + IN UINTN CryptoNid
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> P = (X^3 + AX + B) Mod P.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnPrime Group prime number.
> > > > > + @param[out] BnA A coefficient.
> > > > > + @param[out] BnB B coefficient..
> > > > > + @param[in] BnCtx BN context.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *BnPrime,
> > > > > + OUT VOID *BnA,
> > > > > + OUT VOID *BnB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC group order.
> > > > > + This function will set the provided Big Number object to the
> corresponding
> > > > > + value. The caller needs to make sure that the "out" BigNumber
> parameter
> > > > > + is properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] BnOrder Group prime number.
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGroupGetOrder (
> > > > > + IN VOID *EcGroup,
> > > > > + OUT VOID *BnOrder
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > +
> > > > > + @param[in] EcGroup EC group object to free.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcGroupFree (
> > > > > + IN VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Initialize new opaque EC Point object. This object represents an EC
> point
> > > > > + within the given EC group (curve).
> > > > > +
> > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > +
> > > > > + @retval EC Point object On success.
> > > > > + @retval NULL On failure.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcPointInit (
> > > > > + IN CONST VOID *EcGroup
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > +
> > > > > + @param[in] EcPoint EC Point to free.
> > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcPointDeInit (
> > > > > + IN VOID *EcPoint,
> > > > > + IN BOOLEAN Clear
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Get EC point affine (x,y) coordinates.
> > > > > + This function will set the provided Big Number objects to the
> corresponding
> > > > > + values. The caller needs to make sure all the "out" BigNumber
> parameters
> > > > > + are properly initialized.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[out] BnX X coordinate.
> > > > > + @param[out] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointGetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + OUT VOID *BnX,
> > > > > + OUT VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point affine (x,y) coordinates.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point object.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] BnY Y coordinate.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetAffineCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN CONST VOID *BnY,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPointA EC Point.
> > > > > + @param[in] EcPointB EC Point.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointAdd (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> BnPScalar.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[out] EcPointResult EC point to hold the result. The
> point should
> > > > > + be properly initialized.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnPScalar P Scalar.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointMul (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + OUT VOID *EcPointResult,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN CONST VOID *BnPScalar,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Calculate the inverse of the supplied EC point.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointInvert (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN OUT VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is on EC curve.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On curve.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsOnCurve (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if the supplied point is at infinity.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC point to check.
> > > > > +
> > > > > + @retval TRUE At infinity.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointIsAtInfinity (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPoint
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Check if EC points are equal.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPointA EC point A.
> > > > > + @param[in] EcPointB EC point B.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE A == B.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointEqual (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN CONST VOID *EcPointA,
> > > > > + IN CONST VOID *EcPointB,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Set EC point compressed coordinates. Points can be described in
> terms of
> > > > > + their compressed coordinates. For a point (x, y), for any given
> value for x
> > > > > + such that the point is on the curve there will only ever be two
> possible
> > > > > + values for y. Therefore, a point can be set using this function
> where BnX is
> > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> two
> > > > > + possible values for y should be used.
> > > > > +
> > > > > + @param[in] EcGroup EC group object.
> > > > > + @param[in] EcPoint EC Point.
> > > > > + @param[in] BnX X coordinate.
> > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > + @param[in] BnCtx BN context, created with
> BigNumNewContext().
> > > > > +
> > > > > + @retval TRUE On success.
> > > > > + @retval FALSE Otherwise.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcPointSetCompressedCoordinates (
> > > > > + IN CONST VOID *EcGroup,
> > > > > + IN VOID *EcPoint,
> > > > > + IN CONST VOID *BnX,
> > > > > + IN UINT8 YBit,
> > > > > + IN VOID *BnCtx
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> use
> > > > > + with the NID.
> > > > > +
> > > > > + @param[in] Nid cipher NID
> > > > > + @return Pointer to the Elliptic Curve Context that has been
> initialized.
> > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > +**/
> > > > > +VOID *
> > > > > +EFIAPI
> > > > > +EcNewByNid (
> > > > > + IN UINTN Nid
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Release the specified EC context.
> > > > > +
> > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > +**/
> > > > > +VOID
> > > > > +EFIAPI
> > > > > +EcFree (
> > > > > + IN VOID *EcContext
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> this function uses
> > > > > + pseudo random number generator. The caller must make sure
> RandomSeed()
> > > > > + function was properly called before.
> > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > + This function generates random secret, and computes the public
> key (X, Y), which is
> > > > > + returned via parameter Public, PublicSize.
> > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > + EC context is updated accordingly.
> > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> returned and
> > > > > + PublicSize is set to the required buffer size to obtain the public X,
> Y.
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PublicSize is NULL, then return FALSE.
> > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGenerateKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Gets the public key component from the established EC context.
> > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> successfully
> > > > > + generate key pair from EcGenerateKey().
> > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> is Y.
> > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> is Y.
> > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> is Y.
> > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > + @param[out] PublicKey Pointer to t buffer to receive
> generated public X,Y.
> > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> in bytes.
> > > > > + On output, the size of data returned in Public
> buffer in bytes.
> > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > + @retval FALSE Invalid EC key component.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcGetPubKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + OUT UINT8 *PublicKey,
> > > > > + IN OUT UINTN *PublicKeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + Computes exchanged common key.
> > > > > + Given peer's public key (X, Y), this function computes the
> exchanged common key,
> > > > > + based on its own context including value of curve parameter and
> random secret.
> > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> 2.
> > > > > + If EcContext is NULL, then return FALSE.
> > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > + If Key is NULL, then return FALSE.
> > > > > + If KeySize is not large enough, then return FALSE.
> > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> byte is Y.
> > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> byte is Y.
> > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> byte is Y.
> > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > + @param[in] CompressFlag Flag of PeerPublic is
> compressed or not.
> > > > > + @param[out] Key Pointer to the buffer to receive
> generated key.
> > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> bytes.
> > > > > + On output, the size of data returned in Key
> buffer in bytes.
> > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > + @retval FALSE KeySize is not large enough.
> > > > > +**/
> > > > > +BOOLEAN
> > > > > +EFIAPI
> > > > > +EcDhComputeKey (
> > > > > + IN OUT VOID *EcContext,
> > > > > + IN CONST UINT8 *PeerPublic,
> > > > > + IN UINTN PeerPublicSize,
> > > > > + IN CONST INT32 *CompressFlag,
> > > > > + OUT UINT8 *Key,
> > > > > + IN OUT UINTN *KeySize
> > > > > + )
> > > > > +{
> > > > > + ASSERT (FALSE);
> > > > > + return FALSE;
> > > > > +}
> > > > > --
> > > > > 2.31.1.windows.1
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-23 22:40 ` Yao, Jiewen
@ 2022-09-24 2:19 ` Michael D Kinney
2022-09-24 3:44 ` yi1 li
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-24 2:19 UTC (permalink / raw)
To: Yao, Jiewen, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C, Kinney, Michael D
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
Hi Jiewen,
My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.
https://edk2.groups.io/g/devel/message/89019
My main concern at this point is how a platform developer knows how to configure these PCDs.
When should PcdOpensslEcEnabled be set to TRUE? The name of the PCD implies that EC services
are available, but that is not actually true. It only compiles the EC source files into
the openssl lib.
I think a developer has to enable other features in order to actually make use of the
content provided by those source files. Correct?
The other INF that adds the SSL files has the same issue. How does a developer know when
to use the INF with the SSL files or not. And what features need to be enabled in order to use
the content added by those SSL files.
We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources. If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources
Example:
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable SSL EC Description
======================================================== ===== ===== ===========
Sha256.Services.Init FALSE FALSE
Sha256.Services.Init FALSE TRUE
Sha256.Services.Init TRUE FALSE
Sha256.Services.Init TRUE TRUE
If there is a shorter way to describe the impact at the family level or groups of families, then
that would be acceptable as well.
I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable. However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs. This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.
Thanks,
Mike
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Chen, Christine
> <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo,
> Heng <heng.luo@intel.com>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
>
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
>
> Or if you have any other idea, please let us know.
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob
> > C <bob.c.feng@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > # define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine
> > <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney,
> > Michael D <michael.d.kinney@intel.com>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > Guomin <guomin.jiang@intel.com>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned. I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line. This looks like a significant bug with the PCD
> > expression in an INF file. This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509 ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > > EVP_PKEY *pkey;
> > > EC_KEY *key = NULL;
> > > //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > > EC_POINT *, const BIGNUM *x,
> > > const BIGNUM *y,
> > > const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kinney, Michael D
> > <michael.d.kinney@intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > Guomin <guomin.jiang@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase. For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed. From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > > Uncompressed LZMA Compressed
> > > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> > EC=TRUE Increase
> > > ==== =============== ======== ======== ======= ========
> > ======= ========
> > > IA32 NONE CryptoPei 21536 21568 0 KB
> > > IA32 NONE CryptoDxe 21632 21696 0 KB
> > > IA32 NONE CryptoSmm 22976 23072 0 KB
> > > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> > 401034 113 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> > 296022 105 KB
> > > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> > KB
> > > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> > KB
> > > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> > KB
> > > X64 NONE CryptoPei 29632 29664 0 KB
> > > X64 NONE CryptoDxe 29792 29792 0 KB
> > > X64 NONE CryptoSmm 31296 31296 0 KB
> > > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> > 426596 115 KB
> > > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> > 310775 106 KB
> > > X64 ALL CryptoPei 540384 730240 202494 308467 106
> > KB
> > > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> > KB
> > > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > > entire FV is compressed, the total size impact is typically the size of a
> > > single instance of a compressed CryptoLib. The sizes of the Crypto*
> > modules
> > > in the table above should be a close approximation of the size impact
> > to a
> > > single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io; Kishore, Shelly <shelly.kishore@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Kishore, Shelly
> > <shelly.kishore@intel.com>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > Guomin <guomin.jiang@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com>;
> > devel@edk2.groups.io
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > > 1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>; Kinney, Michael
> > D <michael.d.kinney@intel.com>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > > >
> > > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > > over OpenSSL.
> > > > > >
> > > > > > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > > > > >
> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com>
> > > > > > ---
> > > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> > ++++++++++++++++++
> > > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > 8 files changed, 2186 insertions(+)
> > > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > > +
> > > > > > ///
> > > > > > /// MD5 digest size in bytes
> > > > > > ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > > OUT VOID *BnRes
> > > > > > );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient.
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + );
> > > > > > +
> > > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > > Pk/CryptTs.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSign.c
> > > > > > + Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > + Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here. The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval !=-1 On success.
> > > > > > + @retval -1 ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + switch (CryptoNid) {
> > > > > > + case CRYPTO_NID_SECP256R1:
> > > > > > + Nid = NID_X9_62_prime256v1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP384R1:
> > > > > > + Nid = NID_secp384r1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP521R1:
> > > > > > + Nid = NID_secp521r1;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -1;
> > > > > > + }
> > > > > > +
> > > > > > + return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > + if (Nid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + if (Clear) {
> > > > > > + EC_POINT_clear_free (EcPoint);
> > > > > > + } else {
> > > > > > + EC_POINT_free (EcPoint);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> > in
> > > > > > + BaseCryptLib.h).
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 OpenSslNid;
> > > > > > +
> > > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > + if (OpenSslNid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > + // Assume RAND_seed was called
> > > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > + BOOLEAN RetVal;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + if (PublicKey != NULL) {
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + EC_KEY *PeerEcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + EC_POINT *Point;
> > > > > > + INT32 OpenSslNid;
> > > > > > + UINTN HalfSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*KeySize < HalfSize) {
> > > > > > + *KeySize = HalfSize;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *KeySize = HalfSize;
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + Point = NULL;
> > > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > + BnY = NULL;
> > > > > > + Point = EC_POINT_new (Group);
> > > > > > + PeerEcKey = NULL;
> > > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (CompressFlag == NULL) {
> > > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > + if (BnY == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + } else {
> > > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + // Validate NIST ECDH public key
> > > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > + if (PeerEcKey == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + EC_POINT_free (Point);
> > > > > > + EC_KEY_free (PeerEcKey);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > > Pk/CryptX509Null.c
> > > > > > Pk/CryptAuthenticodeNull.c
> > > > > > Pk/CryptTsNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-24 2:19 ` Michael D Kinney
@ 2022-09-24 3:44 ` yi1 li
2022-09-24 10:21 ` Yao, Jiewen
0 siblings, 1 reply; 17+ messages in thread
From: yi1 li @ 2022-09-24 3:44 UTC (permalink / raw)
To: Kinney, Michael D, Yao, Jiewen, devel@edk2.groups.io,
Chen, Christine, Feng, Bob C
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
[-- Attachment #1: Type: text/plain, Size: 126172 bytes --]
Hi Mike,
My bad missed this feedback ☹, this important issue should be discussed as early as possible.
The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs
additional information about the source files config PCD to ensure that the service is enabled properly.
We can add the following table to the DSC file for reference.
################################################################################
#
# Openssl Source Config Table
#
################################################################################
# Note: To ensure crypto services are properly enabled, platform requires:
# 1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family
# to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,
# OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X
# to TRUE if only function X of Services XX needed.
# 2. To optimize Crypto Driver binary size, source files of some crypto
# services have been set to conditional. Additional PCD in below table should
# be set to TRUE.
#===============================================================================
#| Crypto Service | Additional PCD |
#===============================================================================
#|TlsSet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|TlsGet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|Ec | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled |
#===============================================================================
Welcome basetools to provide better ways to optimize the use of PCD,
but from the previous discussion it seems to take quite a long time,
do you think we can merge the current patch first and then optimize it?
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Jiewen,
My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.
https://edk2.groups.io/g/devel/message/89019
My main concern at this point is how a platform developer knows how to configure these PCDs.
When should PcdOpensslEcEnabled be set to TRUE? The name of the PCD implies that EC services
are available, but that is not actually true. It only compiles the EC source files into
the openssl lib.
I think a developer has to enable other features in order to actually make use of the
content provided by those source files. Correct?
The other INF that adds the SSL files has the same issue. How does a developer know when
to use the INF with the SSL files or not. And what features need to be enabled in order to use
the content added by those SSL files.
We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources. If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources
Example:
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable SSL EC Description
======================================================== ===== ===== ===========
Sha256.Services.Init FALSE FALSE
Sha256.Services.Init FALSE TRUE
Sha256.Services.Init TRUE FALSE
Sha256.Services.Init TRUE TRUE
If there is a shorter way to describe the impact at the family level or groups of families, then
that would be acceptable as well.
I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable. However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs. This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.
Thanks,
Mike
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,
> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
>
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
>
> Or if you have any other idea, please let us know.
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob
> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > # define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,
> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned. I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line. This looks like a significant bug with the PCD
> > expression in an INF file. This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509 ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > > EVP_PKEY *pkey;
> > > EC_KEY *key = NULL;
> > > //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > > EC_POINT *, const BIGNUM *x,
> > > const BIGNUM *y,
> > > const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D
> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase. For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed. From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > > Uncompressed LZMA Compressed
> > > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> > EC=TRUE Increase
> > > ==== =============== ======== ======== ======= ========
> > ======= ========
> > > IA32 NONE CryptoPei 21536 21568 0 KB
> > > IA32 NONE CryptoDxe 21632 21696 0 KB
> > > IA32 NONE CryptoSmm 22976 23072 0 KB
> > > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> > 401034 113 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> > 296022 105 KB
> > > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> > KB
> > > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> > KB
> > > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> > KB
> > > X64 NONE CryptoPei 29632 29664 0 KB
> > > X64 NONE CryptoDxe 29792 29792 0 KB
> > > X64 NONE CryptoSmm 31296 31296 0 KB
> > > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> > 426596 115 KB
> > > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> > 310775 106 KB
> > > X64 ALL CryptoPei 540384 730240 202494 308467 106
> > KB
> > > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> > KB
> > > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > > entire FV is compressed, the total size impact is typically the size of a
> > > single instance of a compressed CryptoLib. The sizes of the Crypto*
> > modules
> > > in the table above should be a close approximation of the size impact
> > to a
> > > single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly
> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > > 1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael
> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;
> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > > >
> > > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > > over OpenSSL.
> > > > > >
> > > > > > Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>
> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > >
> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > > ---
> > > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> > ++++++++++++++++++
> > > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > 8 files changed, 2186 insertions(+)
> > > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > > +
> > > > > > ///
> > > > > > /// MD5 digest size in bytes
> > > > > > ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > > OUT VOID *BnRes
> > > > > > );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient.
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + );
> > > > > > +
> > > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > > Pk/CryptTs.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSign.c
> > > > > > + Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > + Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here. The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval !=-1 On success.
> > > > > > + @retval -1 ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + switch (CryptoNid) {
> > > > > > + case CRYPTO_NID_SECP256R1:
> > > > > > + Nid = NID_X9_62_prime256v1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP384R1:
> > > > > > + Nid = NID_secp384r1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP521R1:
> > > > > > + Nid = NID_secp521r1;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -1;
> > > > > > + }
> > > > > > +
> > > > > > + return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > + if (Nid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + if (Clear) {
> > > > > > + EC_POINT_clear_free (EcPoint);
> > > > > > + } else {
> > > > > > + EC_POINT_free (EcPoint);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> > in
> > > > > > + BaseCryptLib.h).
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 OpenSslNid;
> > > > > > +
> > > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > + if (OpenSslNid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > + // Assume RAND_seed was called
> > > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > + BOOLEAN RetVal;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + if (PublicKey != NULL) {
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + EC_KEY *PeerEcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + EC_POINT *Point;
> > > > > > + INT32 OpenSslNid;
> > > > > > + UINTN HalfSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*KeySize < HalfSize) {
> > > > > > + *KeySize = HalfSize;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *KeySize = HalfSize;
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + Point = NULL;
> > > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > + BnY = NULL;
> > > > > > + Point = EC_POINT_new (Group);
> > > > > > + PeerEcKey = NULL;
> > > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (CompressFlag == NULL) {
> > > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > + if (BnY == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + } else {
> > > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + // Validate NIST ECDH public key
> > > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > + if (PeerEcKey == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + EC_POINT_free (Point);
> > > > > > + EC_KEY_free (PeerEcKey);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > > Pk/CryptX509Null.c
> > > > > > Pk/CryptAuthenticodeNull.c
> > > > > > Pk/CryptTsNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
[-- Attachment #2: Type: text/html, Size: 330483 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-24 3:44 ` yi1 li
@ 2022-09-24 10:21 ` Yao, Jiewen
2022-09-24 15:16 ` Michael D Kinney
0 siblings, 1 reply; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-24 10:21 UTC (permalink / raw)
To: Li, Yi1, Kinney, Michael D, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
[-- Attachment #1: Type: text/plain, Size: 128133 bytes --]
Hi Mike
To clarify current situation: We support 3 different use cases:
1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.
2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.
3) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.
I think a platform developer should know its configuration and make right choice.
For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.
For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.
Thank you
Yao, Jiewen
From: Li, Yi1 <yi1.li@intel.com>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Mike,
My bad missed this feedback ☹, this important issue should be discussed as early as possible.
The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs
additional information about the source files config PCD to ensure that the service is enabled properly.
We can add the following table to the DSC file for reference.
################################################################################
#
# Openssl Source Config Table
#
################################################################################
# Note: To ensure crypto services are properly enabled, platform requires:
# 1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family
# to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,
# OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X
# to TRUE if only function X of Services XX needed.
# 2. To optimize Crypto Driver binary size, source files of some crypto
# services have been set to conditional. Additional PCD in below table should
# be set to TRUE.
#===============================================================================
#| Crypto Service | Additional PCD |
#===============================================================================
#|TlsSet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|TlsGet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|Ec | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled |
#===============================================================================
Welcome basetools to provide better ways to optimize the use of PCD,
but from the previous discussion it seems to take quite a long time,
do you think we can merge the current patch first and then optimize it?
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Jiewen,
My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.
https://edk2.groups.io/g/devel/message/89019
My main concern at this point is how a platform developer knows how to configure these PCDs.
When should PcdOpensslEcEnabled be set to TRUE? The name of the PCD implies that EC services
are available, but that is not actually true. It only compiles the EC source files into
the openssl lib.
I think a developer has to enable other features in order to actually make use of the
content provided by those source files. Correct?
The other INF that adds the SSL files has the same issue. How does a developer know when
to use the INF with the SSL files or not. And what features need to be enabled in order to use
the content added by those SSL files.
We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources. If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources
Example:
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable SSL EC Description
======================================================== ===== ===== ===========
Sha256.Services.Init FALSE FALSE
Sha256.Services.Init FALSE TRUE
Sha256.Services.Init TRUE FALSE
Sha256.Services.Init TRUE TRUE
If there is a shorter way to describe the impact at the family level or groups of families, then
that would be acceptable as well.
I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable. However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs. This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.
Thanks,
Mike
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,
> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
>
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
>
> Or if you have any other idea, please let us know.
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob
> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > # define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,
> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned. I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line. This looks like a significant bug with the PCD
> > expression in an INF file. This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509 ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > > EVP_PKEY *pkey;
> > > EC_KEY *key = NULL;
> > > //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > > EC_POINT *, const BIGNUM *x,
> > > const BIGNUM *y,
> > > const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D
> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase. For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed. From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > > Uncompressed LZMA Compressed
> > > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> > EC=TRUE Increase
> > > ==== =============== ======== ======== ======= ========
> > ======= ========
> > > IA32 NONE CryptoPei 21536 21568 0 KB
> > > IA32 NONE CryptoDxe 21632 21696 0 KB
> > > IA32 NONE CryptoSmm 22976 23072 0 KB
> > > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> > 401034 113 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> > 296022 105 KB
> > > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> > KB
> > > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> > KB
> > > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> > KB
> > > X64 NONE CryptoPei 29632 29664 0 KB
> > > X64 NONE CryptoDxe 29792 29792 0 KB
> > > X64 NONE CryptoSmm 31296 31296 0 KB
> > > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> > 426596 115 KB
> > > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> > 310775 106 KB
> > > X64 ALL CryptoPei 540384 730240 202494 308467 106
> > KB
> > > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> > KB
> > > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > > entire FV is compressed, the total size impact is typically the size of a
> > > single instance of a compressed CryptoLib. The sizes of the Crypto*
> > modules
> > > in the table above should be a close approximation of the size impact
> > to a
> > > single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly
> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > > 1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael
> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;
> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > > >
> > > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > > over OpenSSL.
> > > > > >
> > > > > > Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>
> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > >
> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > > ---
> > > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> > ++++++++++++++++++
> > > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > 8 files changed, 2186 insertions(+)
> > > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > > +
> > > > > > ///
> > > > > > /// MD5 digest size in bytes
> > > > > > ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > > OUT VOID *BnRes
> > > > > > );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient.
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + );
> > > > > > +
> > > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > > Pk/CryptTs.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSign.c
> > > > > > + Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > + Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here. The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval !=-1 On success.
> > > > > > + @retval -1 ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + switch (CryptoNid) {
> > > > > > + case CRYPTO_NID_SECP256R1:
> > > > > > + Nid = NID_X9_62_prime256v1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP384R1:
> > > > > > + Nid = NID_secp384r1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP521R1:
> > > > > > + Nid = NID_secp521r1;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -1;
> > > > > > + }
> > > > > > +
> > > > > > + return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > + if (Nid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + if (Clear) {
> > > > > > + EC_POINT_clear_free (EcPoint);
> > > > > > + } else {
> > > > > > + EC_POINT_free (EcPoint);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> > in
> > > > > > + BaseCryptLib.h).
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 OpenSslNid;
> > > > > > +
> > > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > + if (OpenSslNid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > + // Assume RAND_seed was called
> > > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > + BOOLEAN RetVal;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + if (PublicKey != NULL) {
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + EC_KEY *PeerEcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + EC_POINT *Point;
> > > > > > + INT32 OpenSslNid;
> > > > > > + UINTN HalfSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*KeySize < HalfSize) {
> > > > > > + *KeySize = HalfSize;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *KeySize = HalfSize;
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + Point = NULL;
> > > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > + BnY = NULL;
> > > > > > + Point = EC_POINT_new (Group);
> > > > > > + PeerEcKey = NULL;
> > > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (CompressFlag == NULL) {
> > > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > + if (BnY == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + } else {
> > > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + // Validate NIST ECDH public key
> > > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > + if (PeerEcKey == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + EC_POINT_free (Point);
> > > > > > + EC_KEY_free (PeerEcKey);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > > Pk/CryptX509Null.c
> > > > > > Pk/CryptAuthenticodeNull.c
> > > > > > Pk/CryptTsNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
[-- Attachment #2: Type: text/html, Size: 334643 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-24 10:21 ` Yao, Jiewen
@ 2022-09-24 15:16 ` Michael D Kinney
2022-09-24 16:03 ` Yao, Jiewen
0 siblings, 1 reply; 17+ messages in thread
From: Michael D Kinney @ 2022-09-24 15:16 UTC (permalink / raw)
To: Yao, Jiewen, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C, Kinney, Michael D
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
[-- Attachment #1: Type: text/plain, Size: 129909 bytes --]
Hi Jiewen,
Can you explain interaction with compiling SSL sources or not. There are 2 INFs a developer has to select from.
Also, just to clarify. I think you referring to the cyphers available through some of the openssl services.
There is a baseline set of cyphers that were selected for FW use a long time ago. What is that baseline set?
Building the EC sources extends the set of cyphers available.
Some FW features depend on different sets of cyphers in the CryptLib
Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features. Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.
I would like to see this documentation added and reviewed as part of the EC patch series.
Thanks,
Mike
From: Yao, Jiewen <jiewen.yao@intel.com>
Sent: Saturday, September 24, 2022 3:22 AM
To: Li, Yi1 <yi1.li@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Mike
To clarify current situation: We support 3 different use cases:
1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.
2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.
3) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.
I think a platform developer should know its configuration and make right choice.
For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.
For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.
Thank you
Yao, Jiewen
From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Mike,
My bad missed this feedback ☹, this important issue should be discussed as early as possible.
The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs
additional information about the source files config PCD to ensure that the service is enabled properly.
We can add the following table to the DSC file for reference.
################################################################################
#
# Openssl Source Config Table
#
################################################################################
# Note: To ensure crypto services are properly enabled, platform requires:
# 1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family
# to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,
# OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X
# to TRUE if only function X of Services XX needed.
# 2. To optimize Crypto Driver binary size, source files of some crypto
# services have been set to conditional. Additional PCD in below table should
# be set to TRUE.
#===============================================================================
#| Crypto Service | Additional PCD |
#===============================================================================
#|TlsSet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|TlsGet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|Ec | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled |
#===============================================================================
Welcome basetools to provide better ways to optimize the use of PCD,
but from the previous discussion it seems to take quite a long time,
do you think we can merge the current patch first and then optimize it?
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Jiewen,
My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.
https://edk2.groups.io/g/devel/message/89019
My main concern at this point is how a platform developer knows how to configure these PCDs.
When should PcdOpensslEcEnabled be set to TRUE? The name of the PCD implies that EC services
are available, but that is not actually true. It only compiles the EC source files into
the openssl lib.
I think a developer has to enable other features in order to actually make use of the
content provided by those source files. Correct?
The other INF that adds the SSL files has the same issue. How does a developer know when
to use the INF with the SSL files or not. And what features need to be enabled in order to use
the content added by those SSL files.
We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources. If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources
Example:
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable SSL EC Description
======================================================== ===== ===== ===========
Sha256.Services.Init FALSE FALSE
Sha256.Services.Init FALSE TRUE
Sha256.Services.Init TRUE FALSE
Sha256.Services.Init TRUE TRUE
If there is a shorter way to describe the impact at the family level or groups of families, then
that would be acceptable as well.
I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable. However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs. This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.
Thanks,
Mike
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,
> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
>
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
>
> Or if you have any other idea, please let us know.
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob
> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > # define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,
> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned. I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line. This looks like a significant bug with the PCD
> > expression in an INF file. This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509 ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > > EVP_PKEY *pkey;
> > > EC_KEY *key = NULL;
> > > //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > > EC_POINT *, const BIGNUM *x,
> > > const BIGNUM *y,
> > > const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D
> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase. For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed. From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > > Uncompressed LZMA Compressed
> > > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> > EC=TRUE Increase
> > > ==== =============== ======== ======== ======= ========
> > ======= ========
> > > IA32 NONE CryptoPei 21536 21568 0 KB
> > > IA32 NONE CryptoDxe 21632 21696 0 KB
> > > IA32 NONE CryptoSmm 22976 23072 0 KB
> > > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> > 401034 113 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> > 296022 105 KB
> > > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> > KB
> > > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> > KB
> > > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> > KB
> > > X64 NONE CryptoPei 29632 29664 0 KB
> > > X64 NONE CryptoDxe 29792 29792 0 KB
> > > X64 NONE CryptoSmm 31296 31296 0 KB
> > > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> > 426596 115 KB
> > > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> > 310775 106 KB
> > > X64 ALL CryptoPei 540384 730240 202494 308467 106
> > KB
> > > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> > KB
> > > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > > entire FV is compressed, the total size impact is typically the size of a
> > > single instance of a compressed CryptoLib. The sizes of the Crypto*
> > modules
> > > in the table above should be a close approximation of the size impact
> > to a
> > > single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly
> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > > 1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael
> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;
> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > > >
> > > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > > over OpenSSL.
> > > > > >
> > > > > > Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>
> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > >
> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > > ---
> > > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> > ++++++++++++++++++
> > > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > 8 files changed, 2186 insertions(+)
> > > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > > +
> > > > > > ///
> > > > > > /// MD5 digest size in bytes
> > > > > > ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > > OUT VOID *BnRes
> > > > > > );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient.
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + );
> > > > > > +
> > > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > > Pk/CryptTs.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSign.c
> > > > > > + Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > + Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here. The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval !=-1 On success.
> > > > > > + @retval -1 ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + switch (CryptoNid) {
> > > > > > + case CRYPTO_NID_SECP256R1:
> > > > > > + Nid = NID_X9_62_prime256v1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP384R1:
> > > > > > + Nid = NID_secp384r1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP521R1:
> > > > > > + Nid = NID_secp521r1;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -1;
> > > > > > + }
> > > > > > +
> > > > > > + return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > + if (Nid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + if (Clear) {
> > > > > > + EC_POINT_clear_free (EcPoint);
> > > > > > + } else {
> > > > > > + EC_POINT_free (EcPoint);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> > in
> > > > > > + BaseCryptLib.h).
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 OpenSslNid;
> > > > > > +
> > > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > + if (OpenSslNid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > + // Assume RAND_seed was called
> > > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > + BOOLEAN RetVal;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + if (PublicKey != NULL) {
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + EC_KEY *PeerEcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + EC_POINT *Point;
> > > > > > + INT32 OpenSslNid;
> > > > > > + UINTN HalfSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*KeySize < HalfSize) {
> > > > > > + *KeySize = HalfSize;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *KeySize = HalfSize;
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + Point = NULL;
> > > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > + BnY = NULL;
> > > > > > + Point = EC_POINT_new (Group);
> > > > > > + PeerEcKey = NULL;
> > > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (CompressFlag == NULL) {
> > > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > + if (BnY == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + } else {
> > > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + // Validate NIST ECDH public key
> > > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > + if (PeerEcKey == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + EC_POINT_free (Point);
> > > > > > + EC_KEY_free (PeerEcKey);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > > Pk/CryptX509Null.c
> > > > > > Pk/CryptAuthenticodeNull.c
> > > > > > Pk/CryptTsNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
[-- Attachment #2: Type: text/html, Size: 379577 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
2022-09-24 15:16 ` Michael D Kinney
@ 2022-09-24 16:03 ` Yao, Jiewen
0 siblings, 0 replies; 17+ messages in thread
From: Yao, Jiewen @ 2022-09-24 16:03 UTC (permalink / raw)
To: Kinney, Michael D, Li, Yi1, devel@edk2.groups.io, Chen, Christine,
Feng, Bob C
Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Luo, Heng
[-- Attachment #1: Type: text/plain, Size: 132784 bytes --]
Hi Mike
Good feedback and suggestion. I try to answer:
1. We don’t have PCD to control SSL yet. Neither PcdOpensslEcEnabled nor PcdCryptoServiceFamilyEnable controls SSL.
PcdOpensslEcEnabled controls the OPENSSL configuration.
PcdCryptoServiceFamilyEnable controls Crypto driver configuration.
They are in different level.
1. The PcdOpensslEcEnabled is to control if we need enable ECC MACRO for openssl.
Please refer to https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h
1. The base line of crypto set in openssl is controlled by https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf_generated.h
Before we introduce ECC, we don’t have any PcdOpensslXXXEnabled.
However, when we need ECC capability for TLS, we faced the situation that the size of crypto library is increased dramatically. That impacts the existing platform.
As such, the PcdOpensslEcEnabled is introduced to resolved the size issue, to control openssl MACRO such as OPENSSL_NO_EC.
We did tried reuse PcdCryptoServiceFamilyEnable. However, structure PCD solution does not work, which is confirmed with tool team.
1. Yes, I agree with you that we should provide better documentation to describe the usage and interaction between PcdOpensslEcEnabled and PcdCryptoServiceFamilyEnable.EC.
At least we should say: if PcdCryptoServiceFamilyEnable.EC is 1, then PcdOpensslEcEnabled must be TRUE.
Hi Yi
Please follow Mike’s suggestion to add one more patch to address below feedback:
=================
Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features. Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.
=================
Thank you
Yao Jiewen
From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Saturday, September 24, 2022 11:17 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io; Chen, Christine <yuwei.chen@intel.com>; Feng, Bob C <bob.c.feng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Luo, Heng <heng.luo@intel.com>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Jiewen,
Can you explain interaction with compiling SSL sources or not. There are 2 INFs a developer has to select from.
Also, just to clarify. I think you referring to the cyphers available through some of the openssl services.
There is a baseline set of cyphers that were selected for FW use a long time ago. What is that baseline set?
Building the EC sources extends the set of cyphers available.
Some FW features depend on different sets of cyphers in the CryptLib
Documenting these mappings in the CryptoPkg.dec file along with the PCD settings would
provide the information in one location for a platform developer to set the PCDs correctly
for their platform scoped FW features. Adding information about size impacts would
also be helpful for FW developers to select the right set of FW features for their platform
if they have FW size constraints.
I would like to see this documentation added and reviewed as part of the EC patch series.
Thanks,
Mike
From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Sent: Saturday, September 24, 2022 3:22 AM
To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Mike
To clarify current situation: We support 3 different use cases:
1) PcdOpensslEcEnabled = FALSE, PcdCryptoServiceFamilyEnable.Ec = FALSE
That means legacy platform. No ECC support at all.
2) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = FALSE
This means the platform need ECC in TLS. But no ECC is required in EDKII crypto service.
This is the first configuration to support ECC in surface use case.
3) PcdOpensslEcEnabled = TRUE, PcdCryptoServiceFamilyEnable.Ec = TRUE
This means the platform need ECC in TLS. Also ECC is available in EDKII crypto service.
This is the first configuration to support ECC in BIOS to support WPA3, and SPDM in the future.
I think a platform developer should know its configuration and make right choice.
For other crypto algorithm, we only have PcdCryptoServiceFamilyEnable.
For PcdOpensslEcEnabled, it is newly added for size optimization, as we discussed before.
Base tool team was already involved in the design the solution, with the known limitation of structure PCD.
And that was tool team’s recommendation at that moment.
Thank you
Yao, Jiewen
From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
Sent: Saturday, September 24, 2022 11:44 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Mike,
My bad missed this feedback ☹, this important issue should be discussed as early as possible.
The configuration of PcdCryptoServiceFamilyEnable seems obvious, and the developer may needs
additional information about the source files config PCD to ensure that the service is enabled properly.
We can add the following table to the DSC file for reference.
################################################################################
#
# Openssl Source Config Table
#
################################################################################
# Note: To ensure crypto services are properly enabled, platform requires:
# 1. Set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Family
# to PCD_CRYPTO_SERVICE_ENABLE_FAMILY,
# OR set gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.XX.Services.X
# to TRUE if only function X of Services XX needed.
# 2. To optimize Crypto Driver binary size, source files of some crypto
# services have been set to conditional. Additional PCD in below table should
# be set to TRUE.
#===============================================================================
#| Crypto Service | Additional PCD |
#===============================================================================
#|TlsSet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|TlsGet | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslSslEnabled [TBD] |
#|Ec | gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled |
#===============================================================================
Welcome basetools to provide better ways to optimize the use of PCD,
but from the previous discussion it seems to take quite a long time,
do you think we can merge the current patch first and then optimize it?
Thanks,
Yi
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Saturday, September 24, 2022 10:19 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
Hi Jiewen,
My feedback on this topic back on 4/18/22 was never addressed and this PCD was added anyways.
https://edk2.groups.io/g/devel/message/89019
My main concern at this point is how a platform developer knows how to configure these PCDs.
When should PcdOpensslEcEnabled be set to TRUE? The name of the PCD implies that EC services
are available, but that is not actually true. It only compiles the EC source files into
the openssl lib.
I think a developer has to enable other features in order to actually make use of the
content provided by those source files. Correct?
The other INF that adds the SSL files has the same issue. How does a developer know when
to use the INF with the SSL files or not. And what features need to be enabled in order to use
the content added by those SSL files.
We have a number of services in the BaseCryptLib that can be enabled and disabled using
the structured PCD gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
Can someone provide a table that shows each service from gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable
and if the service is impacted by the inclusion of the ssl sources and/or the ec sources. If there is an impact,
then describe the difference in the behavior for each of the 4 combinations of ssl and ec sources
Example:
gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable SSL EC Description
======================================================== ===== ===== ===========
Sha256.Services.Init FALSE FALSE
Sha256.Services.Init FALSE TRUE
Sha256.Services.Init TRUE FALSE
Sha256.Services.Init TRUE TRUE
If there is a shorter way to describe the impact at the family level or groups of families, then
that would be acceptable as well.
I would prefer the ssl and ec sources from openssl be added/removed based on settings
in the gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable. However, the feature
flag expressions supported in INF files today do not support use of fields from
structured PCDs. This needs to be discuss with the BaseTools owners to see if this
would be difficult to support or not.
Thanks,
Mike
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Sent: Friday, September 23, 2022 3:40 PM
> To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo,
> Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
>
> Hi Mike
> This has been investigated before, but we don’t have better solution than PcdOpensslEcEnabled.
>
> Given the fact that this PCD is introduced before (not in this patch set), do you think we can merge this first, then do
> enhancement for PCD related stuff later?
>
> Or if you have any other idea, please let us know.
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > Sent: Friday, September 23, 2022 3:09 PM
> > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob
> > C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>; Luo, Heng <heng.luo@intel.com<mailto:heng.luo@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Mike,
> >
> > I did make some attempts with it, but it doesn't work, two troubles here:
> >
> > Bob and Yuwei, please point out if I'm wrong:
> > 1. Using member of structure PCD in INF isn’t supported by Basetools
> > currently,
> > At least it cannot be used as FeatureFlag Expression.
> >
> > 2. As far as I know, structure PCD actually is a const array in code,
> > I afraid it will not work fine with precompile but we do have this need:
> > #if !FixedPcdGetBool (PcdOpensslEcEnabled)
> > # ifndef OPENSSL_NO_EC
> > # define OPENSSL_NO_EC
> > # endif
> > #endif
> >
> > This is really caused by the bad structure of openssl,
> > maybe we use more detailed comments to remind developers to sync the
> > two PCDs?
> >
> > Thanks,
> > Yi
> >
> > -----Original Message-----
> > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Sent: Friday, September 23, 2022 1:25 PM
> > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Chen, Christine
> > <yuwei.chen@intel.com<mailto:yuwei.chen@intel.com>>; Feng, Bob C <bob.c.feng@intel.com<mailto:bob.c.feng@intel.com>>; Kinney,
> > Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> >
> > Hi Yi,
> >
> > I agree there are some complex interactions in the opensll sources.
> >
> > Since you are defining a family for EC, can we use the EC Family != 0 instead
> > of
> > PcdOpensslEcEnabled and remove PcdOpensslEcEnabled.
> >
> > I want to make sure developers do not run into strange build failures if
> > they do not keep the 2 different PCDs aligned. I prefer a single PCD
> > setting to enable use of EC services.
> >
> > I also noticed that the use of a PCD expression in an INF to select source
> > files does not work if the PCD value is specified with the --pcd flag on
> > the build command line. This looks like a significant bug with the PCD
> > expression in an INF file. This also needs to be fixed.
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > Sent: Thursday, September 22, 2022 8:02 PM
> > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Mike,
> > >
> > > 1. Yes, it matches.
> > > By Intel side, 100+kb(20%+) FV size increase will be a big concern, please
> > refer to another internal email.
> > >
> > > 2. Additional size is coming from modules may consumed EC APIs, eg. TLS
> > PEM X509 ...
> > >
> > > If we added EC source to OpensslLib.inf and disabled macro
> > OPENSSL_NO_EC, those modules will link EC APIs and increase binary
> > > size,
> > > This an example from x509/x_pubkey.c , other modules is similar:
> > > #ifndef OPENSSL_NO_EC
> > > EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long
> > length)
> > > {
> > > EVP_PKEY *pkey;
> > > EC_KEY *key = NULL;
> > > //.... call EC functions
> > > }
> > > #endif
> > >
> > > If we added EC source to OpensslLib.inf and enable macro
> > OPENSSL_NO_EC, EC module will throw build error,
> > > Since some EC internal APIs or structs have been disabled by
> > OPENSSL_NO_EC but not another.
> > > This an example from ec/ec_local.h , other error is similar:
> > >
> > > #ifndef OPENSSL_NO_EC
> > > typedef struct ec_group_st EC_GROUP;
> > > typedef struct ec_point_st EC_POINT;
> > > #endif
> > >
> > > // but this function not been enclosed by OPENSSL_NO_EC, and will
> > throw build error
> > > int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
> > > EC_POINT *, const BIGNUM *x,
> > > const BIGNUM *y,
> > > const BIGNUM *z, BN_CTX *);
> > >
> > > To avoid this annoying openssl error, we introduced conditional EC.
> > >
> > > Thanks,
> > > Yi
> > >
> > > -----Original Message-----
> > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Sent: Friday, September 23, 2022 6:47 AM
> > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kinney, Michael D
> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Hi Yi,
> > >
> > > I agree EC is an important feature.
> > >
> > > I did some analysis of the size impact to the CryptoPkg modules on
> > current trunk
> > > with EC on and off. Uncompressed size is important for PEI Phase. For
> > DXE and
> > > SMM phase, the Crypto services can always be compressed. From the
> > table below,
> > > building all the EC services in the OpensslLib has no size impact to the
> > NONE
> > > profile and the MIN_PEI profile. It has ~105 KB impact to compressed
> > DXE/SMM
> > > usages that may use the MIN_DXE_MIN_SMM or ALL profiles.
> > >
> > > Uncompressed LZMA Compressed
> > > CPU CRYPTO_SERVICES Module EC=FALSE EC=TRUE EC=FALSE
> > EC=TRUE Increase
> > > ==== =============== ======== ======== ======= ========
> > ======= ========
> > > IA32 NONE CryptoPei 21536 21568 0 KB
> > > IA32 NONE CryptoDxe 21632 21696 0 KB
> > > IA32 NONE CryptoSmm 22976 23072 0 KB
> > > IA32 MIN_PEI CryptoPei 248992 249120 0 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoDxe 636672 829568 288520
> > 401034 113 KB
> > > IA32 MIN_DXE_MIN_SMM CryptoSmm 426048 601472 191517
> > 296022 105 KB
> > > IA32 ALL CryptoPei 423840 598976 189047 293759 104
> > KB
> > > IA32 ALL CryptoDxe 645280 838144 292955 405277 113
> > KB
> > > IA32 ALL CryptoSmm 441888 617184 198779 303628 105
> > KB
> > > X64 NONE CryptoPei 29632 29664 0 KB
> > > X64 NONE CryptoDxe 29792 29792 0 KB
> > > X64 NONE CryptoSmm 31296 31296 0 KB
> > > X64 MIN_PEI CryptoPei 310784 310848 0 KB
> > > X64 MIN_DXE_MIN_SMM CryptoDxe 804288 1016256 311436
> > 426596 115 KB
> > > X64 MIN_DXE_MIN_SMM CryptoSmm 543776 733920 204483
> > 310775 106 KB
> > > X64 ALL CryptoPei 540384 730240 202494 308467 106
> > KB
> > > X64 ALL CryptoDxe 815392 1027296 316228 431321 115
> > KB
> > > X64 ALL CryptoSmm 563648 753696 213488 319644 106
> > KB
> > >
> > > NOTE: Even if multiple modules in an FV use static linking of Crypto libs, if
> > the
> > > entire FV is compressed, the total size impact is typically the size of a
> > > single instance of a compressed CryptoLib. The sizes of the Crypto*
> > modules
> > > in the table above should be a close approximation of the size impact
> > to a
> > > single FV.
> > >
> > > Does this match your previous size analysis?
> > >
> > > The critical issue to evaluate here is why adding the EC sources to
> > OpensllLib.inf
> > > causes the modules that do not use any EC services to grow by ~105KB.
> > Has any
> > > detailed analysis of the final linked images been performed to see where
> > this
> > > additional size is coming from?
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > Sent: Thursday, September 22, 2022 5:54 AM
> > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > Hi Mike,
> > > > I have did some POC that seems existed structured PCD is hard to
> > control binary size,
> > > > Here is the previous discussion for reference.
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3679
> > > > https://edk2.groups.io/g/devel/topic/86257810#81814
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1446
> > > >
> > > > Anyway EC is an important feature which consumed by vary modern
> > security features such WPA3 , SPDM, TLS1.3 etc.
> > > > Hope it can be added to edk2, and I am glad to take the code and test
> > work if there are other ways to control the size.
> > > >
> > > > Thanks,
> > > > Yi
> > > >
> > > > -----Original Message-----
> > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > Sent: Thursday, September 22, 2022 11:56 AM
> > > > To: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Kishore, Shelly
> > <shelly.kishore@intel.com<mailto:shelly.kishore@intel.com>>
> > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > >
> > > > That change to OpensslLib.inf should not have been done either.
> > > >
> > > > Looks like this EC feature needs more evaluation to fit into the
> > > > structured PCD control of the lib sizes.
> > > >
> > > > Mike
> > > >
> > > > > -----Original Message-----
> > > > > From: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > > > To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
> > devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Hi Mike,
> > > > > Thanks for review.
> > > > >
> > > > > Even PCD_CRYPTO_SERVICE_FAMILY_ENABLE is set to 0, CryptoEc.c
> > will also be compiled and throw build error:
> > > > >
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): error C2220: the following warning is treated
> > > > as
> > > > > an error
> > > > > 1 file(s) copied.
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4013: 'EC_GROUP_new_by_curve_name'
> > > > > undefined; assuming extern returning int
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(77): warning C4047: 'return': 'void *' differs in
> > > > > levels of indirection from 'int'
> > > > >
> > d:\workspace\tianocore\edk2\CryptoPkg\Library\BaseCryptLib\Pk\CryptEc.
> > c(105): warning C4013: 'EC_GROUP_get_curve'
> > > undefined;
> > > > > assuming extern returning int
> > > > >
> > > > > I think the root cause is that we have enabled conditional ec in
> > OpensslLib.inf before by PcdOpensslEcEnabled,
> > > > >
> > > >
> > >
> > https://github.com/tianocore/edk2/blob/2c17d676e402d75a3a67449934
> > 2f7ddaccf387bd/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L2
> > > > > 02-L238
> > > > > if PcdOpensslEcEnabled not true, all ec files will not be compiled.
> > > > > This will save 200+kb memory on platforms which use dxe driver but
> > do not need ec feature.
> > > > >
> > > > > So I add this PCD to BaseCryptLib.inf also to avoid build error, Not
> > sure if there is any other way, other better ideas
> > > are
> > > > > welcome.
> > > > >
> > > > > Thanks,
> > > > > Yi
> > > > >
> > > > > -----Original Message-----
> > > > > From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Sent: Thursday, September 22, 2022 12:22 AM
> > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Kinney, Michael
> > D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > > > > Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wang, Jian J
> > <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang,
> > > > > Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > >
> > > > > Comments embedded below.
> > > > >
> > > > > Mike
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of
> > yi1 li
> > > > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > > > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> > > > > > Cc: Li, Yi1 <yi1.li@intel.com<mailto:yi1.li@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;
> > Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Lu, Xiaoyu1
> > > > > > <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>; Jiang, Guomin <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > > Subject: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> > > > > >
> > > > > > This patch is used to add CryptEc library, which is wrapped
> > > > > > over OpenSSL.
> > > > > >
> > > > > > Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> > > > > > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com<mailto:xiaoyu1.lu@intel.com>>
> > > > > > Cc: Guomin Jiang <guomin.jiang@intel.com<mailto:guomin.jiang@intel.com>>
> > > > > >
> > > > > > Signed-off-by: Yi Li <yi1.li@intel.com<mailto:yi1.li@intel.com>>
> > > > > > ---
> > > > > > CryptoPkg/Include/Library/BaseCryptLib.h | 424 ++++++++++
> > > > > > .../Library/BaseCryptLib/BaseCryptLib.inf | 2 +
> > > > > > .../Library/BaseCryptLib/PeiCryptLib.inf | 1 +
> > > > > > CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 765
> > ++++++++++++++++++
> > > > > > .../Library/BaseCryptLib/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > .../Library/BaseCryptLib/SmmCryptLib.inf | 1 +
> > > > > > .../BaseCryptLibNull/BaseCryptLibNull.inf | 1 +
> > > > > > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 496 ++++++++++++
> > > > > > 8 files changed, 2186 insertions(+)
> > > > > > create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > index b253923dd8..d74fc21c1e 100644
> > > > > > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > > > @@ -14,6 +14,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > #include <Uefi/UefiBaseType.h>
> > > > > >
> > > > > > +#define CRYPTO_NID_NULL 0x0000
> > > > > > +
> > > > > > +// Key Exchange
> > > > > > +#define CRYPTO_NID_SECP256R1 0x0204
> > > > > > +#define CRYPTO_NID_SECP384R1 0x0205
> > > > > > +#define CRYPTO_NID_SECP521R1 0x0206
> > > > > > +
> > > > > > ///
> > > > > > /// MD5 digest size in bytes
> > > > > > ///
> > > > > > @@ -2850,4 +2857,421 @@ BigNumAddMod (
> > > > > > OUT VOID *BnRes
> > > > > > );
> > > > > >
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient.
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + );
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + );
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + );
> > > > > > +
> > > > > > #endif // __BASE_CRYPT_LIB_H__
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > index 9e4be2fb0d..ade6ee3fdd 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > > > > > @@ -52,6 +52,8 @@
> > > > > > Pk/CryptTs.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSign.c
> > > > > > + Pk/CryptEcNull.c
> > |*|*|*|!gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > > > + Pk/CryptEc.c
> > |*|*|*|gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled
> > > > >
> > > > > The use of the PCD to select the file should not be needed here. The
> > > > > Ec Family and individual service enable/disable fields in the
> > > > > PCD_CRYPTO_SERVICE_FAMILY_ENABLE structured PCD are all that is
> > needed to
> > > > > disable the Ec services.
> > > > >
> > > > > The PCD gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled should
> > be removed
> > > > > completely as part of this patch series.
> > > > >
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBn.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > index 65ad23fb81..383df2b23c 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > > > > > @@ -58,6 +58,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Bn/CryptBnNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..396c819834
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> > > > > > @@ -0,0 +1,765 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include "InternalCryptLib.h"
> > > > > > +#include <openssl/objects.h>
> > > > > > +#include <openssl/bn.h>
> > > > > > +#include <openssl/ec.h>
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Basic Elliptic Curve Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Return the Nid of certain ECC curve.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval !=-1 On success.
> > > > > > + @retval -1 ECC curve not supported.
> > > > > > +**/
> > > > > > +STATIC
> > > > > > +INT32
> > > > > > +CryptoNidToOpensslNid (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + switch (CryptoNid) {
> > > > > > + case CRYPTO_NID_SECP256R1:
> > > > > > + Nid = NID_X9_62_prime256v1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP384R1:
> > > > > > + Nid = NID_secp384r1;
> > > > > > + break;
> > > > > > + case CRYPTO_NID_SECP521R1:
> > > > > > + Nid = NID_secp521r1;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -1;
> > > > > > + }
> > > > > > +
> > > > > > + return Nid;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 Nid;
> > > > > > +
> > > > > > + Nid = CryptoNidToOpensslNid (CryptoNid);
> > > > > > +
> > > > > > + if (Nid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return EC_GROUP_new_by_curve_name (Nid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA,
> > BnB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder,
> > NULL);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + EC_GROUP_free (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_new (EcGroup);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + if (Clear) {
> > > > > > + EC_POINT_clear_free (EcPoint);
> > > > > > + } else {
> > > > > > + EC_POINT_free (EcPoint);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup,
> > EcPoint, BnX, BnY, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult,
> > EcPointA, EcPointB, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL,
> > EcPoint, BnPScalar, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_on_curve (EcGroup, EcPoint, BnCtx) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_is_at_infinity (EcGroup, EcPoint) == 1;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return EC_POINT_cmp (EcGroup, EcPointA, EcPointB, BnCtx) == 0;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + return (BOOLEAN)EC_POINT_set_compressed_coordinates
> > (EcGroup, EcPoint, BnX, YBit, BnCtx);
> > > > > > +}
> > > > > > +
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +// Elliptic Curve Diffie Hellman Primitives
> > > > > > +//
> > ==========================================================
> > ===========================
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid Identifying number for the ECC curve (Defined
> > in
> > > > > > + BaseCryptLib.h).
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + INT32 OpenSslNid;
> > > > > > +
> > > > > > + OpenSslNid = CryptoNidToOpensslNid (Nid);
> > > > > > + if (OpenSslNid < 0) {
> > > > > > + return NULL;
> > > > > > + }
> > > > > > +
> > > > > > + return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY_free ((EC_KEY *)EcContext);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > +
> > > > > > + // Assume RAND_seed was called
> > > > > > + if (EC_KEY_generate_key (EcKey) != 1) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + CONST EC_POINT *EcPoint;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + UINTN HalfSize;
> > > > > > + INTN XSize;
> > > > > > + INTN YSize;
> > > > > > + BOOLEAN RetVal;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PublicKeySize == NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if (*PublicKeySize < HalfSize * 2) {
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *PublicKeySize = HalfSize * 2;
> > > > > > +
> > > > > > + EcPoint = EC_KEY_get0_public_key (EcKey);
> > > > > > + if (EcPoint == NULL) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + BnX = BN_new ();
> > > > > > + BnY = BN_new ();
> > > > > > + if ((BnX == NULL) || (BnY == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + XSize = BN_num_bytes (BnX);
> > > > > > + YSize = BN_num_bytes (BnY);
> > > > > > + if ((XSize <= 0) || (YSize <= 0)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
> > > > > > +
> > > > > > + if (PublicKey != NULL) {
> > > > > > + ZeroMem (PublicKey, *PublicKeySize);
> > > > > > + BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]);
> > > > > > + BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]);
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If public key is compressed, the PeerPublic will only contain half
> > key (X).
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + EC_KEY *EcKey;
> > > > > > + EC_KEY *PeerEcKey;
> > > > > > + CONST EC_GROUP *Group;
> > > > > > + BOOLEAN RetVal;
> > > > > > + BIGNUM *BnX;
> > > > > > + BIGNUM *BnY;
> > > > > > + EC_POINT *Point;
> > > > > > + INT32 OpenSslNid;
> > > > > > + UINTN HalfSize;
> > > > > > +
> > > > > > + if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize ==
> > NULL)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((Key == NULL) && (*KeySize != 0)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (PeerPublicSize > INT_MAX) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + EcKey = (EC_KEY *)EcContext;
> > > > > > + Group = EC_KEY_get0_group (EcKey);
> > > > > > + HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
> > > > > > + if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if ((CompressFlag != NULL) && (PeerPublicSize != HalfSize)) {
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + if (*KeySize < HalfSize) {
> > > > > > + *KeySize = HalfSize;
> > > > > > + return FALSE;
> > > > > > + }
> > > > > > +
> > > > > > + *KeySize = HalfSize;
> > > > > > +
> > > > > > + RetVal = FALSE;
> > > > > > + Point = NULL;
> > > > > > + BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL);
> > > > > > + BnY = NULL;
> > > > > > + Point = EC_POINT_new (Group);
> > > > > > + PeerEcKey = NULL;
> > > > > > + if ((BnX == NULL) || (Point == NULL)) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (CompressFlag == NULL) {
> > > > > > + BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL);
> > > > > > + if (BnY == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY,
> > NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + } else {
> > > > > > + if (EC_POINT_set_compressed_coordinates (Group, Point, BnX,
> > *CompressFlag, NULL) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + // Validate NIST ECDH public key
> > > > > > + OpenSslNid = EC_GROUP_get_curve_name (Group);
> > > > > > + PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
> > > > > > + if (PeerEcKey == NULL) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (EC_KEY_check_key (PeerEcKey) != 1) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) {
> > > > > > + goto fail;
> > > > > > + }
> > > > > > +
> > > > > > + RetVal = TRUE;
> > > > > > +
> > > > > > +fail:
> > > > > > + BN_free (BnX);
> > > > > > + BN_free (BnY);
> > > > > > + EC_POINT_free (Point);
> > > > > > + EC_KEY_free (PeerEcKey);
> > > > > > + return RetVal;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > index ce6a789dfd..4bc3063485 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > > > @@ -59,6 +59,7 @@
> > > > > > Pk/CryptTsNull.c
> > > > > > Pk/CryptRsaPss.c
> > > > > > Pk/CryptRsaPssSignNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPem.c
> > > > > > Bn/CryptBnNull.c
> > > > > >
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > index 354f3d80aa..e1a57ef09f 100644
> > > > > > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > > > > > @@ -49,6 +49,7 @@
> > > > > > Pk/CryptX509Null.c
> > > > > > Pk/CryptAuthenticodeNull.c
> > > > > > Pk/CryptTsNull.c
> > > > > > + Pk/CryptEcNull.c
> > > > > > Pem/CryptPemNull.c
> > > > > > Rand/CryptRandNull.c
> > > > > > Pk/CryptRsaPssNull.c
> > > > > > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d9f1004f6c
> > > > > > --- /dev/null
> > > > > > +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> > > > > > @@ -0,0 +1,496 @@
> > > > > > +/** @file
> > > > > > + Elliptic Curve and ECDH API implementation based on OpenSSL
> > > > > > +
> > > > > > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > +
> > > > > > +**/
> > > > > > +
> > > > > > +#include <Library/BaseCryptLib.h>
> > > > > > +#include <Library/DebugLib.h>
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EcGroup object. This object represents an EC
> > curve and
> > > > > > + and is used for calculation within this group. This object should be
> > freed
> > > > > > + using EcGroupFree() function.
> > > > > > +
> > > > > > + @param[in] CryptoNid Identifying number for the ECC curve
> > (Defined in
> > > > > > + BaseCryptLib.h).
> > > > > > +
> > > > > > + @retval EcGroup object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcGroupInit (
> > > > > > + IN UINTN CryptoNid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC curve parameters. While elliptic curve equation is Y^2 mod
> > P = (X^3 + AX + B) Mod P.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnPrime Group prime number.
> > > > > > + @param[out] BnA A coefficient.
> > > > > > + @param[out] BnB B coefficient..
> > > > > > + @param[in] BnCtx BN context.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *BnPrime,
> > > > > > + OUT VOID *BnA,
> > > > > > + OUT VOID *BnB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC group order.
> > > > > > + This function will set the provided Big Number object to the
> > corresponding
> > > > > > + value. The caller needs to make sure that the "out" BigNumber
> > parameter
> > > > > > + is properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] BnOrder Group prime number.
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGroupGetOrder (
> > > > > > + IN VOID *EcGroup,
> > > > > > + OUT VOID *BnOrder
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC group object using EcGroupInit().
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object to free.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcGroupFree (
> > > > > > + IN VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Initialize new opaque EC Point object. This object represents an EC
> > point
> > > > > > + within the given EC group (curve).
> > > > > > +
> > > > > > + @param[in] EC Group, properly initialized using EcGroupInit().
> > > > > > +
> > > > > > + @retval EC Point object On success.
> > > > > > + @retval NULL On failure.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcPointInit (
> > > > > > + IN CONST VOID *EcGroup
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Free previously allocated EC Point object using EcPointInit().
> > > > > > +
> > > > > > + @param[in] EcPoint EC Point to free.
> > > > > > + @param[in] Clear TRUE iff the memory should be cleared.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcPointDeInit (
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN BOOLEAN Clear
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Get EC point affine (x,y) coordinates.
> > > > > > + This function will set the provided Big Number objects to the
> > corresponding
> > > > > > + values. The caller needs to make sure all the "out" BigNumber
> > parameters
> > > > > > + are properly initialized.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[out] BnX X coordinate.
> > > > > > + @param[out] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointGetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + OUT VOID *BnX,
> > > > > > + OUT VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point affine (x,y) coordinates.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point object.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] BnY Y coordinate.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetAffineCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN CONST VOID *BnY,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + EC Point addition. EcPointResult = EcPointA + EcPointB.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPointA EC Point.
> > > > > > + @param[in] EcPointB EC Point.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointAdd (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Variable EC point multiplication. EcPointResult = EcPoint *
> > BnPScalar.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[out] EcPointResult EC point to hold the result. The
> > point should
> > > > > > + be properly initialized.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnPScalar P Scalar.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointMul (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + OUT VOID *EcPointResult,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN CONST VOID *BnPScalar,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Calculate the inverse of the supplied EC point.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in,out] EcPoint EC point to invert.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointInvert (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN OUT VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is on EC curve.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On curve.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsOnCurve (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if the supplied point is at infinity.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC point to check.
> > > > > > +
> > > > > > + @retval TRUE At infinity.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointIsAtInfinity (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPoint
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Check if EC points are equal.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPointA EC point A.
> > > > > > + @param[in] EcPointB EC point B.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE A == B.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointEqual (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN CONST VOID *EcPointA,
> > > > > > + IN CONST VOID *EcPointB,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Set EC point compressed coordinates. Points can be described in
> > terms of
> > > > > > + their compressed coordinates. For a point (x, y), for any given
> > value for x
> > > > > > + such that the point is on the curve there will only ever be two
> > possible
> > > > > > + values for y. Therefore, a point can be set using this function
> > where BnX is
> > > > > > + the x coordinate and YBit is a value 0 or 1 to identify which of the
> > two
> > > > > > + possible values for y should be used.
> > > > > > +
> > > > > > + @param[in] EcGroup EC group object.
> > > > > > + @param[in] EcPoint EC Point.
> > > > > > + @param[in] BnX X coordinate.
> > > > > > + @param[in] YBit 0 or 1 to identify which Y value is used.
> > > > > > + @param[in] BnCtx BN context, created with
> > BigNumNewContext().
> > > > > > +
> > > > > > + @retval TRUE On success.
> > > > > > + @retval FALSE Otherwise.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcPointSetCompressedCoordinates (
> > > > > > + IN CONST VOID *EcGroup,
> > > > > > + IN VOID *EcPoint,
> > > > > > + IN CONST VOID *BnX,
> > > > > > + IN UINT8 YBit,
> > > > > > + IN VOID *BnCtx
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Allocates and Initializes one Elliptic Curve Context for subsequent
> > use
> > > > > > + with the NID.
> > > > > > +
> > > > > > + @param[in] Nid cipher NID
> > > > > > + @return Pointer to the Elliptic Curve Context that has been
> > initialized.
> > > > > > + If the allocations fails, EcNewByNid() returns NULL.
> > > > > > +**/
> > > > > > +VOID *
> > > > > > +EFIAPI
> > > > > > +EcNewByNid (
> > > > > > + IN UINTN Nid
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return NULL;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Release the specified EC context.
> > > > > > +
> > > > > > + @param[in] EcContext Pointer to the EC context to be released.
> > > > > > +**/
> > > > > > +VOID
> > > > > > +EFIAPI
> > > > > > +EcFree (
> > > > > > + IN VOID *EcContext
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Generates EC key and returns EC public key (X, Y), Please note,
> > this function uses
> > > > > > + pseudo random number generator. The caller must make sure
> > RandomSeed()
> > > > > > + function was properly called before.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid.
> > > > > > + This function generates random secret, and computes the public
> > key (X, Y), which is
> > > > > > + returned via parameter Public, PublicSize.
> > > > > > + X is the first half of Public with size being PublicSize / 2,
> > > > > > + Y is the second half of Public with size being PublicSize / 2.
> > > > > > + EC context is updated accordingly.
> > > > > > + If the Public buffer is too small to hold the public X, Y, FALSE is
> > returned and
> > > > > > + PublicSize is set to the required buffer size to obtain the public X,
> > Y.
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PublicSize is NULL, then return FALSE.
> > > > > > + If PublicSize is large enough but Public is NULL, then return FALSE.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC public X,Y generation succeeded.
> > > > > > + @retval FALSE EC public X,Y generation failed.
> > > > > > + @retval FALSE PublicKeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGenerateKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Gets the public key component from the established EC context.
> > > > > > + The Ec context should be correctly initialized by EcNewByNid, and
> > successfully
> > > > > > + generate key pair from EcGenerateKey().
> > > > > > + For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte
> > is Y.
> > > > > > + For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte
> > is Y.
> > > > > > + For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte
> > is Y.
> > > > > > + @param[in, out] EcContext Pointer to EC context being set.
> > > > > > + @param[out] PublicKey Pointer to t buffer to receive
> > generated public X,Y.
> > > > > > + @param[in, out] PublicKeySize On input, the size of Public buffer
> > in bytes.
> > > > > > + On output, the size of data returned in Public
> > buffer in bytes.
> > > > > > + @retval TRUE EC key component was retrieved successfully.
> > > > > > + @retval FALSE Invalid EC key component.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcGetPubKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + OUT UINT8 *PublicKey,
> > > > > > + IN OUT UINTN *PublicKeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + Computes exchanged common key.
> > > > > > + Given peer's public key (X, Y), this function computes the
> > exchanged common key,
> > > > > > + based on its own context including value of curve parameter and
> > random secret.
> > > > > > + X is the first half of PeerPublic with size being PeerPublicSize / 2,
> > > > > > + Y is the second half of PeerPublic with size being PeerPublicSize /
> > 2.
> > > > > > + If EcContext is NULL, then return FALSE.
> > > > > > + If PeerPublic is NULL, then return FALSE.
> > > > > > + If PeerPublicSize is 0, then return FALSE.
> > > > > > + If Key is NULL, then return FALSE.
> > > > > > + If KeySize is not large enough, then return FALSE.
> > > > > > + For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-
> > byte is Y.
> > > > > > + For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-
> > byte is Y.
> > > > > > + For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-
> > byte is Y.
> > > > > > + @param[in, out] EcContext Pointer to the EC context.
> > > > > > + @param[in] PeerPublic Pointer to the peer's public X,Y.
> > > > > > + @param[in] PeerPublicSize Size of peer's public X,Y in bytes.
> > > > > > + @param[in] CompressFlag Flag of PeerPublic is
> > compressed or not.
> > > > > > + @param[out] Key Pointer to the buffer to receive
> > generated key.
> > > > > > + @param[in, out] KeySize On input, the size of Key buffer in
> > bytes.
> > > > > > + On output, the size of data returned in Key
> > buffer in bytes.
> > > > > > + @retval TRUE EC exchanged key generation succeeded.
> > > > > > + @retval FALSE EC exchanged key generation failed.
> > > > > > + @retval FALSE KeySize is not large enough.
> > > > > > +**/
> > > > > > +BOOLEAN
> > > > > > +EFIAPI
> > > > > > +EcDhComputeKey (
> > > > > > + IN OUT VOID *EcContext,
> > > > > > + IN CONST UINT8 *PeerPublic,
> > > > > > + IN UINTN PeerPublicSize,
> > > > > > + IN CONST INT32 *CompressFlag,
> > > > > > + OUT UINT8 *Key,
> > > > > > + IN OUT UINTN *KeySize
> > > > > > + )
> > > > > > +{
> > > > > > + ASSERT (FALSE);
> > > > > > + return FALSE;
> > > > > > +}
> > > > > > --
> > > > > > 2.31.1.windows.1
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
[-- Attachment #2: Type: text/html, Size: 345088 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2022-09-24 16:03 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <cover.1663735439.git.yi1.li@intel.com>
2022-09-21 4:54 ` [PATCH V2 1/3] CryptoPkg: Add EC support yi1 li
2022-09-21 16:21 ` [edk2-devel] " Michael D Kinney
2022-09-22 2:15 ` yi1 li
2022-09-22 3:56 ` Michael D Kinney
2022-09-22 12:54 ` yi1 li
2022-09-22 22:46 ` Michael D Kinney
2022-09-23 3:01 ` yi1 li
2022-09-23 5:25 ` Michael D Kinney
2022-09-23 7:08 ` yi1 li
2022-09-23 22:40 ` Yao, Jiewen
2022-09-24 2:19 ` Michael D Kinney
2022-09-24 3:44 ` yi1 li
2022-09-24 10:21 ` Yao, Jiewen
2022-09-24 15:16 ` Michael D Kinney
2022-09-24 16:03 ` Yao, Jiewen
2022-09-21 4:54 ` [PATCH V2 2/3] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
2022-09-21 4:54 ` [PATCH V2 3/3] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox