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

yi1 li yi1.li at intel.com
Fri Sep 23 07:08:39 UTC 2022


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 at intel.com> 
Sent: Friday, September 23, 2022 1:25 PM
To: Li, Yi1 <yi1.li at intel.com>; devel at edk2.groups.io; Chen, Christine <yuwei.chen at intel.com>; Feng, Bob C <bob.c.feng at intel.com>; Kinney, Michael D <michael.d.kinney at intel.com>
Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang, Guomin <guomin.jiang at 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 at intel.com>
> Sent: Thursday, September 22, 2022 8:02 PM
> To: Kinney, Michael D <michael.d.kinney at intel.com>; devel at edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> Guomin <guomin.jiang at 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 at intel.com>
> Sent: Friday, September 23, 2022 6:47 AM
> To: Li, Yi1 <yi1.li at intel.com>; devel at edk2.groups.io; Kinney, Michael D <michael.d.kinney at intel.com>
> Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> Guomin <guomin.jiang at 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 at intel.com>
> > Sent: Thursday, September 22, 2022 5:54 AM
> > To: Kinney, Michael D <michael.d.kinney at intel.com>; devel at edk2.groups.io; Kishore, Shelly <shelly.kishore at intel.com>
> > Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> > Guomin <guomin.jiang at 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 at intel.com>
> > Sent: Thursday, September 22, 2022 11:56 AM
> > To: Li, Yi1 <yi1.li at intel.com>; devel at edk2.groups.io; Kishore, Shelly <shelly.kishore at intel.com>
> > Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> > Guomin <guomin.jiang at 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 at intel.com>
> > > Sent: Wednesday, September 21, 2022 7:16 PM
> > > To: Kinney, Michael D <michael.d.kinney at intel.com>; devel at edk2.groups.io
> > > Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> > > Guomin <guomin.jiang at 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 at intel.com>
> > > Sent: Thursday, September 22, 2022 12:22 AM
> > > To: devel at edk2.groups.io; Li, Yi1 <yi1.li at intel.com>; Kinney, Michael D <michael.d.kinney at intel.com>
> > > Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> > > Guomin <guomin.jiang at intel.com>
> > > Subject: RE: [edk2-devel] [PATCH V2 1/3] CryptoPkg: Add EC support
> > >
> > > Comments embedded below.
> > >
> > > Mike
> > >
> > > > -----Original Message-----
> > > > From: devel at edk2.groups.io <devel at edk2.groups.io> On Behalf Of yi1 li
> > > > Sent: Tuesday, September 20, 2022 9:55 PM
> > > > To: devel at edk2.groups.io
> > > > Cc: Li, Yi1 <yi1.li at intel.com>; Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1
> > > > <xiaoyu1.lu at intel.com>; Jiang, Guomin <guomin.jiang at 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 at intel.com>
> > > > Cc: Jian J Wang <jian.j.wang at intel.com>
> > > > Cc: Xiaoyu Lu <xiaoyu1.lu at intel.com>
> > > > Cc: Guomin Jiang <guomin.jiang at intel.com>
> > > >
> > > > Signed-off-by: Yi Li <yi1.li at 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
> > > >
> > > >
> > > >
> > > > 
> > > >



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#94190): https://edk2.groups.io/g/devel/message/94190
Mute This Topic: https://groups.io/mt/93820542/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list