public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib
@ 2022-09-07  8:29 yi1 li
  2022-09-07  8:29 ` [PATCH 1/7] CryptoPkg: Add BigNum support yi1 li
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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

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

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

Tested-by: Yi Li <yi1.li@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>

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

Yi Li (7):
  CryptoPkg: Add BigNum support
  CryptoPkg: Add BigNum API to DXE and protocol
  CryptoPkg: Add EC support
  CryptoPkg: Add EC APIs to DXE and protocol
  CryptoPkg/Test: Add unit test for CryptoBn
  CryptoPkg/Test: Add unit test for CryptoEc
  CryptoPkg: Run uncrustify tools on EC and BN change

 CryptoPkg/CryptoPkg.dsc                       |    2 +
 CryptoPkg/Driver/Crypto.c                     | 1016 +++++++++++++-
 CryptoPkg/Include/Library/BaseCryptLib.h      |  842 ++++++++++++
 .../Pcd/PcdCryptoServiceFamilyEnable.h        |   55 +
 .../Library/BaseCryptLib/BaseCryptLib.inf     |    3 +
 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   |  581 ++++++++
 .../Library/BaseCryptLib/Bn/CryptBnNull.c     |  520 ++++++++
 .../Library/BaseCryptLib/PeiCryptLib.inf      |    2 +
 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   |  765 +++++++++++
 .../Library/BaseCryptLib/Pk/CryptEcNull.c     |  496 +++++++
 .../Library/BaseCryptLib/SmmCryptLib.inf      |    2 +
 .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |    3 +
 .../BaseCryptLibNull/BaseCryptLibNull.inf     |    2 +
 .../Library/BaseCryptLibNull/Bn/CryptBnNull.c |  520 ++++++++
 .../Library/BaseCryptLibNull/Pk/CryptEcNull.c |  496 +++++++
 .../BaseCryptLibOnProtocolPpi/CryptLib.c      |  961 ++++++++++++++
 CryptoPkg/Private/Protocol/Crypto.h           | 1176 ++++++++++++++---
 CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |    3 +
 .../BaseCryptLib/BaseCryptLibUnitTests.c      |    2 +
 .../UnitTest/Library/BaseCryptLib/BnTests.c   |  266 ++++
 .../UnitTest/Library/BaseCryptLib/EcTests.c   |  290 ++++
 .../Library/BaseCryptLib/TestBaseCryptLib.h   |    5 +
 .../BaseCryptLib/TestBaseCryptLibHost.inf     |    2 +
 .../BaseCryptLib/TestBaseCryptLibShell.inf    |    2 +
 24 files changed, 7852 insertions(+), 160 deletions(-)
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c

-- 
2.31.1.windows.1


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

* [PATCH 1/7] CryptoPkg: Add BigNum support
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 2/7] CryptoPkg: Add BigNum API to DXE and protocol yi1 li
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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

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

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/Include/Library/BaseCryptLib.h      | 418 +++++++++++++
 .../Library/BaseCryptLib/BaseCryptLib.inf     |   1 +
 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   | 581 ++++++++++++++++++
 .../Library/BaseCryptLib/Bn/CryptBnNull.c     | 520 ++++++++++++++++
 .../Library/BaseCryptLib/PeiCryptLib.inf      |   1 +
 .../Library/BaseCryptLib/SmmCryptLib.inf      |   1 +
 .../BaseCryptLibNull/BaseCryptLibNull.inf     |   1 +
 .../Library/BaseCryptLibNull/Bn/CryptBnNull.c | 520 ++++++++++++++++
 8 files changed, 2043 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c

diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index 7d1499350a..b253923dd8 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -2432,4 +2432,422 @@ HkdfSha256ExtractAndExpand (
   IN   UINTN        OutSize
   );
 
+// =====================================================================================
+//    Big number primitives
+// =====================================================================================
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumInit (
+  VOID
+  );
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  );
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+BigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  );
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+BigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  );
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+BigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  );
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+
+UINTN
+EFIAPI
+BigNumBits (
+  IN CONST VOID  *Bn
+  );
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+BigNumBytes (
+  IN CONST VOID  *Bn
+  );
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  );
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsOdd (
+  IN CONST VOID  *Bn
+  );
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+BigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  );
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+BigNumValueOne (
+  VOID
+  );
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number.
+**/
+VOID
+EFIAPI
+BigNumConstTime (
+  IN VOID  *Bn
+  );
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  );
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumNewContext (
+  VOID
+  );
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+BigNumContextFree (
+  IN VOID  *BnCtx
+  );
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  );
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  );
+
 #endif // __BASE_CRYPT_LIB_H__
diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
index 3d7b917103..9e4be2fb0d 100644
--- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -53,6 +53,7 @@
   Pk/CryptRsaPss.c
   Pk/CryptRsaPssSign.c
   Pem/CryptPem.c
+  Bn/CryptBn.c
 
   SysCall/CrtWrapper.c
   SysCall/TimerWrapper.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
new file mode 100644
index 0000000000..7a3043b1de
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
@@ -0,0 +1,581 @@
+/** @file  Big number 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/bn.h>
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumInit (
+  VOID
+  )
+{
+  return BN_new ();
+}
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  )
+{
+  return BN_bin2bn (Buf, (INT32)Len, NULL);
+}
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+BigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  )
+{
+  return BN_bn2bin (Bn, Buf);
+}
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+BigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  )
+{
+  if (Clear) {
+    BN_clear_free (Bn);
+  } else {
+    BN_free (Bn);
+  }
+}
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return (BOOLEAN) BN_add (BnRes, BnA, BnB);
+}
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return (BOOLEAN) BN_sub (BnRes, BnA, BnB);
+}
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_mod (BnRes, BnA, BnB, Ctx);
+  BN_CTX_free (Ctx);
+
+  return RetVal;
+}
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_mod_exp (BnRes, BnA, BnP, BnM, Ctx);
+
+  BN_CTX_free (Ctx);
+  return RetVal;
+}
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = FALSE;
+  if (BN_mod_inverse (BnRes, BnA, BnM, Ctx) != NULL) {
+    RetVal = TRUE;
+  };
+
+  BN_CTX_free (Ctx);
+  return RetVal;
+}
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_div (BnRes, NULL, BnA, BnB, Ctx);
+  BN_CTX_free (Ctx);
+
+  return RetVal;
+}
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_mod_mul (BnRes, BnA, BnB, BnM, Ctx);
+  BN_CTX_free (Ctx);
+
+  return RetVal;
+}
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+BigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  )
+{
+  return BN_cmp (BnA, BnB);
+}
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+UINTN
+EFIAPI
+BigNumBits (
+  IN CONST VOID  *Bn
+  )
+{
+  return BN_num_bits (Bn);
+}
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+BigNumBytes (
+  IN CONST VOID  *Bn
+  )
+{
+  return BN_num_bytes (Bn);
+}
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  )
+{
+  return (BOOLEAN) BN_is_word (Bn, Num);
+}
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsOdd (
+  IN CONST VOID  *Bn
+  )
+{
+  return (BOOLEAN) BN_is_odd (Bn);
+}
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+BigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  )
+{
+  return BN_copy (BnDst, BnSrc);
+}
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+BigNumValueOne (
+  VOID
+  )
+{
+  return BN_value_one ();
+}
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  )
+{
+  return (BOOLEAN) BN_rshift (BnRes, Bn, (INT32) N);
+}
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number
+**/
+VOID
+EFIAPI
+BigNumConstTime (
+  IN VOID  *Bn
+  )
+{
+  BN_set_flags (Bn, BN_FLG_CONSTTIME);
+}
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_mod_sqr (BnRes, BnA, BnM, Ctx);
+  BN_CTX_free (Ctx);
+
+  return RetVal;
+}
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumNewContext (
+  VOID
+  )
+{
+  return BN_CTX_new ();
+}
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+BigNumContextFree (
+  IN VOID  *BnCtx
+  )
+{
+  BN_CTX_free (BnCtx);
+}
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  )
+{
+  return (BOOLEAN) BN_set_word (Bn, Val);
+}
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  BOOLEAN RetVal;
+  BN_CTX  *Ctx;
+
+  Ctx = BN_CTX_new ();
+  if (Ctx == NULL) {
+    return FALSE;
+  }
+
+  RetVal = (BOOLEAN) BN_mod_add (BnRes, BnA, BnB, BnM, Ctx);
+  BN_CTX_free (Ctx);
+
+  return RetVal;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
new file mode 100644
index 0000000000..547401fa12
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
@@ -0,0 +1,520 @@
+/** @file
+  Big number 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>
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumInit (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+BigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  )
+{
+  ASSERT (FALSE);
+  return -1;
+}
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+BigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+BigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+UINTN
+EFIAPI
+BigNumBits (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+BigNumBytes (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsOdd (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+BigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+BigNumValueOne (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number
+**/
+VOID
+EFIAPI
+BigNumConstTime (
+  IN VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumNewContext (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+BigNumContextFree (
+  IN VOID  *BnCtx
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
index 01de27e037..65ad23fb81 100644
--- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -60,6 +60,7 @@
   Pk/CryptRsaPssSignNull.c
   Pem/CryptPemNull.c
   Rand/CryptRandNull.c
+  Bn/CryptBnNull.c
 
   SysCall/CrtWrapper.c
   SysCall/ConstantTimeClock.c
diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index 91a1715095..ce6a789dfd 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -60,6 +60,7 @@
   Pk/CryptRsaPss.c
   Pk/CryptRsaPssSignNull.c
   Pem/CryptPem.c
+  Bn/CryptBnNull.c
 
   SysCall/CrtWrapper.c
   SysCall/ConstantTimeClock.c
diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
index 63d1d82d19..354f3d80aa 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
+++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -53,6 +53,7 @@
   Rand/CryptRandNull.c
   Pk/CryptRsaPssNull.c
   Pk/CryptRsaPssSignNull.c
+  Bn/CryptBnNull.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c b/CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
new file mode 100644
index 0000000000..547401fa12
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
@@ -0,0 +1,520 @@
+/** @file
+  Big number 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>
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumInit (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+BigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  )
+{
+  ASSERT (FALSE);
+  return -1;
+}
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+BigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+BigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+UINTN
+EFIAPI
+BigNumBits (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+BigNumBytes (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsOdd (
+  IN CONST VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+BigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+BigNumValueOne (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number
+**/
+VOID
+EFIAPI
+BigNumConstTime (
+  IN VOID  *Bn
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumNewContext (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return NULL;
+}
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+BigNumContextFree (
+  IN VOID  *BnCtx
+  )
+{
+  ASSERT (FALSE);
+}
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
-- 
2.31.1.windows.1


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

* [PATCH 2/7] CryptoPkg: Add BigNum API to DXE and protocol
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
  2022-09-07  8:29 ` [PATCH 1/7] CryptoPkg: Add BigNum support yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 3/7] CryptoPkg: Add EC support yi1 li
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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

The implementation provides CryptBn library functions
for EFI CryptoDxe and EFI BaseCrypt Protocol.

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

Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/CryptoPkg.dsc                       |   1 +
 CryptoPkg/Driver/Crypto.c                     | 520 +++++++++++++++++-
 .../Pcd/PcdCryptoServiceFamilyEnable.h        |  30 +
 .../BaseCryptLibOnProtocolPpi/CryptLib.c      | 492 +++++++++++++++++
 CryptoPkg/Private/Protocol/Crypto.h           | 427 ++++++++++++++
 5 files changed, 1469 insertions(+), 1 deletion(-)

diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index 50e7721f25..a766851728 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -168,6 +168,7 @@
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Tls.Family                               | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsSet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsGet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
+  gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Bn.Family                                | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
 !endif
 
 !if $(CRYPTO_SERVICES) == MIN_PEI
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index 76cb9f4da0..07150ad2f2 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -4582,6 +4582,498 @@ CryptoServiceParallelHash256HashAll (
   return CALL_BASECRYPTLIB (ParallelHash.Services.HashAll, ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
 }
 
+// =====================================================================================
+//    Big number primitives
+// =====================================================================================
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceBigNumInit (
+  VOID
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Init, BigNumInit, (), NULL);
+}
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceBigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.FromBin, BigNumFromBin, (Buf, Len), NULL);
+}
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+CryptoServiceBigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.ToBin, BigNumToBin, (Bn, Buf), -1);
+}
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+CryptoServiceBigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Bn.Services.Free, BigNumFree, (Bn, Clear));
+}
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Add, BigNumAdd, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Sub, BigNumSub, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Mod, BigNumMod, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized.
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.ExpMod, BigNumExpMod, (BnA, BnP, BnM, BnRes), FALSE);
+}
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.InverseMod, BigNumInverseMod, (BnA, BnM, BnRes), FALSE);
+}
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Div, BigNumDiv, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.MulMod, BigNumMulMod, (BnA, BnB, BnM, BnRes), FALSE);
+}
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+CryptoServiceBigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Cmp, BigNumCmp, (BnA, BnB), 0);
+}
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+UINTN
+EFIAPI
+CryptoServiceBigNumBits (
+  IN CONST VOID  *Bn
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Bits, BigNumBits, (Bn), 0);
+}
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+CryptoServiceBigNumBytes (
+  IN CONST VOID  *Bn
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Bytes, BigNumBytes, (Bn), 0);
+}
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.IsWord, BigNumIsWord, (Bn, Num), FALSE);
+}
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumIsOdd (
+  IN CONST VOID  *Bn
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.IsOdd, BigNumIsOdd, (Bn), FALSE);
+}
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+CryptoServiceBigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.Copy, BigNumCopy, (BnDst, BnSrc), NULL);
+}
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+CryptoServiceBigNumValueOne (
+  VOID
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.ValueOne, BigNumValueOne, (), NULL);
+}
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.RShift, BigNumRShift, (Bn, N, BnRes), FALSE);
+}
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number.
+**/
+VOID
+EFIAPI
+CryptoServiceBigNumConstTime (
+  IN VOID  *Bn
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Bn.Services.ConstTime, BigNumConstTime, (Bn));
+}
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.SqrMod, BigNumSqrMod, (BnA, BnM, BnRes), FALSE);
+}
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceBigNumNewContext (
+  VOID
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.NewContext, BigNumNewContext, (), NULL);
+}
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+CryptoServiceBigNumContextFree (
+  IN VOID  *BnCtx
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Bn.Services.ContextFree, BigNumContextFree, (BnCtx));
+}
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.SetUint, BigNumSetUint, (Bn, Val), FALSE);
+}
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceBigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  return CALL_BASECRYPTLIB (Bn.Services.AddMod, BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
+}
+
 const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   /// Version
   CryptoServiceGetCryptoVersion,
@@ -4787,5 +5279,31 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   CryptoServiceRsaPssSign,
   CryptoServiceRsaPssVerify,
   /// Parallel hash
-  CryptoServiceParallelHash256HashAll
+  CryptoServiceParallelHash256HashAll,
+  /// Big Numbers
+  CryptoServiceBigNumInit,
+  CryptoServiceBigNumFromBin,
+  CryptoServiceBigNumToBin,
+  CryptoServiceBigNumFree,
+  CryptoServiceBigNumAdd,
+  CryptoServiceBigNumSub,
+  CryptoServiceBigNumMod,
+  CryptoServiceBigNumExpMod,
+  CryptoServiceBigNumInverseMod,
+  CryptoServiceBigNumDiv,
+  CryptoServiceBigNumMulMod,
+  CryptoServiceBigNumCmp,
+  CryptoServiceBigNumBits,
+  CryptoServiceBigNumBytes,
+  CryptoServiceBigNumIsWord,
+  CryptoServiceBigNumIsOdd,
+  CryptoServiceBigNumCopy,
+  CryptoServiceBigNumValueOne,
+  CryptoServiceBigNumRShift,
+  CryptoServiceBigNumConstTime,
+  CryptoServiceBigNumSqrMod,
+  CryptoServiceBigNumNewContext,
+  CryptoServiceBigNumContextFree,
+  CryptoServiceBigNumSetUint,
+  CryptoServiceBigNumAddMod,
 };
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 3d53c2f105..1b3c9d8f52 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -301,6 +301,36 @@ typedef struct {
     } Services;
     UINT32    Family;
   } ParallelHash;
+  union {
+    struct {
+      UINT8    Init        : 1;
+      UINT8    FromBin     : 1;
+      UINT8    ToBin       : 1;
+      UINT8    Free        : 1;
+      UINT8    Add         : 1;
+      UINT8    Sub         : 1;
+      UINT8    Mod         : 1;
+      UINT8    ExpMod      : 1;
+      UINT8    InverseMod  : 1;
+      UINT8    Div         : 1;
+      UINT8    MulMod      : 1;
+      UINT8    Cmp         : 1;
+      UINT8    Bits        : 1;
+      UINT8    Bytes       : 1;
+      UINT8    IsWord      : 1;
+      UINT8    IsOdd       : 1;
+      UINT8    Copy        : 1;
+      UINT8    ValueOne    : 1;
+      UINT8    RShift      : 1;
+      UINT8    ConstTime   : 1;
+      UINT8    SqrMod      : 1;
+      UINT8    NewContext  : 1;
+      UINT8    ContextFree : 1;
+      UINT8    SetUint     : 1;
+      UINT8    AddMod      : 1;
+    } Services;
+    UINT32    Family;
+  } Bn;
 } PCD_CRYPTO_SERVICE_FAMILY_ENABLE;
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index 8ee1b53cf9..c5d71b5269 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -3612,3 +3612,495 @@ TlsGetCertRevocationList (
 {
   CALL_CRYPTO_SERVICE (TlsGetCertRevocationList, (Data, DataSize), EFI_UNSUPPORTED);
 }
+
+// =====================================================================================
+//    Big number primitive
+// =====================================================================================
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumInit (
+  VOID
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumInit, (), NULL);
+}
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumFromBin (
+  IN CONST UINT8  *Buf,
+  IN UINTN        Len
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumFromBin, (Buf, Len), NULL);
+}
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least BigNumBytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+INTN
+EFIAPI
+BigNumToBin (
+  IN CONST VOID  *Bn,
+  OUT UINT8      *Buf
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumToBin, (Bn, Buf), -1);
+}
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+VOID
+EFIAPI
+BigNumFree (
+  IN VOID     *Bn,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (BigNumFree, (Bn, Clear));
+}
+
+/**
+  Calculate the sum of two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAdd (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumAdd, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Subtract two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSub (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumSub, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Calculate remainder: BnRes = BnA % BnB
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumMod, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result of (BnA ^ BnP) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumExpMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnP,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumExpMod, (BnA, BnP, BnM, BnRes), FALSE);
+}
+
+/**
+  Compute BnA inverse modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumInverseMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumInverseMod, (BnA, BnM, BnRes), FALSE);
+}
+
+/**
+  Divide two Big Numbers.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumDiv (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumDiv, (BnA, BnB, BnRes), FALSE);
+}
+
+/**
+  Multiply two Big Numbers modulo BnM.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumMulMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumMulMod, (BnA, BnB, BnM, BnRes), FALSE);
+}
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+INTN
+EFIAPI
+BigNumCmp (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumCmp, (BnA, BnB), 0);
+}
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+UINTN
+EFIAPI
+BigNumBits (
+  IN CONST VOID  *Bn
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumBits, (Bn), 0);
+}
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+UINTN
+EFIAPI
+BigNumBytes (
+  IN CONST VOID  *Bn
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumBytes, (Bn), 0);
+}
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsWord (
+  IN CONST VOID  *Bn,
+  IN UINTN       Num
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumIsWord, (Bn, Num), FALSE);
+}
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumIsOdd (
+  IN CONST VOID  *Bn
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumIsOdd, (Bn), FALSE);
+}
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+VOID *
+EFIAPI
+BigNumCopy (
+  OUT VOID       *BnDst,
+  IN CONST VOID  *BnSrc
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumCopy, (BnDst, BnSrc), NULL);
+}
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+CONST VOID *
+EFIAPI
+BigNumValueOne (
+  VOID
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumValueOne, (), NULL);
+}
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumRShift (
+  IN CONST VOID  *Bn,
+  IN UINTN       N,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumRShift, (Bn, N, BnRes), FALSE);
+}
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number.
+**/
+VOID
+EFIAPI
+BigNumConstTime (
+  IN VOID  *Bn
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (BigNumConstTime, (Bn));
+}
+
+/**
+  Calculate square modulo.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSqrMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumSqrMod, (BnA, BnM, BnRes), FALSE);
+}
+
+/**
+  Create new Big Number computation context. This is an opaque structure
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+VOID *
+EFIAPI
+BigNumNewContext (
+  VOID
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumNewContext, (), NULL);
+}
+
+/**
+  Free Big Number context that was allocated with BigNumNewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+VOID
+EFIAPI
+BigNumContextFree (
+  IN VOID  *BnCtx
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (BigNumContextFree, (BnCtx));
+}
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumSetUint (
+  IN VOID   *Bn,
+  IN UINTN  Val
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumSetUint, (Bn, Val), FALSE);
+}
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA       Big number.
+  @param[in]   BnB       Big number.
+  @param[in]   BnM       Big number (modulo).
+  @param[out]  BnRes     The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+BigNumAddMod (
+  IN CONST VOID  *BnA,
+  IN CONST VOID  *BnB,
+  IN CONST VOID  *BnM,
+  OUT VOID       *BnRes
+  )
+{
+  CALL_CRYPTO_SERVICE (BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
+}
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index c417568e96..ec3cba8e93 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -3486,6 +3486,407 @@ BOOLEAN
   IN       UINTN  CustomByteLen
   );
 
+// =====================================================================================
+//   Big Number Primitive
+// =====================================================================================
+
+/**
+  Allocate new Big Number.
+
+  @retval New BigNum opaque structure or NULL on failure.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_BIGNUM_INIT)(
+  VOID
+  );
+
+/**
+  Allocate new Big Number and assign the provided value to it.
+
+  @param[in]   Buf    Big endian encoded buffer.
+  @param[in]   Len    Buffer length.
+
+  @retval New EDKII_CRYPTO_BIGNUM_ opaque structure or NULL on failure.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_BIGNUM_FROM_BIN)(
+  IN CONST UINT8 *Buf,
+  IN UINTN Len
+  );
+
+/**
+  Convert the absolute value of Bn into big-endian form and store it at Buf.
+  The Buf array should have at least EDKII_CRYPTO_BIGNUM_Bytes() in it.
+
+  @param[in]   Bn     Big number to convert.
+  @param[out]  Buf    Output buffer.
+
+  @retval The length of the big-endian number placed at Buf or -1 on error.
+**/
+typedef
+INTN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_TO_BIN)(
+  IN CONST VOID *Bn,
+  OUT UINT8 *Buf
+  );
+
+/**
+  Free the Big Number.
+
+  @param[in]   Bn      Big number to free.
+  @param[in]   Clear   TRUE if the buffer should be cleared.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_BIGNUM_FREE)(
+  IN VOID *Bn,
+  IN BOOLEAN Clear
+  );
+
+/**
+  Calculate the sum of two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes    The result of BnA + BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_ADD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  OUT VOID *BnRes
+  );
+
+/**
+  Subtract two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes    The result of BnA - BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_SUB)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  OUT VOID *BnRes
+  );
+
+/**
+  Calculate remainder: BnRes = BnA % BnB.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes    The result of BnA % BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  OUT VOID *BnRes
+  );
+
+/**
+  Compute BnA to the BnP-th power modulo BnM.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnP     Big number (power).
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes    The result of BnA ^ BnP % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_EXP_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnP,
+  IN CONST VOID *BnM,
+  OUT VOID *BnRes
+  );
+
+/**
+  Compute BnA inverse modulo BnM.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnRes) % BnM == 1.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_INVERSE_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnM,
+  OUT VOID *BnRes
+  );
+
+/**
+  Divide two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[out]  BnRes   The result, such that BnA / BnB.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_DIV)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  OUT VOID *BnRes
+  );
+
+/**
+  Multiply two Big Numbers modulo BnM.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA * BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_MUL_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  IN CONST VOID *BnM,
+  OUT VOID *BnRes
+  );
+
+/**
+  Compare two Big Numbers.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+
+  @retval 0          BnA == BnB.
+  @retval 1          BnA > BnB.
+  @retval -1         BnA < BnB.
+**/
+typedef
+INTN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_CMP)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB
+  );
+
+/**
+  Get number of bits in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bits.
+**/
+typedef
+UINTN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_BITS)(
+  IN CONST VOID *Bn
+  );
+
+/**
+  Get number of bytes in Bn.
+
+  @param[in]   Bn     Big number.
+
+  @retval Number of bytes.
+**/
+typedef
+UINTN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_BYTES)(
+  IN CONST VOID *Bn
+  );
+
+/**
+  Checks if Big Number equals to the given Num.
+
+  @param[in]   Bn     Big number.
+  @param[in]   Num    Number.
+
+  @retval TRUE   iff Bn == Num.
+  @retval FALSE  otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_IS_WORD)(
+  IN CONST VOID *Bn,
+  IN UINTN Num
+  );
+
+/**
+  Checks if Big Number is odd.
+
+  @param[in]   Bn     Big number.
+
+  @retval TRUE   Bn is odd (Bn % 2 == 1).
+  @retval FALSE  otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_IS_ODD)(
+  IN CONST VOID *Bn
+  );
+
+/**
+  Copy Big number.
+
+  @param[out]  BnDst     Destination.
+  @param[in]   BnSrc     Source.
+
+  @retval BnDst on success.
+  @retval NULL otherwise.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_BIGNUM_COPY)(
+  OUT VOID *BnDst,
+  IN CONST VOID *BnSrc
+  );
+
+/**
+  Get constant Big number with value of "1".
+  This may be used to save expensive allocations.
+
+  @retval Big Number with value of 1.
+**/
+typedef
+CONST VOID *
+(EFIAPI *EDKII_CRYPTO_BIGNUM_VALUE_ONE)(
+  VOID
+  );
+
+/**
+  Shift right Big Number.
+  Please note, all "out" Big number arguments should be properly initialized
+  by calling to BigNumInit() or BigNumFromBin() functions.
+
+  @param[in]   Bn      Big number.
+  @param[in]   N       Number of bits to shift.
+  @param[out]  BnRes   The result.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_R_SHIFT)(
+  IN CONST VOID *Bn,
+  IN UINTN N,
+  OUT VOID *BnRes
+  );
+
+/**
+  Mark Big Number for constant time computations.
+  This function should be called before any constant time computations are
+  performed on the given Big number.
+
+  @param[in]   Bn     Big number.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_BIGNUM_CONST_TIME)(
+  IN VOID *Bn
+  );
+
+/**
+  Calculate square modulo.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA ^ 2) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_SQR_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnM,
+  OUT VOID *BnRes
+  );
+
+/**
+  Create new Big Number computation context. This is an opaque structure.
+  which should be passed to any function that requires it. The BN context is
+  needed to optimize calculations and expensive allocations.
+
+  @retval Big Number context struct or NULL on failure.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_BIGNUM_NEW_CONTEXT)(
+  VOID
+  );
+
+/**
+  Free Big Number context that was allocated with EDKII_CRYPTO_BIGNUM_NewContext().
+
+  @param[in]   BnCtx     Big number context to free.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_BIGNUM_CONTEXT_FREE)(
+  IN VOID *BnCtx
+  );
+
+/**
+  Set Big Number to a given value.
+
+  @param[in]   Bn     Big number to set.
+  @param[in]   Val    Value to set.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_SET_UINT)(
+  IN VOID *Bn,
+  IN UINTN Val
+  );
+
+/**
+  Add two Big Numbers modulo BnM.
+
+  @param[in]   BnA     Big number.
+  @param[in]   BnB     Big number.
+  @param[in]   BnM     Big number (modulo).
+  @param[out]  BnRes   The result, such that (BnA + BnB) % BnM.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_BIGNUM_ADD_MOD)(
+  IN CONST VOID *BnA,
+  IN CONST VOID *BnB,
+  IN CONST VOID *BnM,
+  OUT VOID *BnRes
+  );
+
 ///
 /// EDK II Crypto Protocol
 ///
@@ -3675,6 +4076,32 @@ struct _EDKII_CRYPTO_PROTOCOL {
   EDKII_CRYPTO_RSA_PSS_VERIFY                        RsaPssVerify;
   /// Parallel hash
   EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
+  /// Big Number
+  EDKII_CRYPTO_BIGNUM_INIT                           BigNumInit;
+  EDKII_CRYPTO_BIGNUM_FROM_BIN                       BigNumFromBin;
+  EDKII_CRYPTO_BIGNUM_TO_BIN                         BigNumToBin;
+  EDKII_CRYPTO_BIGNUM_FREE                           BigNumFree;
+  EDKII_CRYPTO_BIGNUM_ADD                            BigNumAdd;
+  EDKII_CRYPTO_BIGNUM_SUB                            BigNumSub;
+  EDKII_CRYPTO_BIGNUM_MOD                            BigNumMod;
+  EDKII_CRYPTO_BIGNUM_EXP_MOD                        BigNumExpMod;
+  EDKII_CRYPTO_BIGNUM_INVERSE_MOD                    BigNumInverseMod;
+  EDKII_CRYPTO_BIGNUM_DIV                            BigNumDiv;
+  EDKII_CRYPTO_BIGNUM_MUL_MOD                        BigNumMulMod;
+  EDKII_CRYPTO_BIGNUM_CMP                            BigNumCmp;
+  EDKII_CRYPTO_BIGNUM_BITS                           BigNumBits;
+  EDKII_CRYPTO_BIGNUM_BYTES                          BigNumBytes;
+  EDKII_CRYPTO_BIGNUM_IS_WORD                        BigNumIsWord;
+  EDKII_CRYPTO_BIGNUM_IS_ODD                         BigNumIsOdd;
+  EDKII_CRYPTO_BIGNUM_COPY                           BigNumCopy;
+  EDKII_CRYPTO_BIGNUM_VALUE_ONE                      BigNumValueOne;
+  EDKII_CRYPTO_BIGNUM_R_SHIFT                        BigNumRShift;
+  EDKII_CRYPTO_BIGNUM_CONST_TIME                     BigNumConstTime;
+  EDKII_CRYPTO_BIGNUM_SQR_MOD                        BigNumSqrMod;
+  EDKII_CRYPTO_BIGNUM_NEW_CONTEXT                    BigNumNewContext;
+  EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                   BigNumContextFree;
+  EDKII_CRYPTO_BIGNUM_SET_UINT                       BigNumSetUint;
+  EDKII_CRYPTO_BIGNUM_ADD_MOD                        BigNumAddMod;
 };
 
 extern GUID  gEdkiiCryptoProtocolGuid;
-- 
2.31.1.windows.1


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

* [PATCH 3/7] CryptoPkg: Add EC support
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
  2022-09-07  8:29 ` [PATCH 1/7] CryptoPkg: Add BigNum support yi1 li
  2022-09-07  8:29 ` [PATCH 2/7] CryptoPkg: Add BigNum API to DXE and protocol yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 4/7] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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

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

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

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


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

* [PATCH 4/7] CryptoPkg: Add EC APIs to DXE and protocol
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
                   ` (2 preceding siblings ...)
  2022-09-07  8:29 ` [PATCH 3/7] CryptoPkg: Add EC support yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 5/7] CryptoPkg/Test: Add unit test for CryptoBn yi1 li
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

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

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

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

Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/CryptoPkg.dsc                       |   1 +
 CryptoPkg/Driver/Crypto.c                     | 496 ++++++++++++++++++
 .../Pcd/PcdCryptoServiceFamilyEnable.h        |  25 +
 .../BaseCryptLibOnProtocolPpi/CryptLib.c      | 469 +++++++++++++++++
 CryptoPkg/Private/Protocol/Crypto.h           | 431 +++++++++++++++
 5 files changed, 1422 insertions(+)

diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index a766851728..4f6cece6ee 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -169,6 +169,7 @@
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsSet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsGet.Family                            | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Bn.Family                                | PCD_CRYPTO_SERVICE_ENABLE_FAMILY
+  gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Ec.Family                                | 0
 !endif
 
 !if $(CRYPTO_SERVICES) == MIN_PEI
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index 07150ad2f2..f7b9287218 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -5074,6 +5074,481 @@ CryptoServiceBigNumAddMod (
   return CALL_BASECRYPTLIB (Bn.Services.AddMod, BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
 }
 
+// =====================================================================================
+//    Basic Elliptic Curve Primitives
+// =====================================================================================
+
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success.
+  @retval NULL            On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcGroupInit (
+  IN UINTN  CryptoNid
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupInit, EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetCurve (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *BnPrime,
+  OUT VOID       *BnA,
+  OUT VOID       *BnB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupGetCurve, EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object.
+  @param[out] BnOrder   Group prime number.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGroupGetOrder (
+  IN VOID   *EcGroup,
+  OUT VOID  *BnOrder
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GroupGetOrder, EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+  Free previously allocated EC group object using EcGroupInit().
+
+  @param[in]  EcGroup   EC group object to free.
+**/
+VOID
+EFIAPI
+CryptoServiceEcGroupFree (
+  IN VOID  *EcGroup
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.GroupFree, EcGroupFree, (EcGroup));
+}
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit().
+
+  @retval EC Point object  On success.
+  @retval NULL             On failure.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcPointInit (
+  IN CONST VOID  *EcGroup
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointInit, EcPointInit, (EcGroup), NULL);
+}
+
+/**
+  Free previously allocated EC Point object using EcPointInit().
+
+  @param[in]  EcPoint   EC Point to free.
+  @param[in]  Clear     TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+CryptoServiceEcPointDeInit (
+  IN VOID     *EcPoint,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.PointDeInit, EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[out] BnX        X coordinate.
+  @param[out] BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointGetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  OUT VOID       *BnX,
+  OUT VOID       *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointGetAffineCoordinates, EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[in]  BnX        X coordinate.
+  @param[in]  BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN CONST VOID  *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointSetAffineCoordinates, EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB.
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point.
+  @param[in]  EcPointB         EC Point.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointAdd (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointAdd, EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point.
+  @param[in]  BnPScalar        P Scalar.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointMul (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPoint,
+  IN CONST VOID  *BnPScalar,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointMul, EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object.
+  @param[in,out] EcPoint   EC point to invert.
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointInvert (
+  IN CONST VOID  *EcGroup,
+  IN OUT VOID    *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointInvert, EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is on EC curve.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On curve.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsOnCurve (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointIsOnCurve, EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is at infinity.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+
+  @retval TRUE          At infinity.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointIsAtInfinity (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointIsAtInfinity, EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+  Check if EC points are equal.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPointA  EC point A.
+  @param[in]  EcPointB  EC point B.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          A == B.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointEqual (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointEqual, EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC Point.
+  @param[in]  BnX        X coordinate.
+  @param[in]  YBit       0 or 1 to identify which Y value is used.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcPointSetCompressedCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN UINT8       YBit,
+  IN VOID        *BnCtx
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.PointSetCompressedCoordinates, EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+// =====================================================================================
+//    Elliptic Curve Diffie Hellman Primitives
+// =====================================================================================
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+CryptoServiceEcNewByNid (
+  IN UINTN  Nid
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.NewByNid, EcNewByNid, (Nid), NULL);
+}
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+CryptoServiceEcFree (
+  IN  VOID  *EcContext
+  )
+{
+  CALL_VOID_BASECRYPTLIB (Ec.Services.Free, EcFree, (EcContext));
+}
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGenerateKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GenerateKey, EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGetPubKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.GetPubKey, EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcDhComputeKey (
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  )
+{
+  return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag ,Key, KeySize), FALSE);
+}
+
 const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   /// Version
   CryptoServiceGetCryptoVersion,
@@ -5306,4 +5781,25 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   CryptoServiceBigNumContextFree,
   CryptoServiceBigNumSetUint,
   CryptoServiceBigNumAddMod,
+  /// EC
+  CryptoServiceEcGroupInit,
+  CryptoServiceEcGroupGetCurve,
+  CryptoServiceEcGroupGetOrder,
+  CryptoServiceEcGroupFree,
+  CryptoServiceEcPointInit,
+  CryptoServiceEcPointDeInit,
+  CryptoServiceEcPointGetAffineCoordinates,
+  CryptoServiceEcPointSetAffineCoordinates,
+  CryptoServiceEcPointAdd,
+  CryptoServiceEcPointMul,
+  CryptoServiceEcPointInvert,
+  CryptoServiceEcPointIsOnCurve,
+  CryptoServiceEcPointIsAtInfinity,
+  CryptoServiceEcPointEqual,
+  CryptoServiceEcPointSetCompressedCoordinates,
+  CryptoServiceEcNewByNid,
+  CryptoServiceEcFree,
+  CryptoServiceEcGenerateKey,
+  CryptoServiceEcGetPubKey,
+  CryptoServiceEcDhComputeKey,
 };
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 1b3c9d8f52..65ea7807dc 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -331,6 +331,31 @@ typedef struct {
     } Services;
     UINT32    Family;
   } Bn;
+  union {
+    struct {
+      UINT8    GroupInit                     : 1;
+      UINT8    GroupGetCurve                 : 1;
+      UINT8    GroupGetOrder                 : 1;
+      UINT8    GroupFree                     : 1;
+      UINT8    PointInit                     : 1;
+      UINT8    PointDeInit                   : 1;
+      UINT8    PointGetAffineCoordinates     : 1;
+      UINT8    PointSetAffineCoordinates     : 1;
+      UINT8    PointAdd                      : 1;
+      UINT8    PointMul                      : 1;
+      UINT8    PointInvert                   : 1;
+      UINT8    PointIsOnCurve                : 1;
+      UINT8    PointIsAtInfinity             : 1;
+      UINT8    PointEqual                    : 1;
+      UINT8    PointSetCompressedCoordinates : 1;
+      UINT8    NewByNid                      : 1;
+      UINT8    Free                          : 1;
+      UINT8    GenerateKey                   : 1;
+      UINT8    GetPubKey                     : 1;
+      UINT8    DhComputeKey                  : 1;
+    } Services;
+    UINT32    Family;
+  } Ec;
 } PCD_CRYPTO_SERVICE_FAMILY_ENABLE;
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index c5d71b5269..3746c823d9 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -4104,3 +4104,472 @@ BigNumAddMod (
 {
   CALL_CRYPTO_SERVICE (BigNumAddMod, (BnA, BnB, BnM, BnRes), FALSE);
 }
+
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success.
+  @retval NULL            On failure.
+**/
+VOID *
+EFIAPI
+EcGroupInit (
+  IN UINTN  CryptoNid
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupInit, (CryptoNid), NULL);
+}
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetCurve (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *BnPrime,
+  OUT VOID       *BnA,
+  OUT VOID       *BnB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupGetCurve, (EcGroup, BnPrime, BnA, BnB, BnCtx), FALSE);
+}
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object.
+  @param[out] BnOrder   Group prime number.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcGroupGetOrder (
+  IN VOID   *EcGroup,
+  OUT VOID  *BnOrder
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGroupGetOrder, (EcGroup, BnOrder), FALSE);
+}
+
+/**
+  Free previously allocated EC group object using EcGroupInit().
+
+  @param[in]  EcGroup   EC group object to free.
+**/
+VOID
+EFIAPI
+EcGroupFree (
+  IN VOID  *EcGroup
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcGroupFree, (EcGroup));
+}
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit().
+
+  @retval EC Point object  On success.
+  @retval NULL             On failure.
+**/
+VOID *
+EFIAPI
+EcPointInit (
+  IN CONST VOID  *EcGroup
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointInit, (EcGroup), NULL);
+}
+
+/**
+  Free previously allocated EC Point object using EcPointInit().
+
+  @param[in]  EcPoint   EC Point to free.
+  @param[in]  Clear     TRUE iff the memory should be cleared.
+**/
+VOID
+EFIAPI
+EcPointDeInit (
+  IN VOID     *EcPoint,
+  IN BOOLEAN  Clear
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcPointDeInit, (EcPoint, Clear));
+}
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[out] BnX        X coordinate.
+  @param[out] BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointGetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  OUT VOID       *BnX,
+  OUT VOID       *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointGetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC point object.
+  @param[in]  BnX        X coordinate.
+  @param[in]  BnY        Y coordinate.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetAffineCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN CONST VOID  *BnY,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointSetAffineCoordinates, (EcGroup, EcPoint, BnX, BnY, BnCtx), FALSE);
+}
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point.
+  @param[in]  EcPointB         EC Point.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointAdd (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointAdd, (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar.
+
+  @param[in]  EcGroup          EC group object.
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point.
+  @param[in]  BnPScalar        P Scalar.
+  @param[in]  BnCtx            BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointMul (
+  IN CONST VOID  *EcGroup,
+  OUT VOID       *EcPointResult,
+  IN CONST VOID  *EcPoint,
+  IN CONST VOID  *BnPScalar,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointMul, (EcGroup, EcPointResult, EcPoint, BnPScalar, BnCtx), FALSE);
+}
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object.
+  @param[in,out] EcPoint   EC point to invert.
+  @param[in]     BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointInvert (
+  IN CONST VOID  *EcGroup,
+  IN OUT VOID    *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointInvert, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is on EC curve.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          On curve.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsOnCurve (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointIsOnCurve, (EcGroup, EcPoint, BnCtx), FALSE);
+}
+
+/**
+  Check if the supplied point is at infinity.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPoint   EC point to check.
+
+  @retval TRUE          At infinity.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointIsAtInfinity (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPoint
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointIsAtInfinity, (EcGroup, EcPoint), FALSE);
+}
+
+/**
+  Check if EC points are equal.
+
+  @param[in]  EcGroup   EC group object.
+  @param[in]  EcPointA  EC point A.
+  @param[in]  EcPointB  EC point B.
+  @param[in]  BnCtx     BN context, created with BigNumNewContext().
+
+  @retval TRUE          A == B.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointEqual (
+  IN CONST VOID  *EcGroup,
+  IN CONST VOID  *EcPointA,
+  IN CONST VOID  *EcPointB,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointEqual, (EcGroup, EcPointA, EcPointB, BnCtx), FALSE);
+}
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object.
+  @param[in]  EcPoint    EC Point.
+  @param[in]  BnX        X coordinate.
+  @param[in]  YBit       0 or 1 to identify which Y value is used.
+  @param[in]  BnCtx      BN context, created with BigNumNewContext().
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+BOOLEAN
+EFIAPI
+EcPointSetCompressedCoordinates (
+  IN CONST VOID  *EcGroup,
+  IN VOID        *EcPoint,
+  IN CONST VOID  *BnX,
+  IN UINT8       YBit,
+  IN VOID        *BnCtx
+  )
+{
+  CALL_CRYPTO_SERVICE (EcPointSetCompressedCoordinates, (EcGroup, EcPoint, BnX, YBit, BnCtx), FALSE);
+}
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+VOID *
+EFIAPI
+EcNewByNid (
+  IN UINTN  Nid
+  )
+{
+  CALL_CRYPTO_SERVICE (EcNewByNid, (Nid), NULL);
+}
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+VOID
+EFIAPI
+EcFree (
+  IN  VOID  *EcContext
+  )
+{
+  CALL_VOID_CRYPTO_SERVICE (EcFree, (EcContext));
+}
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to the buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcGenerateKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGenerateKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+BOOLEAN
+EFIAPI
+EcGetPubKey (
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcGetPubKey, (EcContext, PublicKey, PublicKeySize), FALSE);
+}
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+BOOLEAN
+EFIAPI
+EcDhComputeKey (
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  )
+{
+  CALL_CRYPTO_SERVICE (EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
+}
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index ec3cba8e93..84d9fbba32 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -3887,6 +3887,416 @@ BOOLEAN
   OUT VOID *BnRes
   );
 
+/**
+  Initialize new opaque EcGroup object. This object represents an EC curve and
+  and is used for calculation within this group. This object should be freed
+  using EcGroupFree() function.
+
+  @param[in]  CryptoNid   Identifying number for the ECC curve (Defined in
+                          BaseCryptLib.h).
+
+  @retval EcGroup object  On success
+  @retval NULL            On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_INIT)(
+  IN UINTN  CryptoNid
+  );
+
+/**
+  Get EC curve parameters. While elliptic curve equation is Y^2 mod P = (X^3 + AX + B) Mod P.
+  This function will set the provided Big Number objects  to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object.
+  @param[out] BnPrime    Group prime number.
+  @param[out] BnA        A coefficient.
+  @param[out] BnB        B coefficient.
+  @param[in]  BnCtx      BN context.
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_CURVE)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *BnPrime,
+  OUT VOID *BnA,
+  OUT VOID *BnB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Get EC group order.
+  This function will set the provided Big Number object to the corresponding
+  value. The caller needs to make sure that the "out" BigNumber parameter
+  is properly initialized.
+
+  @param[in]  EcGroup   EC group object
+  @param[out] BnOrder   Group prime number
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_GET_ORDER)(
+  IN VOID *EcGroup,
+  OUT VOID *BnOrder
+  );
+
+/**
+  Free previously allocated EC group object using EcGroupInit()
+
+  @param[in]  EcGroup   EC group object to free
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_GROUP_FREE)(
+  IN VOID *EcGroup
+  );
+
+/**
+  Initialize new opaque EC Point object. This object represents an EC point
+  within the given EC group (curve).
+
+  @param[in]  EC Group, properly initialized using EcGroupInit()
+
+  @retval EC Point object  On success
+  @retval NULL             On failure
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INIT)(
+  IN CONST VOID *EcGroup
+  );
+
+/**
+  Free previously allocated EC Point object using EcPointInit()
+
+  @param[in]  EcPoint   EC Point to free
+  @param[in]  Clear     TRUE iff the memory should be cleared
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_POINT_DE_INIT)(
+  IN VOID *EcPoint,
+  IN BOOLEAN Clear
+  );
+
+/**
+  Get EC point affine (x,y) coordinates.
+  This function will set the provided Big Number objects to the corresponding
+  values. The caller needs to make sure all the "out" BigNumber parameters
+  are properly initialized.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC point object
+  @param[out] BnX        X coordinate
+  @param[out] BnY        Y coordinate
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint,
+  OUT VOID *BnX,
+  OUT VOID *BnY,
+  IN VOID *BnCtx
+  );
+
+/**
+  Set EC point affine (x,y) coordinates.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC point object
+  @param[in]  BnX        X coordinate
+  @param[in]  BnY        Y coordinate
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN VOID *EcPoint,
+  IN CONST VOID *BnX,
+  IN CONST VOID *BnY,
+  IN VOID *BnCtx
+  );
+
+/**
+  EC Point addition. EcPointResult = EcPointA + EcPointB
+
+  @param[in]  EcGroup          EC group object
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPointA         EC Point
+  @param[in]  EcPointB         EC Point
+  @param[in]  BnCtx            BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_ADD)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *EcPointResult,
+  IN CONST VOID *EcPointA,
+  IN CONST VOID *EcPointB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Variable EC point multiplication. EcPointResult = EcPoint * BnPScalar
+
+  @param[in]  EcGroup          EC group object
+  @param[out] EcPointResult    EC point to hold the result. The point should
+                               be properly initialized.
+  @param[in]  EcPoint          EC Point
+  @param[in]  BnPScalar        P Scalar
+  @param[in]  BnCtx            BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_MUL)(
+  IN CONST VOID *EcGroup,
+  OUT VOID *EcPointResult,
+  IN CONST VOID *EcPoint,
+  IN CONST VOID *BnPScalar,
+  IN VOID *BnCtx
+  );
+
+/**
+  Calculate the inverse of the supplied EC point.
+
+  @param[in]     EcGroup   EC group object
+  @param[in,out] EcPoint   EC point to invert
+  @param[in]     BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_INVERT)(
+  IN CONST VOID *EcGroup,
+  IN OUT VOID *EcPoint,
+  IN VOID *BnCtx
+  );
+
+/**
+  Check if the supplied point is on EC curve
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPoint   EC point to check
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE           On curve
+  @retval FALSE          Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_ON_CURVE)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint,
+  IN VOID *BnCtx
+  );
+
+/**
+  Check if the supplied point is at infinity
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPoint   EC point to check
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          At infinity
+  @retval FALSE         Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPoint
+  );
+
+/**
+  Check if EC points are equal
+
+  @param[in]  EcGroup   EC group object
+  @param[in]  EcPointA  EC point A
+  @param[in]  EcPointB  EC point B
+  @param[in]  BnCtx     BN context, created with BigNumNewContext()
+
+  @retval TRUE          A == B
+  @retval FALSE         Otherwise
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_EQUAL)(
+  IN CONST VOID *EcGroup,
+  IN CONST VOID *EcPointA,
+  IN CONST VOID *EcPointB,
+  IN VOID *BnCtx
+  );
+
+/**
+  Set EC point compressed coordinates. Points can be described in terms of
+  their compressed coordinates. For a point (x, y), for any given value for x
+  such that the point is on the curve there will only ever be two possible
+  values for y. Therefore, a point can be set using this function where BnX is
+  the x coordinate and YBit is a value 0 or 1 to identify which of the two
+  possible values for y should be used.
+
+  @param[in]  EcGroup    EC group object
+  @param[in]  EcPoint    EC Point
+  @param[in]  BnX        X coordinate
+  @param[in]  YBit       0 or 1 to identify which Y value is used
+  @param[in]  BnCtx      BN context, created with BigNumNewContext()
+
+  @retval TRUE          On success.
+  @retval FALSE         Otherwise.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES)(
+  IN CONST VOID *EcGroup,
+  IN VOID *EcPoint,
+  IN CONST VOID *BnX,
+  IN UINT8 YBit,
+  IN VOID *BnCtx
+  );
+
+/**
+  Allocates and Initializes one Elliptic Curve Context for subsequent use
+  with the NID.
+
+  @param[in]  Nid cipher NID
+  @return     Pointer to the Elliptic Curve Context that has been initialized.
+              If the allocations fails, EcNewByNid() returns NULL.
+**/
+typedef
+VOID *
+(EFIAPI *EDKII_CRYPTO_EC_NEW_BY_NID)(
+  IN UINTN  Nid
+  );
+
+/**
+  Release the specified EC context.
+
+  @param[in]  EcContext  Pointer to the EC context to be released.
+**/
+typedef
+VOID
+(EFIAPI *EDKII_CRYPTO_EC_FREE)(
+  IN  VOID  *EcContext
+  );
+
+/**
+  Generates EC key and returns EC public key (X, Y), Please note, this function uses
+  pseudo random number generator. The caller must make sure RandomSeed()
+  function was properly called before.
+  The Ec context should be correctly initialized by EcNewByNid.
+  This function generates random secret, and computes the public key (X, Y), which is
+  returned via parameter Public, PublicSize.
+  X is the first half of Public with size being PublicSize / 2,
+  Y is the second half of Public with size being PublicSize / 2.
+  EC context is updated accordingly.
+  If the Public buffer is too small to hold the public X, Y, FALSE is returned and
+  PublicSize is set to the required buffer size to obtain the public X, Y.
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  If EcContext is NULL, then return FALSE.
+  If PublicSize is NULL, then return FALSE.
+  If PublicSize is large enough but Public is NULL, then return FALSE.
+  @param[in, out]  EcContext      Pointer to the EC context.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval TRUE   EC public X,Y generation succeeded.
+  @retval FALSE  EC public X,Y generation failed.
+  @retval FALSE  PublicKeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GENERATE_KEY)(
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  );
+
+/**
+  Gets the public key component from the established EC context.
+  The Ec context should be correctly initialized by EcNewByNid, and successfully
+  generate key pair from EcGenerateKey().
+  For P-256, the PublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext      Pointer to EC context being set.
+  @param[out]      PublicKey      Pointer to t buffer to receive generated public X,Y.
+  @param[in, out]  PublicKeySize  On input, the size of Public buffer in bytes.
+                                  On output, the size of data returned in Public buffer in bytes.
+  @retval  TRUE   EC key component was retrieved successfully.
+  @retval  FALSE  Invalid EC key component.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GET_PUB_KEY)(
+  IN OUT  VOID   *EcContext,
+  OUT     UINT8  *PublicKey,
+  IN OUT  UINTN  *PublicKeySize
+  );
+
+/**
+  Computes exchanged common key.
+  Given peer's public key (X, Y), this function computes the exchanged common key,
+  based on its own context including value of curve parameter and random secret.
+  X is the first half of PeerPublic with size being PeerPublicSize / 2,
+  Y is the second half of PeerPublic with size being PeerPublicSize / 2.
+  If EcContext is NULL, then return FALSE.
+  If PeerPublic is NULL, then return FALSE.
+  If PeerPublicSize is 0, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeySize is not large enough, then return FALSE.
+  For P-256, the PeerPublicSize is 64. First 32-byte is X, Second 32-byte is Y.
+  For P-384, the PeerPublicSize is 96. First 48-byte is X, Second 48-byte is Y.
+  For P-521, the PeerPublicSize is 132. First 66-byte is X, Second 66-byte is Y.
+  @param[in, out]  EcContext          Pointer to the EC context.
+  @param[in]       PeerPublic         Pointer to the peer's public X,Y.
+  @param[in]       PeerPublicSize     Size of peer's public X,Y in bytes.
+  @param[in]       CompressFlag       Flag of PeerPublic is compressed or not.
+  @param[out]      Key                Pointer to the buffer to receive generated key.
+  @param[in, out]  KeySize            On input, the size of Key buffer in bytes.
+                                      On output, the size of data returned in Key buffer in bytes.
+  @retval TRUE   EC exchanged key generation succeeded.
+  @retval FALSE  EC exchanged key generation failed.
+  @retval FALSE  KeySize is not large enough.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_DH_COMPUTE_KEY)(
+  IN OUT  VOID         *EcContext,
+  IN      CONST UINT8  *PeerPublic,
+  IN      UINTN        PeerPublicSize,
+  IN      CONST INT32  *CompressFlag,
+  OUT     UINT8        *Key,
+  IN OUT  UINTN        *KeySize
+  );
+
 ///
 /// EDK II Crypto Protocol
 ///
@@ -4102,6 +4512,27 @@ struct _EDKII_CRYPTO_PROTOCOL {
   EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                   BigNumContextFree;
   EDKII_CRYPTO_BIGNUM_SET_UINT                       BigNumSetUint;
   EDKII_CRYPTO_BIGNUM_ADD_MOD                        BigNumAddMod;
+  /// EC
+  EDKII_CRYPTO_EC_GROUP_INIT                          EcGroupInit;
+  EDKII_CRYPTO_EC_GROUP_GET_CURVE                     EcGroupGetCurve;
+  EDKII_CRYPTO_EC_GROUP_GET_ORDER                     EcGroupGetOrder;
+  EDKII_CRYPTO_EC_GROUP_FREE                          EcGroupFree;
+  EDKII_CRYPTO_EC_POINT_INIT                          EcPointInit;
+  EDKII_CRYPTO_EC_POINT_DE_INIT                       EcPointDeInit;
+  EDKII_CRYPTO_EC_POINT_GET_AFFINE_COORDINATES        EcPointGetAffineCoordinates;
+  EDKII_CRYPTO_EC_POINT_SET_AFFINE_COORDINATES        EcPointSetAffineCoordinates;
+  EDKII_CRYPTO_EC_POINT_ADD                           EcPointAdd;
+  EDKII_CRYPTO_EC_POINT_MUL                           EcPointMul;
+  EDKII_CRYPTO_EC_POINT_INVERT                        EcPointInvert;
+  EDKII_CRYPTO_EC_POINT_IS_ON_CURVE                   EcPointIsOnCurve;
+  EDKII_CRYPTO_EC_POINT_IS_AT_INFINITY                EcPointIsAtInfinity;
+  EDKII_CRYPTO_EC_POINT_EQUAL                         EcPointEqual;
+  EDKII_CRYPTO_EC_POINT_SET_COMPRESSED_COORDINATES    EcPointSetCompressedCoordinates;
+  EDKII_CRYPTO_EC_NEW_BY_NID                          EcNewByNid;
+  EDKII_CRYPTO_EC_FREE                                EcFree;
+  EDKII_CRYPTO_EC_GENERATE_KEY                        EcGenerateKey;
+  EDKII_CRYPTO_EC_GET_PUB_KEY                         EcGetPubKey;
+  EDKII_CRYPTO_EC_DH_COMPUTE_KEY                      EcDhComputeKey;
 };
 
 extern GUID  gEdkiiCryptoProtocolGuid;
-- 
2.31.1.windows.1


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

* [PATCH 5/7] CryptoPkg/Test: Add unit test for CryptoBn
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
                   ` (3 preceding siblings ...)
  2022-09-07  8:29 ` [PATCH 4/7] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 6/7] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

Add unit test for CryptoBn.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
 .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |   1 +
 .../BaseCryptLib/BaseCryptLibUnitTests.c      |   1 +
 .../UnitTest/Library/BaseCryptLib/BnTests.c   | 257 ++++++++++++++++++
 .../Library/BaseCryptLib/TestBaseCryptLib.h   |   3 +
 .../BaseCryptLib/TestBaseCryptLibHost.inf     |   1 +
 .../BaseCryptLib/TestBaseCryptLibShell.inf    |   1 +
 6 files changed, 264 insertions(+)
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c

diff --git a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
index 11ff1c6931..cf8810e598 100644
--- a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
@@ -46,6 +46,7 @@
   Pem/CryptPem.c
   Pk/CryptRsaPss.c
   Pk/CryptRsaPssSign.c
+  Bn/CryptBn.c
 
   SysCall/UnitTestHostCrtWrapper.c
 
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
index 3c57aead1e..792006a194 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
@@ -25,6 +25,7 @@ SUITE_DESC  mSuiteDesc[] = {
   { "DH verify tests",             "CryptoPkg.BaseCryptLib", NULL, NULL, &mDhTestNum,             mDhTest             },
   { "PRNG verify tests",           "CryptoPkg.BaseCryptLib", NULL, NULL, &mPrngTestNum,           mPrngTest           },
   { "OAEP encrypt verify tests",   "CryptoPkg.BaseCryptLib", NULL, NULL, &mOaepTestNum,           mOaepTest           },
+  { "Bn verify tests",             "CryptoPkg.BaseCryptLib", NULL, NULL, &mBnTestNum,             mBnTest             },
 };
 
 EFI_STATUS
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
new file mode 100644
index 0000000000..df91752c9c
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
@@ -0,0 +1,257 @@
+/** @file
+  Application for BigNumber Primitives Validation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Debug data
+//
+#define MAX_TEST_DATA_SIZE  512
+#define BYTES_OF_OPERATION_A  60
+#define BITS_OF_OPERATION_A  480 //(8 * 60)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationA[] = {
+  0x00, 0x00, 0x00, 0x00, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+  0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+  0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+  0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationB[] = {
+  0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
+  0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+  0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+  0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationC[] = {
+  0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationExp[] = {
+  0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationMod[] = {
+  0x48, 0xbe, 0xcb, 0xd5, 0x36, 0x2e, 0x93, 0x0b, 0x51, 0x45, 0x9c, 0x7d, 0xe7, 0xfe, 0x47, 0xaa,
+  0xc5, 0xd3, 0x4b, 0x4f, 0x06, 0x24, 0xb4, 0x31, 0x83, 0x55, 0xb5, 0xf0, 0xda, 0x14, 0xca, 0x46
+};
+
+// BnOperationA + BnOperationB
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultSum[] = {
+  0xb0, 0x03, 0x61, 0xa4, 0x29, 0x78, 0xf5, 0x57, 0x80, 0x52, 0x72, 0xab, 0xa0, 0x20, 0x56, 0xde,
+  0xdd, 0xe7, 0x6f, 0x8d, 0xcf, 0x4c, 0xdd, 0x2d, 0xc0, 0x3f, 0x2c, 0x4f, 0xe6, 0x1c, 0x23, 0xa1,
+  0x48, 0xbe, 0xcb, 0xd5, 0x36, 0x2e, 0x93, 0x0b, 0x51, 0x45, 0x9c, 0x7d, 0xe7, 0xfe, 0x47, 0xaa,
+  0xc5, 0xd3, 0x4b, 0x4f, 0x06, 0x24, 0xb4, 0x31, 0x83, 0x55, 0xb5, 0xf0, 0xda, 0x14, 0xca, 0x46
+};
+
+// (BnOperationA + BnOperationC) % BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultSumMod[] =  {
+  0x16, 0x0a, 0xcf, 0x78, 0x20, 0xac, 0x31, 0x53, 0xd9, 0x0f, 0x22, 0xfc, 0x08, 0x8d, 0xde, 0x0d,
+  0x29, 0xf4, 0x07, 0xdd, 0xfa, 0xf5, 0x61, 0xd4, 0x1a, 0xe5, 0xa1, 0xef, 0x4a, 0x37, 0xfe, 0xec
+};
+
+// (BnOperationA * BnOperationC) % BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultMulMod[] =  {
+  0x01, 0xDB, 0xD2, 0x82, 0xC9, 0x24, 0x66, 0x2A, 0x96, 0x05, 0x11, 0xF2, 0x31, 0xF0, 0xCB, 0x28,
+  0xBA, 0x5C, 0xBE, 0x7D, 0xEE, 0x37, 0x25, 0xB1, 0x24, 0x7E, 0x15, 0xAB, 0xCD, 0x86, 0x8E, 0x39
+};
+
+// BnOperationA / BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultDiv[] =  {
+  0x02, 0x06, 0xA6, 0xDC, 0x2E, 0x97, 0x05, 0xEA, 0xCD, 0xF7, 0xAB, 0xCD, 0xE5, 0x9C, 0x33, 0x03,
+  0xCE, 0x3D, 0x7E, 0x63, 0x23, 0xB2, 0xEC, 0xED, 0x96, 0x9D, 0xC9, 0xBB, 0x78
+};
+
+// BnOperationA % BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultMod[] =  {
+  0x06, 0x2A, 0x8D, 0x06, 0x9D, 0x14, 0x53, 0x3B, 0x05, 0xD9, 0x86, 0x00, 0xA5, 0xB9, 0x05, 0x7F,
+  0xC1, 0x82, 0xEC, 0x23, 0x44, 0x23, 0xC8, 0xA2, 0x42, 0xB3, 0x43, 0xB8, 0x7C, 0xD6, 0xB1, 0xCF
+};
+
+// BnOperationA % BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultInverseMod[] =  {
+  0x3a, 0xeb, 0xc5, 0x98, 0x9c, 0x22, 0xd6, 0x76, 0x7d, 0x1c, 0xc6, 0xd6, 0xbb, 0x1b, 0xed, 0xfd,
+  0x0f, 0x34, 0xbf, 0xe0, 0x2b, 0x4a, 0x26, 0xc3, 0xc0, 0xd9, 0x57, 0xc7, 0x11, 0xc0, 0xd6, 0x35
+};
+
+// BnOperationA % BnOperationMod
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultExpMod[] =  {
+  0x39, 0xf8, 0x74, 0xa0, 0xe8, 0x02, 0x8b, 0xf2, 0x22, 0x62, 0x82, 0x4c, 0xe0, 0xed, 0x63, 0x48,
+  0xb9, 0xa2, 0xaa, 0xbc, 0xba, 0xb1, 0xd3, 0x6a, 0x02, 0xfd, 0xf3, 0x0e, 0x3a, 0x19, 0x39, 0x37
+};
+
+// BnOperationA >> 128
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultRShift[] =  {
+                          0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+  0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+  0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd
+};
+
+// 0x12345678
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultUIntSet[] =  {0x12, 0x34, 0x56, 0x78};
+
+typedef struct {
+  VOID *BnA;
+  VOID *BnB;
+  VOID *BnC;
+  VOID *BnD;
+  VOID *BnCTX;
+} BN_TEST_CONTEXT;
+
+GLOBAL_REMOVE_IF_UNREFERENCED STATIC BN_TEST_CONTEXT mBnContext = {NULL, NULL, NULL, NULL, NULL};
+
+//
+// Debug function
+//
+STATIC
+BOOLEAN
+EqualBn2Bn (
+  CONST VOID *Expected, CONST VOID *Actual
+  )
+{
+    if (BigNumCmp(Expected, Actual) == 0)
+        return TRUE;
+    return FALSE;
+}
+
+STATIC
+BOOLEAN
+EqualBn2Bin (
+  CONST VOID *Bn, CONST UINT8 *Buffer, CONST UINTN BufferSize
+  )
+{
+  UINTN  BnTestBufferSize;
+  UINT8  BnTestBuffer[MAX_TEST_DATA_SIZE];
+
+  BnTestBufferSize = BigNumToBin (Bn, BnTestBuffer);
+  if (BnTestBufferSize == BufferSize) {
+    if (CompareMem (Buffer, BnTestBuffer, BnTestBufferSize) == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyBnPreReq (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  BN_TEST_CONTEXT *BnContext;
+
+  BnContext = Context;
+  BnContext->BnCTX = BigNumNewContext();
+  BnContext->BnA = BigNumInit();
+  BnContext->BnB = BigNumInit();
+  BnContext->BnC = BigNumInit();
+  BnContext->BnD = BigNumInit();
+  if (BnContext->BnCTX == NULL
+        || BnContext->BnA == NULL
+        || BnContext->BnB == NULL
+        || BnContext->BnC == NULL
+        || BnContext->BnD == NULL
+        ) {
+    return UNIT_TEST_ERROR_TEST_FAILED;
+  }
+  return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyBnCleanUp (
+  UNIT_TEST_CONTEXT  Context
+  )
+{
+  BN_TEST_CONTEXT *BnContext;
+
+  BnContext = Context;
+  BigNumContextFree (BnContext->BnCTX);
+  BigNumFree (BnContext->BnA, TRUE);
+  BigNumFree (BnContext->BnB, TRUE);
+  BigNumFree (BnContext->BnC, TRUE);
+  BigNumFree (BnContext->BnD, TRUE);
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyBn (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  BN_TEST_CONTEXT *BnContext;
+  UINTN Num;
+  CONST VOID *BnOne;
+
+  BnContext = Context;
+
+  // Calculation tests
+  BnContext->BnA = BigNumFromBin (BnOperationA, sizeof (BnOperationA));
+  BnContext->BnB = BigNumFromBin (BnOperationB, sizeof (BnOperationB));
+  //C=A+B
+  BigNumAdd (BnContext->BnA, BnContext->BnB, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultSum, sizeof (BnResultSum)));
+  //D=C-A=B
+  BigNumSub (BnContext->BnC, BnContext->BnA, BnContext->BnD);
+  UT_ASSERT_TRUE (EqualBn2Bn (BnContext->BnB, BnContext->BnD));
+  //C=(A+B)%D
+  BnContext->BnD = BigNumFromBin (BnOperationMod, sizeof (BnOperationMod));
+  BigNumAddMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultSumMod, sizeof (BnResultSumMod)));
+  //C=(A*B)%D
+  BigNumMulMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultMulMod, sizeof (BnResultMulMod)));
+  //C=A/D
+  BigNumDiv (BnContext->BnA, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultDiv, sizeof (BnResultDiv)));
+  //C=A%D
+  BigNumMod (BnContext->BnA, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultMod, sizeof (BnResultMod)));
+  //1=(A*C)%D
+  BigNumInverseMod (BnContext->BnA, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultInverseMod, sizeof (BnResultInverseMod)));
+  //C=(A^B)%D
+  BnContext->BnB = BigNumFromBin (BnOperationExp, sizeof (BnOperationExp));
+  BigNumExpMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultExpMod, sizeof (BnResultExpMod)));
+  //C=A>>128
+  BigNumRShift (BnContext->BnA, 128, BnContext->BnC);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultRShift, sizeof (BnResultRShift)));
+  //C=0x12345678
+  BigNumSetUint (BnContext->BnC, 0x12345678);
+  UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultUIntSet, sizeof (BnResultUIntSet)));
+  //Bn compare
+  UT_ASSERT_TRUE (BigNumIsWord (BnContext->BnC, 0x12345678));
+  UT_ASSERT_FALSE (BigNumIsWord (BnContext->BnC, 0x12345600));
+  UT_ASSERT_FALSE (BigNumIsOdd (BnContext->BnC));
+  UT_ASSERT_TRUE (BigNumIsOdd (BnContext->BnA));
+
+  //Other tests
+  BigNumConstTime (BnContext->BnA);
+  Num = BigNumBytes (BnContext->BnA);
+  UT_ASSERT_EQUAL (Num, BYTES_OF_OPERATION_A);
+  Num = BigNumBits (BnContext->BnA);
+  UT_ASSERT_EQUAL (Num, BITS_OF_OPERATION_A);
+  BnOne = BigNumValueOne();
+  if (BnOne == NULL) {
+    return UNIT_TEST_ERROR_TEST_FAILED;
+  }
+  UT_ASSERT_TRUE (BigNumIsWord (BnOne, 0x1));
+
+  return UNIT_TEST_PASSED;
+}
+
+TEST_DESC  mBnTest[] = {
+  //
+  // -----Description----------------Class---------------------Function-----------Pre----------------Post---------Context
+  //
+  { "TestVerifyBn()",   "CryptoPkg.BaseCryptLib.BigNumber", TestVerifyBn, TestVerifyBnPreReq, TestVerifyBnCleanUp, &mBnContext   },
+};
+
+UINTN  mBnTestNum = ARRAY_SIZE(mBnTest);
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
index a6b3482742..b8f0fdfd89 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -86,6 +86,9 @@ extern TEST_DESC  mOaepTest[];
 extern UINTN      mRsaPssTestNum;
 extern TEST_DESC  mRsaPssTest[];
 
+extern UINTN      mBnTestNum;
+extern TEST_DESC  mBnTest[];
+
 /** Creates a framework you can use */
 EFI_STATUS
 EFIAPI
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
index 399db596c2..1301345a13 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -37,6 +37,7 @@
   OaepEncryptTests.c
   RsaPssTests.c
   ParallelhashTests.c
+  BnTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
index ca789aa6ad..9a41dbc317 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -36,6 +36,7 @@
   Pkcs7EkuTests.c
   OaepEncryptTests.c
   RsaPssTests.c
+  BnTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.31.1.windows.1


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

* [PATCH 6/7] CryptoPkg/Test: Add unit test for CryptoEc
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
                   ` (4 preceding siblings ...)
  2022-09-07  8:29 ` [PATCH 5/7] CryptoPkg/Test: Add unit test for CryptoBn yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-07  8:29 ` [PATCH 7/7] CryptoPkg: Run uncrustify tools on EC and BN change yi1 li
  2022-09-20 16:01 ` [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib Yao, Jiewen
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

Add unit test for CryptoEc.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
 .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |   2 +
 CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |   3 +
 .../BaseCryptLib/BaseCryptLibUnitTests.c      |   1 +
 .../UnitTest/Library/BaseCryptLib/EcTests.c   | 289 ++++++++++++++++++
 .../Library/BaseCryptLib/TestBaseCryptLib.h   |   2 +
 .../BaseCryptLib/TestBaseCryptLibHost.inf     |   1 +
 .../BaseCryptLib/TestBaseCryptLibShell.inf    |   1 +
 7 files changed, 299 insertions(+)
 create mode 100644 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c

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


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

* [PATCH 7/7] CryptoPkg: Run uncrustify tools on EC and BN change
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
                   ` (5 preceding siblings ...)
  2022-09-07  8:29 ` [PATCH 6/7] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
@ 2022-09-07  8:29 ` yi1 li
  2022-09-20 16:01 ` [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib Yao, Jiewen
  7 siblings, 0 replies; 11+ messages in thread
From: yi1 li @ 2022-09-07  8:29 UTC (permalink / raw)
  To: devel; +Cc: Yi Li, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang

Run uncrustify tools on EC and BN change to meet UEFI code style.

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

Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/Driver/Crypto.c                     |   2 +-
 CryptoPkg/Include/Library/BaseCryptLib.h      |   8 +-
 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   |  54 +--
 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   | 156 ++++----
 CryptoPkg/Private/Protocol/Crypto.h           | 368 +++++++++---------
 .../UnitTest/Library/BaseCryptLib/BnTests.c   | 109 +++---
 .../UnitTest/Library/BaseCryptLib/EcTests.c   |  93 ++---
 7 files changed, 405 insertions(+), 385 deletions(-)

diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index f7b9287218..9682a46778 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -5546,7 +5546,7 @@ CryptoServiceEcDhComputeKey (
   IN OUT  UINTN        *KeySize
   )
 {
-  return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag ,Key, KeySize), FALSE);
+  return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
 }
 
 const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index ea3ed5270f..d74fc21c1e 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -14,12 +14,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <Uefi/UefiBaseType.h>
 
-#define CRYPTO_NID_NULL        0x0000
+#define CRYPTO_NID_NULL  0x0000
 
 // Key Exchange
-#define CRYPTO_NID_SECP256R1           0x0204
-#define CRYPTO_NID_SECP384R1           0x0205
-#define CRYPTO_NID_SECP521R1           0x0206
+#define CRYPTO_NID_SECP256R1  0x0204
+#define CRYPTO_NID_SECP384R1  0x0205
+#define CRYPTO_NID_SECP521R1  0x0206
 
 ///
 /// MD5 digest size in bytes
diff --git a/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
index 7a3043b1de..282926ddcc 100644
--- a/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
+++ b/CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
@@ -99,7 +99,7 @@ BigNumAdd (
   OUT VOID       *BnRes
   )
 {
-  return (BOOLEAN) BN_add (BnRes, BnA, BnB);
+  return (BOOLEAN)BN_add (BnRes, BnA, BnB);
 }
 
 /**
@@ -122,7 +122,7 @@ BigNumSub (
   OUT VOID       *BnRes
   )
 {
-  return (BOOLEAN) BN_sub (BnRes, BnA, BnB);
+  return (BOOLEAN)BN_sub (BnRes, BnA, BnB);
 }
 
 /**
@@ -145,15 +145,15 @@ BigNumMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_mod (BnRes, BnA, BnB, Ctx);
+  RetVal = (BOOLEAN)BN_mod (BnRes, BnA, BnB, Ctx);
   BN_CTX_free (Ctx);
 
   return RetVal;
@@ -181,15 +181,15 @@ BigNumExpMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_mod_exp (BnRes, BnA, BnP, BnM, Ctx);
+  RetVal = (BOOLEAN)BN_mod_exp (BnRes, BnA, BnP, BnM, Ctx);
 
   BN_CTX_free (Ctx);
   return RetVal;
@@ -215,8 +215,8 @@ BigNumInverseMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
@@ -226,7 +226,7 @@ BigNumInverseMod (
   RetVal = FALSE;
   if (BN_mod_inverse (BnRes, BnA, BnM, Ctx) != NULL) {
     RetVal = TRUE;
-  };
+  }
 
   BN_CTX_free (Ctx);
   return RetVal;
@@ -252,15 +252,15 @@ BigNumDiv (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_div (BnRes, NULL, BnA, BnB, Ctx);
+  RetVal = (BOOLEAN)BN_div (BnRes, NULL, BnA, BnB, Ctx);
   BN_CTX_free (Ctx);
 
   return RetVal;
@@ -288,15 +288,15 @@ BigNumMulMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_mod_mul (BnRes, BnA, BnB, BnM, Ctx);
+  RetVal = (BOOLEAN)BN_mod_mul (BnRes, BnA, BnB, BnM, Ctx);
   BN_CTX_free (Ctx);
 
   return RetVal;
@@ -370,7 +370,7 @@ BigNumIsWord (
   IN UINTN       Num
   )
 {
-  return (BOOLEAN) BN_is_word (Bn, Num);
+  return (BOOLEAN)BN_is_word (Bn, Num);
 }
 
 /**
@@ -387,7 +387,7 @@ BigNumIsOdd (
   IN CONST VOID  *Bn
   )
 {
-  return (BOOLEAN) BN_is_odd (Bn);
+  return (BOOLEAN)BN_is_odd (Bn);
 }
 
 /**
@@ -444,7 +444,7 @@ BigNumRShift (
   OUT VOID       *BnRes
   )
 {
-  return (BOOLEAN) BN_rshift (BnRes, Bn, (INT32) N);
+  return (BOOLEAN)BN_rshift (BnRes, Bn, (INT32)N);
 }
 
 /**
@@ -483,15 +483,15 @@ BigNumSqrMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_mod_sqr (BnRes, BnA, BnM, Ctx);
+  RetVal = (BOOLEAN)BN_mod_sqr (BnRes, BnA, BnM, Ctx);
   BN_CTX_free (Ctx);
 
   return RetVal;
@@ -543,7 +543,7 @@ BigNumSetUint (
   IN UINTN  Val
   )
 {
-  return (BOOLEAN) BN_set_word (Bn, Val);
+  return (BOOLEAN)BN_set_word (Bn, Val);
 }
 
 /**
@@ -566,15 +566,15 @@ BigNumAddMod (
   OUT VOID       *BnRes
   )
 {
-  BOOLEAN RetVal;
-  BN_CTX  *Ctx;
+  BOOLEAN  RetVal;
+  BN_CTX   *Ctx;
 
   Ctx = BN_CTX_new ();
   if (Ctx == NULL) {
     return FALSE;
   }
 
-  RetVal = (BOOLEAN) BN_mod_add (BnRes, BnA, BnB, BnM, Ctx);
+  RetVal = (BOOLEAN)BN_mod_add (BnRes, BnA, BnB, BnM, Ctx);
   BN_CTX_free (Ctx);
 
   return RetVal;
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
index e9b0391a56..396c819834 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
@@ -27,8 +27,8 @@
 STATIC
 INT32
 CryptoNidToOpensslNid (
-  IN UINTN CryptoNid
-)
+  IN UINTN  CryptoNid
+  )
 {
   INT32  Nid;
 
@@ -102,7 +102,7 @@ EcGroupGetCurve (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
+  return (BOOLEAN)EC_GROUP_get_curve (EcGroup, BnPrime, BnA, BnB, BnCtx);
 }
 
 /**
@@ -124,7 +124,7 @@ EcGroupGetOrder (
   OUT VOID  *BnOrder
   )
 {
-  return (BOOLEAN) EC_GROUP_get_order (EcGroup, BnOrder, NULL);
+  return (BOOLEAN)EC_GROUP_get_order (EcGroup, BnOrder, NULL);
 }
 
 /**
@@ -204,7 +204,7 @@ EcPointGetAffineCoordinates (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
+  return (BOOLEAN)EC_POINT_get_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
 }
 
 /**
@@ -229,7 +229,7 @@ EcPointSetAffineCoordinates (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
+  return (BOOLEAN)EC_POINT_set_affine_coordinates (EcGroup, EcPoint, BnX, BnY, BnCtx);
 }
 
 /**
@@ -255,7 +255,7 @@ EcPointAdd (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
+  return (BOOLEAN)EC_POINT_add (EcGroup, EcPointResult, EcPointA, EcPointB, BnCtx);
 }
 
 /**
@@ -281,7 +281,7 @@ EcPointMul (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
+  return (BOOLEAN)EC_POINT_mul (EcGroup, EcPointResult, NULL, EcPoint, BnPScalar, BnCtx);
 }
 
 /**
@@ -302,7 +302,7 @@ EcPointInvert (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_invert (EcGroup, EcPoint, BnCtx);
+  return (BOOLEAN)EC_POINT_invert (EcGroup, EcPoint, BnCtx);
 }
 
 /**
@@ -395,7 +395,7 @@ EcPointSetCompressedCoordinates (
   IN VOID        *BnCtx
   )
 {
-  return (BOOLEAN) EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
+  return (BOOLEAN)EC_POINT_set_compressed_coordinates (EcGroup, EcPoint, BnX, YBit, BnCtx);
 }
 
 // =====================================================================================
@@ -417,7 +417,7 @@ EcNewByNid (
   IN UINTN  Nid
   )
 {
-  INT32 OpenSslNid;
+  INT32  OpenSslNid;
 
   OpenSslNid = CryptoNidToOpensslNid (Nid);
   if (OpenSslNid < 0) {
@@ -438,7 +438,7 @@ EcFree (
   IN  VOID  *EcContext
   )
 {
-  EC_KEY_free ((EC_KEY *) EcContext);
+  EC_KEY_free ((EC_KEY *)EcContext);
 }
 
 /**
@@ -475,26 +475,26 @@ EcGenerateKey (
   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) {
+  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) {
+  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
     return FALSE;
   }
 
-  EcKey = (EC_KEY *)EcContext;
-  Group = EC_KEY_get0_group (EcKey);
+  EcKey    = (EC_KEY *)EcContext;
+  Group    = EC_KEY_get0_group (EcKey);
   HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
 
   // Assume RAND_seed was called
@@ -506,6 +506,7 @@ EcGenerateKey (
     *PublicKeySize = HalfSize * 2;
     return FALSE;
   }
+
   *PublicKeySize = HalfSize * 2;
 
   EcPoint = EC_KEY_get0_public_key (EcKey);
@@ -514,9 +515,9 @@ EcGenerateKey (
   }
 
   RetVal = FALSE;
-  BnX = BN_new();
-  BnY = BN_new();
-  if (BnX == NULL || BnY == NULL) {
+  BnX    = BN_new ();
+  BnY    = BN_new ();
+  if ((BnX == NULL) || (BnY == NULL)) {
     goto fail;
   }
 
@@ -526,9 +527,10 @@ EcGenerateKey (
 
   XSize = BN_num_bytes (BnX);
   YSize = BN_num_bytes (BnY);
-  if (XSize <= 0 || YSize <= 0) {
+  if ((XSize <= 0) || (YSize <= 0)) {
     goto fail;
   }
+
   ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
 
   ZeroMem (PublicKey, *PublicKeySize);
@@ -565,31 +567,32 @@ EcGetPubKey (
   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) {
+  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) {
+  if ((PublicKey == NULL) && (*PublicKeySize != 0)) {
     return FALSE;
   }
 
-  EcKey = (EC_KEY *)EcContext;
-  Group = EC_KEY_get0_group (EcKey);
+  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);
@@ -598,9 +601,9 @@ EcGetPubKey (
   }
 
   RetVal = FALSE;
-  BnX = BN_new();
-  BnY = BN_new();
-  if (BnX == NULL || BnY == NULL) {
+  BnX    = BN_new ();
+  BnY    = BN_new ();
+  if ((BnX == NULL) || (BnY == NULL)) {
     goto fail;
   }
 
@@ -610,9 +613,10 @@ EcGetPubKey (
 
   XSize = BN_num_bytes (BnX);
   YSize = BN_num_bytes (BnY);
-  if (XSize <= 0 || YSize <= 0) {
+  if ((XSize <= 0) || (YSize <= 0)) {
     goto fail;
   }
+
   ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize);
 
   if (PublicKey != NULL) {
@@ -666,21 +670,21 @@ EcDhComputeKey (
   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) {
+  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) {
+  if ((Key == NULL) && (*KeySize != 0)) {
     return FALSE;
   }
 
@@ -688,36 +692,40 @@ EcDhComputeKey (
     return FALSE;
   }
 
-  EcKey = (EC_KEY *) EcContext;
-  Group = EC_KEY_get0_group (EcKey);
+  EcKey    = (EC_KEY *)EcContext;
+  Group    = EC_KEY_get0_group (EcKey);
   HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8;
-  if (CompressFlag == NULL && PeerPublicSize != HalfSize * 2) {
+  if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) {
     return FALSE;
   }
-  if (CompressFlag != NULL && PeerPublicSize != HalfSize) {
+
+  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);
+  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) {
+  if ((BnX == NULL) || (Point == NULL)) {
     goto fail;
   }
 
   if (CompressFlag == NULL) {
-    BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32) HalfSize, 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;
     }
@@ -729,13 +737,15 @@ EcDhComputeKey (
 
   // Validate NIST ECDH public key
   OpenSslNid = EC_GROUP_get_curve_name (Group);
-  PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid);
+  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;
   }
@@ -749,7 +759,7 @@ EcDhComputeKey (
 fail:
   BN_free (BnX);
   BN_free (BnY);
-  EC_POINT_free(Point);
+  EC_POINT_free (Point);
   EC_KEY_free (PeerEcKey);
   return RetVal;
 }
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index 84d9fbba32..a91f97b0c0 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -4302,216 +4302,216 @@ BOOLEAN
 ///
 struct _EDKII_CRYPTO_PROTOCOL {
   /// Version
-  EDKII_CRYPTO_GET_VERSION                           GetVersion;
+  EDKII_CRYPTO_GET_VERSION                            GetVersion;
   /// HMAC MD5 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW               DeprecatedHmacMd5New;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE              DeprecatedHmacMd5Free;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY           DeprecatedHmacMd5SetKey;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE         DeprecatedHmacMd5Duplicate;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE            DeprecatedHmacMd5Update;
-  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL             DeprecatedHmacMd5Final;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_NEW                DeprecatedHmacMd5New;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FREE               DeprecatedHmacMd5Free;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_SET_KEY            DeprecatedHmacMd5SetKey;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_DUPLICATE          DeprecatedHmacMd5Duplicate;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_UPDATE             DeprecatedHmacMd5Update;
+  DEPRECATED_EDKII_CRYPTO_HMAC_MD5_FINAL              DeprecatedHmacMd5Final;
   /// HMAC SHA1 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW              DeprecatedHmacSha1New;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE             DeprecatedHmacSha1Free;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY          DeprecatedHmacSha1SetKey;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE        DeprecatedHmacSha1Duplicate;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE           DeprecatedHmacSha1Update;
-  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL            DeprecatedHmacSha1Final;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_NEW               DeprecatedHmacSha1New;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FREE              DeprecatedHmacSha1Free;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_SET_KEY           DeprecatedHmacSha1SetKey;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_DUPLICATE         DeprecatedHmacSha1Duplicate;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_UPDATE            DeprecatedHmacSha1Update;
+  DEPRECATED_EDKII_CRYPTO_HMAC_SHA1_FINAL             DeprecatedHmacSha1Final;
   /// HMAC SHA256
-  EDKII_CRYPTO_HMAC_SHA256_NEW                       HmacSha256New;
-  EDKII_CRYPTO_HMAC_SHA256_FREE                      HmacSha256Free;
-  EDKII_CRYPTO_HMAC_SHA256_SET_KEY                   HmacSha256SetKey;
-  EDKII_CRYPTO_HMAC_SHA256_DUPLICATE                 HmacSha256Duplicate;
-  EDKII_CRYPTO_HMAC_SHA256_UPDATE                    HmacSha256Update;
-  EDKII_CRYPTO_HMAC_SHA256_FINAL                     HmacSha256Final;
+  EDKII_CRYPTO_HMAC_SHA256_NEW                        HmacSha256New;
+  EDKII_CRYPTO_HMAC_SHA256_FREE                       HmacSha256Free;
+  EDKII_CRYPTO_HMAC_SHA256_SET_KEY                    HmacSha256SetKey;
+  EDKII_CRYPTO_HMAC_SHA256_DUPLICATE                  HmacSha256Duplicate;
+  EDKII_CRYPTO_HMAC_SHA256_UPDATE                     HmacSha256Update;
+  EDKII_CRYPTO_HMAC_SHA256_FINAL                      HmacSha256Final;
   /// Md4 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE       DeprecatedMd4GetContextSize;
-  DEPRECATED_EDKII_CRYPTO_MD4_INIT                   DeprecatedMd4Init;
-  DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE              DeprecatedMd4Duplicate;
-  DEPRECATED_EDKII_CRYPTO_MD4_UPDATE                 DeprecatedMd4Update;
-  DEPRECATED_EDKII_CRYPTO_MD4_FINAL                  DeprecatedMd4Final;
-  DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL               DeprecatedMd4HashAll;
+  DEPRECATED_EDKII_CRYPTO_MD4_GET_CONTEXT_SIZE        DeprecatedMd4GetContextSize;
+  DEPRECATED_EDKII_CRYPTO_MD4_INIT                    DeprecatedMd4Init;
+  DEPRECATED_EDKII_CRYPTO_MD4_DUPLICATE               DeprecatedMd4Duplicate;
+  DEPRECATED_EDKII_CRYPTO_MD4_UPDATE                  DeprecatedMd4Update;
+  DEPRECATED_EDKII_CRYPTO_MD4_FINAL                   DeprecatedMd4Final;
+  DEPRECATED_EDKII_CRYPTO_MD4_HASH_ALL                DeprecatedMd4HashAll;
   /// Md5
-  EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE                  Md5GetContextSize;
-  EDKII_CRYPTO_MD5_INIT                              Md5Init;
-  EDKII_CRYPTO_MD5_DUPLICATE                         Md5Duplicate;
-  EDKII_CRYPTO_MD5_UPDATE                            Md5Update;
-  EDKII_CRYPTO_MD5_FINAL                             Md5Final;
-  EDKII_CRYPTO_MD5_HASH_ALL                          Md5HashAll;
+  EDKII_CRYPTO_MD5_GET_CONTEXT_SIZE                   Md5GetContextSize;
+  EDKII_CRYPTO_MD5_INIT                               Md5Init;
+  EDKII_CRYPTO_MD5_DUPLICATE                          Md5Duplicate;
+  EDKII_CRYPTO_MD5_UPDATE                             Md5Update;
+  EDKII_CRYPTO_MD5_FINAL                              Md5Final;
+  EDKII_CRYPTO_MD5_HASH_ALL                           Md5HashAll;
   /// Pkcs
-  EDKII_CRYPTO_PKCS1_ENCRYPT_V2                      Pkcs1v2Encrypt;
-  EDKII_CRYPTO_PKCS5_PW_HASH                         Pkcs5HashPassword;
-  EDKII_CRYPTO_PKCS7_VERIFY                          Pkcs7Verify;
-  EDKII_CRYPTO_PKCS7_VERIFY_EKU                      VerifyEKUsInPkcs7Signature;
-  EDKII_CRYPTO_PKCS7_GET_SIGNERS                     Pkcs7GetSigners;
-  EDKII_CRYPTO_PKCS7_FREE_SIGNERS                    Pkcs7FreeSigners;
-  EDKII_CRYPTO_PKCS7_SIGN                            Pkcs7Sign;
-  EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT            Pkcs7GetAttachedContent;
-  EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST           Pkcs7GetCertificatesList;
-  EDKII_CRYPTO_AUTHENTICODE_VERIFY                   AuthenticodeVerify;
-  EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY                ImageTimestampVerify;
+  EDKII_CRYPTO_PKCS1_ENCRYPT_V2                       Pkcs1v2Encrypt;
+  EDKII_CRYPTO_PKCS5_PW_HASH                          Pkcs5HashPassword;
+  EDKII_CRYPTO_PKCS7_VERIFY                           Pkcs7Verify;
+  EDKII_CRYPTO_PKCS7_VERIFY_EKU                       VerifyEKUsInPkcs7Signature;
+  EDKII_CRYPTO_PKCS7_GET_SIGNERS                      Pkcs7GetSigners;
+  EDKII_CRYPTO_PKCS7_FREE_SIGNERS                     Pkcs7FreeSigners;
+  EDKII_CRYPTO_PKCS7_SIGN                             Pkcs7Sign;
+  EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT             Pkcs7GetAttachedContent;
+  EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST            Pkcs7GetCertificatesList;
+  EDKII_CRYPTO_AUTHENTICODE_VERIFY                    AuthenticodeVerify;
+  EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY                 ImageTimestampVerify;
   /// DH
-  EDKII_CRYPTO_DH_NEW                                DhNew;
-  EDKII_CRYPTO_DH_FREE                               DhFree;
-  EDKII_CRYPTO_DH_GENERATE_PARAMETER                 DhGenerateParameter;
-  EDKII_CRYPTO_DH_SET_PARAMETER                      DhSetParameter;
-  EDKII_CRYPTO_DH_GENERATE_KEY                       DhGenerateKey;
-  EDKII_CRYPTO_DH_COMPUTE_KEY                        DhComputeKey;
+  EDKII_CRYPTO_DH_NEW                                 DhNew;
+  EDKII_CRYPTO_DH_FREE                                DhFree;
+  EDKII_CRYPTO_DH_GENERATE_PARAMETER                  DhGenerateParameter;
+  EDKII_CRYPTO_DH_SET_PARAMETER                       DhSetParameter;
+  EDKII_CRYPTO_DH_GENERATE_KEY                        DhGenerateKey;
+  EDKII_CRYPTO_DH_COMPUTE_KEY                         DhComputeKey;
   /// Random
-  EDKII_CRYPTO_RANDOM_SEED                           RandomSeed;
-  EDKII_CRYPTO_RANDOM_BYTES                          RandomBytes;
+  EDKII_CRYPTO_RANDOM_SEED                            RandomSeed;
+  EDKII_CRYPTO_RANDOM_BYTES                           RandomBytes;
   /// RSA
-  EDKII_CRYPTO_RSA_VERIFY_PKCS1                      RsaVerifyPkcs1;
-  EDKII_CRYPTO_RSA_NEW                               RsaNew;
-  EDKII_CRYPTO_RSA_FREE                              RsaFree;
-  EDKII_CRYPTO_RSA_SET_KEY                           RsaSetKey;
-  EDKII_CRYPTO_RSA_GET_KEY                           RsaGetKey;
-  EDKII_CRYPTO_RSA_GENERATE_KEY                      RsaGenerateKey;
-  EDKII_CRYPTO_RSA_CHECK_KEY                         RsaCheckKey;
-  EDKII_CRYPTO_RSA_PKCS1_SIGN                        RsaPkcs1Sign;
-  EDKII_CRYPTO_RSA_PKCS1_VERIFY                      RsaPkcs1Verify;
-  EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM          RsaGetPrivateKeyFromPem;
-  EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509          RsaGetPublicKeyFromX509;
+  EDKII_CRYPTO_RSA_VERIFY_PKCS1                       RsaVerifyPkcs1;
+  EDKII_CRYPTO_RSA_NEW                                RsaNew;
+  EDKII_CRYPTO_RSA_FREE                               RsaFree;
+  EDKII_CRYPTO_RSA_SET_KEY                            RsaSetKey;
+  EDKII_CRYPTO_RSA_GET_KEY                            RsaGetKey;
+  EDKII_CRYPTO_RSA_GENERATE_KEY                       RsaGenerateKey;
+  EDKII_CRYPTO_RSA_CHECK_KEY                          RsaCheckKey;
+  EDKII_CRYPTO_RSA_PKCS1_SIGN                         RsaPkcs1Sign;
+  EDKII_CRYPTO_RSA_PKCS1_VERIFY                       RsaPkcs1Verify;
+  EDKII_CRYPTO_RSA_GET_PRIVATE_KEY_FROM_PEM           RsaGetPrivateKeyFromPem;
+  EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509           RsaGetPublicKeyFromX509;
   /// Sha1
-  EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE                 Sha1GetContextSize;
-  EDKII_CRYPTO_SHA1_INIT                             Sha1Init;
-  EDKII_CRYPTO_SHA1_DUPLICATE                        Sha1Duplicate;
-  EDKII_CRYPTO_SHA1_UPDATE                           Sha1Update;
-  EDKII_CRYPTO_SHA1_FINAL                            Sha1Final;
-  EDKII_CRYPTO_SHA1_HASH_ALL                         Sha1HashAll;
+  EDKII_CRYPTO_SHA1_GET_CONTEXT_SIZE                  Sha1GetContextSize;
+  EDKII_CRYPTO_SHA1_INIT                              Sha1Init;
+  EDKII_CRYPTO_SHA1_DUPLICATE                         Sha1Duplicate;
+  EDKII_CRYPTO_SHA1_UPDATE                            Sha1Update;
+  EDKII_CRYPTO_SHA1_FINAL                             Sha1Final;
+  EDKII_CRYPTO_SHA1_HASH_ALL                          Sha1HashAll;
   /// Sha256
-  EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE               Sha256GetContextSize;
-  EDKII_CRYPTO_SHA256_INIT                           Sha256Init;
-  EDKII_CRYPTO_SHA256_DUPLICATE                      Sha256Duplicate;
-  EDKII_CRYPTO_SHA256_UPDATE                         Sha256Update;
-  EDKII_CRYPTO_SHA256_FINAL                          Sha256Final;
-  EDKII_CRYPTO_SHA256_HASH_ALL                       Sha256HashAll;
+  EDKII_CRYPTO_SHA256_GET_CONTEXT_SIZE                Sha256GetContextSize;
+  EDKII_CRYPTO_SHA256_INIT                            Sha256Init;
+  EDKII_CRYPTO_SHA256_DUPLICATE                       Sha256Duplicate;
+  EDKII_CRYPTO_SHA256_UPDATE                          Sha256Update;
+  EDKII_CRYPTO_SHA256_FINAL                           Sha256Final;
+  EDKII_CRYPTO_SHA256_HASH_ALL                        Sha256HashAll;
   /// Sha384
-  EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE               Sha384GetContextSize;
-  EDKII_CRYPTO_SHA384_INIT                           Sha384Init;
-  EDKII_CRYPTO_SHA384_DUPLICATE                      Sha384Duplicate;
-  EDKII_CRYPTO_SHA384_UPDATE                         Sha384Update;
-  EDKII_CRYPTO_SHA384_FINAL                          Sha384Final;
-  EDKII_CRYPTO_SHA384_HASH_ALL                       Sha384HashAll;
+  EDKII_CRYPTO_SHA384_GET_CONTEXT_SIZE                Sha384GetContextSize;
+  EDKII_CRYPTO_SHA384_INIT                            Sha384Init;
+  EDKII_CRYPTO_SHA384_DUPLICATE                       Sha384Duplicate;
+  EDKII_CRYPTO_SHA384_UPDATE                          Sha384Update;
+  EDKII_CRYPTO_SHA384_FINAL                           Sha384Final;
+  EDKII_CRYPTO_SHA384_HASH_ALL                        Sha384HashAll;
   /// Sha512
-  EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE               Sha512GetContextSize;
-  EDKII_CRYPTO_SHA512_INIT                           Sha512Init;
-  EDKII_CRYPTO_SHA512_DUPLICATE                      Sha512Duplicate;
-  EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
-  EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
-  EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
+  EDKII_CRYPTO_SHA512_GET_CONTEXT_SIZE                Sha512GetContextSize;
+  EDKII_CRYPTO_SHA512_INIT                            Sha512Init;
+  EDKII_CRYPTO_SHA512_DUPLICATE                       Sha512Duplicate;
+  EDKII_CRYPTO_SHA512_UPDATE                          Sha512Update;
+  EDKII_CRYPTO_SHA512_FINAL                           Sha512Final;
+  EDKII_CRYPTO_SHA512_HASH_ALL                        Sha512HashAll;
   /// X509
-  EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
-  EDKII_CRYPTO_X509_GET_COMMON_NAME                  X509GetCommonName;
-  EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME            X509GetOrganizationName;
-  EDKII_CRYPTO_X509_VERIFY_CERT                      X509VerifyCert;
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE            X509ConstructCertificate;
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK      X509ConstructCertificateStack;
-  EDKII_CRYPTO_X509_FREE                             X509Free;
-  EDKII_CRYPTO_X509_STACK_FREE                       X509StackFree;
-  EDKII_CRYPTO_X509_GET_TBS_CERT                     X509GetTBSCert;
+  EDKII_CRYPTO_X509_GET_SUBJECT_NAME                  X509GetSubjectName;
+  EDKII_CRYPTO_X509_GET_COMMON_NAME                   X509GetCommonName;
+  EDKII_CRYPTO_X509_GET_ORGANIZATION_NAME             X509GetOrganizationName;
+  EDKII_CRYPTO_X509_VERIFY_CERT                       X509VerifyCert;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE             X509ConstructCertificate;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK       X509ConstructCertificateStack;
+  EDKII_CRYPTO_X509_FREE                              X509Free;
+  EDKII_CRYPTO_X509_STACK_FREE                        X509StackFree;
+  EDKII_CRYPTO_X509_GET_TBS_CERT                      X509GetTBSCert;
   /// TDES - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE      DeprecatedTdesGetContextSize;
-  DEPRECATED_EDKII_CRYPTO_TDES_INIT                  DeprecatedTdesInit;
-  DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT           DeprecatedTdesEcbEncrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT           DeprecatedTdesEcbDecrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT           DeprecatedTdesCbcEncrypt;
-  DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT           DeprecatedTdesCbcDecrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_GET_CONTEXT_SIZE       DeprecatedTdesGetContextSize;
+  DEPRECATED_EDKII_CRYPTO_TDES_INIT                   DeprecatedTdesInit;
+  DEPRECATED_EDKII_CRYPTO_TDES_ECB_ENCRYPT            DeprecatedTdesEcbEncrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_ECB_DECRYPT            DeprecatedTdesEcbDecrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_CBC_ENCRYPT            DeprecatedTdesCbcEncrypt;
+  DEPRECATED_EDKII_CRYPTO_TDES_CBC_DECRYPT            DeprecatedTdesCbcDecrypt;
   /// AES - ECB Mode is deprecated and unsupported
-  EDKII_CRYPTO_AES_GET_CONTEXT_SIZE                  AesGetContextSize;
-  EDKII_CRYPTO_AES_INIT                              AesInit;
-  DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT            DeprecatedAesEcbEncrypt;
-  DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT            DeprecatedAesEcbDecrypt;
-  EDKII_CRYPTO_AES_CBC_ENCRYPT                       AesCbcEncrypt;
-  EDKII_CRYPTO_AES_CBC_DECRYPT                       AesCbcDecrypt;
+  EDKII_CRYPTO_AES_GET_CONTEXT_SIZE                   AesGetContextSize;
+  EDKII_CRYPTO_AES_INIT                               AesInit;
+  DEPRECATED_EDKII_CRYPTO_AES_ECB_ENCRYPT             DeprecatedAesEcbEncrypt;
+  DEPRECATED_EDKII_CRYPTO_AES_ECB_DECRYPT             DeprecatedAesEcbDecrypt;
+  EDKII_CRYPTO_AES_CBC_ENCRYPT                        AesCbcEncrypt;
+  EDKII_CRYPTO_AES_CBC_DECRYPT                        AesCbcDecrypt;
   /// Arc4 - deprecated and unsupported
-  DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE      DeprecatedArc4GetContextSize;
-  DEPRECATED_EDKII_CRYPTO_ARC4_INIT                  DeprecatedArc4Init;
-  DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT               DeprecatedArc4Encrypt;
-  DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT               DeprecatedArc4Decrypt;
-  DEPRECATED_EDKII_CRYPTO_ARC4_RESET                 DeprecatedArc4Reset;
+  DEPRECATED_EDKII_CRYPTO_ARC4_GET_CONTEXT_SIZE       DeprecatedArc4GetContextSize;
+  DEPRECATED_EDKII_CRYPTO_ARC4_INIT                   DeprecatedArc4Init;
+  DEPRECATED_EDKII_CRYPTO_ARC4_ENCRYPT                DeprecatedArc4Encrypt;
+  DEPRECATED_EDKII_CRYPTO_ARC4_DECRYPT                DeprecatedArc4Decrypt;
+  DEPRECATED_EDKII_CRYPTO_ARC4_RESET                  DeprecatedArc4Reset;
   /// SM3
-  EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE                  Sm3GetContextSize;
-  EDKII_CRYPTO_SM3_INIT                              Sm3Init;
-  EDKII_CRYPTO_SM3_DUPLICATE                         Sm3Duplicate;
-  EDKII_CRYPTO_SM3_UPDATE                            Sm3Update;
-  EDKII_CRYPTO_SM3_FINAL                             Sm3Final;
-  EDKII_CRYPTO_SM3_HASH_ALL                          Sm3HashAll;
+  EDKII_CRYPTO_SM3_GET_CONTEXT_SIZE                   Sm3GetContextSize;
+  EDKII_CRYPTO_SM3_INIT                               Sm3Init;
+  EDKII_CRYPTO_SM3_DUPLICATE                          Sm3Duplicate;
+  EDKII_CRYPTO_SM3_UPDATE                             Sm3Update;
+  EDKII_CRYPTO_SM3_FINAL                              Sm3Final;
+  EDKII_CRYPTO_SM3_HASH_ALL                           Sm3HashAll;
   /// HKDF
-  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND       HkdfSha256ExtractAndExpand;
+  EDKII_CRYPTO_HKDF_SHA_256_EXTRACT_AND_EXPAND        HkdfSha256ExtractAndExpand;
   /// X509 (Continued)
-  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V    X509ConstructCertificateStackV;
+  EDKII_CRYPTO_X509_CONSTRUCT_CERTIFICATE_STACK_V     X509ConstructCertificateStackV;
   /// TLS
-  EDKII_CRYPTO_TLS_INITIALIZE                        TlsInitialize;
-  EDKII_CRYPTO_TLS_CTX_FREE                          TlsCtxFree;
-  EDKII_CRYPTO_TLS_CTX_NEW                           TlsCtxNew;
-  EDKII_CRYPTO_TLS_FREE                              TlsFree;
-  EDKII_CRYPTO_TLS_NEW                               TlsNew;
-  EDKII_CRYPTO_TLS_IN_HANDSHAKE                      TlsInHandshake;
-  EDKII_CRYPTO_TLS_DO_HANDSHAKE                      TlsDoHandshake;
-  EDKII_CRYPTO_TLS_HANDLE_ALERT                      TlsHandleAlert;
-  EDKII_CRYPTO_TLS_CLOSE_NOTIFY                      TlsCloseNotify;
-  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT                  TlsCtrlTrafficOut;
-  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN                   TlsCtrlTrafficIn;
-  EDKII_CRYPTO_TLS_READ                              TlsRead;
-  EDKII_CRYPTO_TLS_WRITE                             TlsWrite;
+  EDKII_CRYPTO_TLS_INITIALIZE                         TlsInitialize;
+  EDKII_CRYPTO_TLS_CTX_FREE                           TlsCtxFree;
+  EDKII_CRYPTO_TLS_CTX_NEW                            TlsCtxNew;
+  EDKII_CRYPTO_TLS_FREE                               TlsFree;
+  EDKII_CRYPTO_TLS_NEW                                TlsNew;
+  EDKII_CRYPTO_TLS_IN_HANDSHAKE                       TlsInHandshake;
+  EDKII_CRYPTO_TLS_DO_HANDSHAKE                       TlsDoHandshake;
+  EDKII_CRYPTO_TLS_HANDLE_ALERT                       TlsHandleAlert;
+  EDKII_CRYPTO_TLS_CLOSE_NOTIFY                       TlsCloseNotify;
+  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_OUT                   TlsCtrlTrafficOut;
+  EDKII_CRYPTO_TLS_CTRL_TRAFFIC_IN                    TlsCtrlTrafficIn;
+  EDKII_CRYPTO_TLS_READ                               TlsRead;
+  EDKII_CRYPTO_TLS_WRITE                              TlsWrite;
   /// TLS Set
-  EDKII_CRYPTO_TLS_SET_VERSION                       TlsSetVersion;
-  EDKII_CRYPTO_TLS_SET_CONNECTION_END                TlsSetConnectionEnd;
-  EDKII_CRYPTO_TLS_SET_CIPHER_LIST                   TlsSetCipherList;
-  EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD            TlsSetCompressionMethod;
-  EDKII_CRYPTO_TLS_SET_VERIFY                        TlsSetVerify;
-  EDKII_CRYPTO_TLS_SET_VERIFY_HOST                   TlsSetVerifyHost;
-  EDKII_CRYPTO_TLS_SET_SESSIONID                     TlsSetSessionId;
-  EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE                TlsSetCaCertificate;
-  EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT              TlsSetHostPublicCert;
-  EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY              TlsSetHostPrivateKey;
-  EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST          TlsSetCertRevocationList;
+  EDKII_CRYPTO_TLS_SET_VERSION                        TlsSetVersion;
+  EDKII_CRYPTO_TLS_SET_CONNECTION_END                 TlsSetConnectionEnd;
+  EDKII_CRYPTO_TLS_SET_CIPHER_LIST                    TlsSetCipherList;
+  EDKII_CRYPTO_TLS_SET_COMPRESSION_METHOD             TlsSetCompressionMethod;
+  EDKII_CRYPTO_TLS_SET_VERIFY                         TlsSetVerify;
+  EDKII_CRYPTO_TLS_SET_VERIFY_HOST                    TlsSetVerifyHost;
+  EDKII_CRYPTO_TLS_SET_SESSIONID                      TlsSetSessionId;
+  EDKII_CRYPTO_TLS_SET_CA_CERTIFICATE                 TlsSetCaCertificate;
+  EDKII_CRYPTO_TLS_SET_HOST_PUBLIC_CERT               TlsSetHostPublicCert;
+  EDKII_CRYPTO_TLS_SET_HOST_PRIVATE_KEY               TlsSetHostPrivateKey;
+  EDKII_CRYPTO_TLS_SET_CERT_REVOCATION_LIST           TlsSetCertRevocationList;
   /// TLS Get
-  EDKII_CRYPTO_TLS_GET_VERSION                       TlsGetVersion;
-  EDKII_CRYPTO_TLS_GET_CONNECTION_END                TlsGetConnectionEnd;
-  EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER                TlsGetCurrentCipher;
-  EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID        TlsGetCurrentCompressionId;
-  EDKII_CRYPTO_TLS_GET_VERIFY                        TlsGetVerify;
-  EDKII_CRYPTO_TLS_GET_SESSION_ID                    TlsGetSessionId;
-  EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM                 TlsGetClientRandom;
-  EDKII_CRYPTO_TLS_GET_SERVER_RANDOM                 TlsGetServerRandom;
-  EDKII_CRYPTO_TLS_GET_KEY_MATERIAL                  TlsGetKeyMaterial;
-  EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE                TlsGetCaCertificate;
-  EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT              TlsGetHostPublicCert;
-  EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY              TlsGetHostPrivateKey;
-  EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST          TlsGetCertRevocationList;
+  EDKII_CRYPTO_TLS_GET_VERSION                        TlsGetVersion;
+  EDKII_CRYPTO_TLS_GET_CONNECTION_END                 TlsGetConnectionEnd;
+  EDKII_CRYPTO_TLS_GET_CURRENT_CIPHER                 TlsGetCurrentCipher;
+  EDKII_CRYPTO_TLS_GET_CURRENT_COMPRESSION_ID         TlsGetCurrentCompressionId;
+  EDKII_CRYPTO_TLS_GET_VERIFY                         TlsGetVerify;
+  EDKII_CRYPTO_TLS_GET_SESSION_ID                     TlsGetSessionId;
+  EDKII_CRYPTO_TLS_GET_CLIENT_RANDOM                  TlsGetClientRandom;
+  EDKII_CRYPTO_TLS_GET_SERVER_RANDOM                  TlsGetServerRandom;
+  EDKII_CRYPTO_TLS_GET_KEY_MATERIAL                   TlsGetKeyMaterial;
+  EDKII_CRYPTO_TLS_GET_CA_CERTIFICATE                 TlsGetCaCertificate;
+  EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT               TlsGetHostPublicCert;
+  EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY               TlsGetHostPrivateKey;
+  EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST           TlsGetCertRevocationList;
   /// RSA PSS
-  EDKII_CRYPTO_RSA_PSS_SIGN                          RsaPssSign;
-  EDKII_CRYPTO_RSA_PSS_VERIFY                        RsaPssVerify;
+  EDKII_CRYPTO_RSA_PSS_SIGN                           RsaPssSign;
+  EDKII_CRYPTO_RSA_PSS_VERIFY                         RsaPssVerify;
   /// Parallel hash
-  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
+  EDKII_CRYPTO_PARALLEL_HASH_ALL                      ParallelHash256HashAll;
   /// Big Number
-  EDKII_CRYPTO_BIGNUM_INIT                           BigNumInit;
-  EDKII_CRYPTO_BIGNUM_FROM_BIN                       BigNumFromBin;
-  EDKII_CRYPTO_BIGNUM_TO_BIN                         BigNumToBin;
-  EDKII_CRYPTO_BIGNUM_FREE                           BigNumFree;
-  EDKII_CRYPTO_BIGNUM_ADD                            BigNumAdd;
-  EDKII_CRYPTO_BIGNUM_SUB                            BigNumSub;
-  EDKII_CRYPTO_BIGNUM_MOD                            BigNumMod;
-  EDKII_CRYPTO_BIGNUM_EXP_MOD                        BigNumExpMod;
-  EDKII_CRYPTO_BIGNUM_INVERSE_MOD                    BigNumInverseMod;
-  EDKII_CRYPTO_BIGNUM_DIV                            BigNumDiv;
-  EDKII_CRYPTO_BIGNUM_MUL_MOD                        BigNumMulMod;
-  EDKII_CRYPTO_BIGNUM_CMP                            BigNumCmp;
-  EDKII_CRYPTO_BIGNUM_BITS                           BigNumBits;
-  EDKII_CRYPTO_BIGNUM_BYTES                          BigNumBytes;
-  EDKII_CRYPTO_BIGNUM_IS_WORD                        BigNumIsWord;
-  EDKII_CRYPTO_BIGNUM_IS_ODD                         BigNumIsOdd;
-  EDKII_CRYPTO_BIGNUM_COPY                           BigNumCopy;
-  EDKII_CRYPTO_BIGNUM_VALUE_ONE                      BigNumValueOne;
-  EDKII_CRYPTO_BIGNUM_R_SHIFT                        BigNumRShift;
-  EDKII_CRYPTO_BIGNUM_CONST_TIME                     BigNumConstTime;
-  EDKII_CRYPTO_BIGNUM_SQR_MOD                        BigNumSqrMod;
-  EDKII_CRYPTO_BIGNUM_NEW_CONTEXT                    BigNumNewContext;
-  EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                   BigNumContextFree;
-  EDKII_CRYPTO_BIGNUM_SET_UINT                       BigNumSetUint;
-  EDKII_CRYPTO_BIGNUM_ADD_MOD                        BigNumAddMod;
+  EDKII_CRYPTO_BIGNUM_INIT                            BigNumInit;
+  EDKII_CRYPTO_BIGNUM_FROM_BIN                        BigNumFromBin;
+  EDKII_CRYPTO_BIGNUM_TO_BIN                          BigNumToBin;
+  EDKII_CRYPTO_BIGNUM_FREE                            BigNumFree;
+  EDKII_CRYPTO_BIGNUM_ADD                             BigNumAdd;
+  EDKII_CRYPTO_BIGNUM_SUB                             BigNumSub;
+  EDKII_CRYPTO_BIGNUM_MOD                             BigNumMod;
+  EDKII_CRYPTO_BIGNUM_EXP_MOD                         BigNumExpMod;
+  EDKII_CRYPTO_BIGNUM_INVERSE_MOD                     BigNumInverseMod;
+  EDKII_CRYPTO_BIGNUM_DIV                             BigNumDiv;
+  EDKII_CRYPTO_BIGNUM_MUL_MOD                         BigNumMulMod;
+  EDKII_CRYPTO_BIGNUM_CMP                             BigNumCmp;
+  EDKII_CRYPTO_BIGNUM_BITS                            BigNumBits;
+  EDKII_CRYPTO_BIGNUM_BYTES                           BigNumBytes;
+  EDKII_CRYPTO_BIGNUM_IS_WORD                         BigNumIsWord;
+  EDKII_CRYPTO_BIGNUM_IS_ODD                          BigNumIsOdd;
+  EDKII_CRYPTO_BIGNUM_COPY                            BigNumCopy;
+  EDKII_CRYPTO_BIGNUM_VALUE_ONE                       BigNumValueOne;
+  EDKII_CRYPTO_BIGNUM_R_SHIFT                         BigNumRShift;
+  EDKII_CRYPTO_BIGNUM_CONST_TIME                      BigNumConstTime;
+  EDKII_CRYPTO_BIGNUM_SQR_MOD                         BigNumSqrMod;
+  EDKII_CRYPTO_BIGNUM_NEW_CONTEXT                     BigNumNewContext;
+  EDKII_CRYPTO_BIGNUM_CONTEXT_FREE                    BigNumContextFree;
+  EDKII_CRYPTO_BIGNUM_SET_UINT                        BigNumSetUint;
+  EDKII_CRYPTO_BIGNUM_ADD_MOD                         BigNumAddMod;
   /// EC
   EDKII_CRYPTO_EC_GROUP_INIT                          EcGroupInit;
   EDKII_CRYPTO_EC_GROUP_GET_CURVE                     EcGroupGetCurve;
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
index df91752c9c..2636bb6318 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
@@ -11,9 +11,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 //
 // Debug data
 //
-#define MAX_TEST_DATA_SIZE  512
+#define MAX_TEST_DATA_SIZE    512
 #define BYTES_OF_OPERATION_A  60
-#define BITS_OF_OPERATION_A  480 //(8 * 60)
+#define BITS_OF_OPERATION_A   480// (8 * 60)
 
 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnOperationA[] = {
   0x00, 0x00, 0x00, 0x00, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
@@ -88,23 +88,23 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultExpMod[] =  {
 
 // BnOperationA >> 128
 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultRShift[] =  {
-                          0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
-  0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
-  0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd
+  0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+  0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6,0x4b,  0x55, 0xd3, 0x9a,
+  0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23,0xa3,  0xfe, 0xeb, 0xbd
 };
 
 // 0x12345678
-GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultUIntSet[] =  {0x12, 0x34, 0x56, 0x78};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  BnResultUIntSet[] =  { 0x12, 0x34, 0x56, 0x78 };
 
 typedef struct {
-  VOID *BnA;
-  VOID *BnB;
-  VOID *BnC;
-  VOID *BnD;
-  VOID *BnCTX;
+  VOID    *BnA;
+  VOID    *BnB;
+  VOID    *BnC;
+  VOID    *BnD;
+  VOID    *BnCTX;
 } BN_TEST_CONTEXT;
 
-GLOBAL_REMOVE_IF_UNREFERENCED STATIC BN_TEST_CONTEXT mBnContext = {NULL, NULL, NULL, NULL, NULL};
+GLOBAL_REMOVE_IF_UNREFERENCED STATIC BN_TEST_CONTEXT  mBnContext = { NULL, NULL, NULL, NULL, NULL };
 
 //
 // Debug function
@@ -112,18 +112,23 @@ GLOBAL_REMOVE_IF_UNREFERENCED STATIC BN_TEST_CONTEXT mBnContext = {NULL, NULL, N
 STATIC
 BOOLEAN
 EqualBn2Bn (
-  CONST VOID *Expected, CONST VOID *Actual
+  CONST VOID  *Expected,
+  CONST VOID  *Actual
   )
 {
-    if (BigNumCmp(Expected, Actual) == 0)
-        return TRUE;
-    return FALSE;
+  if (BigNumCmp (Expected, Actual) == 0) {
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
 STATIC
 BOOLEAN
 EqualBn2Bin (
-  CONST VOID *Bn, CONST UINT8 *Buffer, CONST UINTN BufferSize
+  CONST VOID   *Bn,
+  CONST UINT8  *Buffer,
+  CONST UINTN  BufferSize
   )
 {
   UINTN  BnTestBufferSize;
@@ -135,6 +140,7 @@ EqualBn2Bin (
       return TRUE;
     }
   }
+
   return FALSE;
 }
 
@@ -144,22 +150,24 @@ TestVerifyBnPreReq (
   UNIT_TEST_CONTEXT  Context
   )
 {
-  BN_TEST_CONTEXT *BnContext;
-
-  BnContext = Context;
-  BnContext->BnCTX = BigNumNewContext();
-  BnContext->BnA = BigNumInit();
-  BnContext->BnB = BigNumInit();
-  BnContext->BnC = BigNumInit();
-  BnContext->BnD = BigNumInit();
-  if (BnContext->BnCTX == NULL
-        || BnContext->BnA == NULL
-        || BnContext->BnB == NULL
-        || BnContext->BnC == NULL
-        || BnContext->BnD == NULL
-        ) {
+  BN_TEST_CONTEXT  *BnContext;
+
+  BnContext        = Context;
+  BnContext->BnCTX = BigNumNewContext ();
+  BnContext->BnA   = BigNumInit ();
+  BnContext->BnB   = BigNumInit ();
+  BnContext->BnC   = BigNumInit ();
+  BnContext->BnD   = BigNumInit ();
+  if (  (BnContext->BnCTX == NULL)
+     || (BnContext->BnA == NULL)
+     || (BnContext->BnB == NULL)
+     || (BnContext->BnC == NULL)
+     || (BnContext->BnD == NULL)
+        )
+  {
     return UNIT_TEST_ERROR_TEST_FAILED;
   }
+
   return UNIT_TEST_PASSED;
 }
 
@@ -169,7 +177,7 @@ TestVerifyBnCleanUp (
   UNIT_TEST_CONTEXT  Context
   )
 {
-  BN_TEST_CONTEXT *BnContext;
+  BN_TEST_CONTEXT  *BnContext;
 
   BnContext = Context;
   BigNumContextFree (BnContext->BnCTX);
@@ -185,63 +193,64 @@ TestVerifyBn (
   IN UNIT_TEST_CONTEXT  Context
   )
 {
-  BN_TEST_CONTEXT *BnContext;
-  UINTN Num;
-  CONST VOID *BnOne;
+  BN_TEST_CONTEXT  *BnContext;
+  UINTN            Num;
+  CONST VOID       *BnOne;
 
   BnContext = Context;
 
   // Calculation tests
   BnContext->BnA = BigNumFromBin (BnOperationA, sizeof (BnOperationA));
   BnContext->BnB = BigNumFromBin (BnOperationB, sizeof (BnOperationB));
-  //C=A+B
+  // C=A+B
   BigNumAdd (BnContext->BnA, BnContext->BnB, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultSum, sizeof (BnResultSum)));
-  //D=C-A=B
+  // D=C-A=B
   BigNumSub (BnContext->BnC, BnContext->BnA, BnContext->BnD);
   UT_ASSERT_TRUE (EqualBn2Bn (BnContext->BnB, BnContext->BnD));
-  //C=(A+B)%D
+  // C=(A+B)%D
   BnContext->BnD = BigNumFromBin (BnOperationMod, sizeof (BnOperationMod));
   BigNumAddMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultSumMod, sizeof (BnResultSumMod)));
-  //C=(A*B)%D
+  // C=(A*B)%D
   BigNumMulMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultMulMod, sizeof (BnResultMulMod)));
-  //C=A/D
+  // C=A/D
   BigNumDiv (BnContext->BnA, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultDiv, sizeof (BnResultDiv)));
-  //C=A%D
+  // C=A%D
   BigNumMod (BnContext->BnA, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultMod, sizeof (BnResultMod)));
-  //1=(A*C)%D
+  // 1=(A*C)%D
   BigNumInverseMod (BnContext->BnA, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultInverseMod, sizeof (BnResultInverseMod)));
-  //C=(A^B)%D
+  // C=(A^B)%D
   BnContext->BnB = BigNumFromBin (BnOperationExp, sizeof (BnOperationExp));
   BigNumExpMod (BnContext->BnA, BnContext->BnB, BnContext->BnD, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultExpMod, sizeof (BnResultExpMod)));
-  //C=A>>128
+  // C=A>>128
   BigNumRShift (BnContext->BnA, 128, BnContext->BnC);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultRShift, sizeof (BnResultRShift)));
-  //C=0x12345678
+  // C=0x12345678
   BigNumSetUint (BnContext->BnC, 0x12345678);
   UT_ASSERT_TRUE (EqualBn2Bin (BnContext->BnC, BnResultUIntSet, sizeof (BnResultUIntSet)));
-  //Bn compare
+  // Bn compare
   UT_ASSERT_TRUE (BigNumIsWord (BnContext->BnC, 0x12345678));
   UT_ASSERT_FALSE (BigNumIsWord (BnContext->BnC, 0x12345600));
   UT_ASSERT_FALSE (BigNumIsOdd (BnContext->BnC));
   UT_ASSERT_TRUE (BigNumIsOdd (BnContext->BnA));
 
-  //Other tests
+  // Other tests
   BigNumConstTime (BnContext->BnA);
   Num = BigNumBytes (BnContext->BnA);
   UT_ASSERT_EQUAL (Num, BYTES_OF_OPERATION_A);
   Num = BigNumBits (BnContext->BnA);
   UT_ASSERT_EQUAL (Num, BITS_OF_OPERATION_A);
-  BnOne = BigNumValueOne();
+  BnOne = BigNumValueOne ();
   if (BnOne == NULL) {
     return UNIT_TEST_ERROR_TEST_FAILED;
   }
+
   UT_ASSERT_TRUE (BigNumIsWord (BnOne, 0x1));
 
   return UNIT_TEST_PASSED;
@@ -251,7 +260,7 @@ TEST_DESC  mBnTest[] = {
   //
   // -----Description----------------Class---------------------Function-----------Pre----------------Post---------Context
   //
-  { "TestVerifyBn()",   "CryptoPkg.BaseCryptLib.BigNumber", TestVerifyBn, TestVerifyBnPreReq, TestVerifyBnCleanUp, &mBnContext   },
+  { "TestVerifyBn()", "CryptoPkg.BaseCryptLib.BigNumber", TestVerifyBn, TestVerifyBnPreReq, TestVerifyBnCleanUp, &mBnContext },
 };
 
-UINTN  mBnTestNum = ARRAY_SIZE(mBnTest);
+UINTN  mBnTestNum = ARRAY_SIZE (mBnTest);
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
index 8008b1dc78..54ce0b22df 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
@@ -8,19 +8,19 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include "TestBaseCryptLib.h"
 
-#define EC_CURVE_NUM_SUPPORTED 3
-UINTN  EcCurveList[EC_CURVE_NUM_SUPPORTED] = {CRYPTO_NID_SECP256R1, CRYPTO_NID_SECP384R1, CRYPTO_NID_SECP521R1};
-UINTN  EcKeyHalfSize[EC_CURVE_NUM_SUPPORTED] = {32, 48, 66};
+#define EC_CURVE_NUM_SUPPORTED  3
+UINTN  EcCurveList[EC_CURVE_NUM_SUPPORTED]   = { CRYPTO_NID_SECP256R1, CRYPTO_NID_SECP384R1, CRYPTO_NID_SECP521R1 };
+UINTN  EcKeyHalfSize[EC_CURVE_NUM_SUPPORTED] = { 32, 48, 66 };
 
-struct Generator
-{
-  UINT8 X[66];
-  UINT8 Y[66];
+struct Generator {
+  UINT8    X[66];
+  UINT8    Y[66];
 };
+
 // Generator points of all ec curve
-struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
+struct Generator  EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
 {
-  //CRYPTO_NID_SECP256R1
+  // CRYPTO_NID_SECP256R1
   {
     { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
       0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
@@ -30,7 +30,7 @@ struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
       0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
       0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 }
   },
-  //CRYPTO_NID_SECP384R1
+  // CRYPTO_NID_SECP384R1
   {
     { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
       0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
@@ -42,7 +42,7 @@ struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
       0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
       0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f }
   },
-  //CRYPTO_NID_SECP521R1
+  // CRYPTO_NID_SECP521R1
   {
     { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
       0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
@@ -60,16 +60,16 @@ struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
   }
 };
 
-VOID   *Ec1     ;
-VOID   *Ec2     ;
-VOID   *Group   ;
-VOID   *Point1  ;
-VOID   *Point2  ;
-VOID   *PointRes;
-VOID   *BnX     ;
-VOID   *BnY     ;
-VOID   *BnP     ;
-VOID   *BnOrder ;
+VOID  *Ec1;
+VOID  *Ec2;
+VOID  *Group;
+VOID  *Point1;
+VOID  *Point2;
+VOID  *PointRes;
+VOID  *BnX;
+VOID  *BnY;
+VOID  *BnP;
+VOID  *BnOrder;
 
 UNIT_TEST_STATUS
 EFIAPI
@@ -87,9 +87,10 @@ TestVerifyEcPreReq (
   BnY      = NULL;
   BnP      = BigNumInit ();
   BnOrder  = BigNumInit ();
-  if (BnP == NULL || BnOrder == NULL) {
+  if ((BnP == NULL) || (BnOrder == NULL)) {
     return UNIT_TEST_ERROR_TEST_FAILED;
   }
+
   return UNIT_TEST_PASSED;
 }
 
@@ -117,8 +118,8 @@ TestVerifyEcBasic (
   UNIT_TEST_CONTEXT  Context
   )
 {
-  UINTN   CurveCount;
-  BOOLEAN Status;
+  UINTN    CurveCount;
+  BOOLEAN  Status;
 
   //
   // Initialize BigNumbers
@@ -132,12 +133,12 @@ TestVerifyEcBasic (
       return UNIT_TEST_ERROR_TEST_FAILED;
     }
 
-    Point1 = EcPointInit (Group);
-    Point2 = EcPointInit (Group);
+    Point1   = EcPointInit (Group);
+    Point2   = EcPointInit (Group);
     PointRes = EcPointInit (Group);
-    BnX = BigNumFromBin (EcCurveGenerator[CurveCount].X, EcKeyHalfSize[CurveCount]);
-    BnY = BigNumFromBin (EcCurveGenerator[CurveCount].Y, EcKeyHalfSize[CurveCount]);
-    if (Point1 == NULL || Point2 == NULL || PointRes == NULL || BnX == NULL || BnY == NULL) {
+    BnX      = BigNumFromBin (EcCurveGenerator[CurveCount].X, EcKeyHalfSize[CurveCount]);
+    BnY      = BigNumFromBin (EcCurveGenerator[CurveCount].Y, EcKeyHalfSize[CurveCount]);
+    if ((Point1 == NULL) || (Point2 == NULL) || (PointRes == NULL) || (BnX == NULL) || (BnY == NULL)) {
       return UNIT_TEST_ERROR_TEST_FAILED;
     }
 
@@ -147,7 +148,7 @@ TestVerifyEcBasic (
     Status = EcGroupGetOrder (Group, BnOrder);
     UT_ASSERT_TRUE (Status);
 
-    //Point G should on curve
+    // Point G should on curve
     Status = EcPointSetAffineCoordinates (Group, Point1, BnX, BnY, NULL);
     UT_ASSERT_TRUE (Status);
 
@@ -163,21 +164,21 @@ TestVerifyEcBasic (
     Status = EcPointIsAtInfinity (Group, Point1);
     UT_ASSERT_FALSE (Status);
 
-    //Point 2G should on curve
+    // Point 2G should on curve
     Status = EcPointAdd (Group, PointRes, Point1, Point1, NULL);
     UT_ASSERT_TRUE (Status);
 
     Status = EcPointIsOnCurve (Group, PointRes, NULL);
     UT_ASSERT_TRUE (Status);
 
-    //Point Order * G should at infinity
+    // Point Order * G should at infinity
     Status = EcPointMul (Group, PointRes, Point1, BnOrder, NULL);
     UT_ASSERT_TRUE (Status);
 
     Status = EcPointIsAtInfinity (Group, PointRes);
     UT_ASSERT_TRUE (Status);
 
-    //-(-G) == G
+    // -(-G) == G
     Status = EcPointInvert (Group, Point2, NULL);
     UT_ASSERT_TRUE (Status);
 
@@ -190,7 +191,7 @@ TestVerifyEcBasic (
     Status = EcPointEqual (Group, Point2, Point1, NULL);
     UT_ASSERT_TRUE (Status);
 
-    //Compress point test
+    // Compress point test
     Status = EcPointSetCompressedCoordinates (Group, Point1, BnX, 0, NULL);
     UT_ASSERT_TRUE (Status);
 
@@ -216,16 +217,16 @@ TestVerifyEcDh (
   UNIT_TEST_CONTEXT  Context
   )
 {
-  UINT8   Public1[66 * 2];
-  UINTN   Public1Length;
-  UINT8   Public2[66 * 2];
-  UINTN   Public2Length;
-  UINT8   Key1[66];
-  UINTN   Key1Length;
-  UINT8   Key2[66];
-  UINTN   Key2Length;
-  UINTN   CurveCount;
-  BOOLEAN Status;
+  UINT8    Public1[66 * 2];
+  UINTN    Public1Length;
+  UINT8    Public2[66 * 2];
+  UINTN    Public2Length;
+  UINT8    Key1[66];
+  UINTN    Key1Length;
+  UINT8    Key2[66];
+  UINTN    Key2Length;
+  UINTN    CurveCount;
+  BOOLEAN  Status;
 
   for (CurveCount = 0; CurveCount < EC_CURVE_NUM_SUPPORTED; CurveCount++) {
     //
@@ -233,8 +234,8 @@ TestVerifyEcDh (
     //
     Public1Length = sizeof (Public1);
     Public2Length = sizeof (Public2);
-    Key1Length = sizeof (Key1);
-    Key2Length = sizeof (Key2);
+    Key1Length    = sizeof (Key1);
+    Key2Length    = sizeof (Key2);
     //
     // ECDH functions unit test
     //
-- 
2.31.1.windows.1


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

* Re: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib
  2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
                   ` (6 preceding siblings ...)
  2022-09-07  8:29 ` [PATCH 7/7] CryptoPkg: Run uncrustify tools on EC and BN change yi1 li
@ 2022-09-20 16:01 ` Yao, Jiewen
  2022-09-21  4:56   ` yi1 li
  7 siblings, 1 reply; 11+ messages in thread
From: Yao, Jiewen @ 2022-09-20 16:01 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io; +Cc: Wang, Jian J, Xiaoyu Lu, Jiang, Guomin

Thanks for the patch. Please:
1) Separate BN and EC. Please submit 2 different patch sets. One for EC, the other for BN.
2) Please squash uncrustify tool update into previous patch. No need to submit a standalone one.
3) Please increase EDKII_CRYPTO_VERSION.

With that change, reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 7, 2022 4:29 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
> Jian J <jian.j.wang@intel.com>; Xiaoyu Lu <xiaoyux.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to
> BaseCryptLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> 
> Review PR: https://github.com/tianocore/edk2/pull/3309
> This patch sequence is used to add CryptBn and CryptEc library, which
> are wrapped over OpenSSL. The implementation provides library functions
> for EFI BaseCrypt protocol and EFI BaseCrypt Configuration Protocol.
> 
> All APIs passed unit test and fuzzing test, detail as:
> 1. Unit test:
> The purpose of unit testing is to ensure that the function obtains the
> expected result under specific input, that is, to ensure the correctness
> of APIs.
> All test case show in patch 5 and patch 6:
>   CryptoPkg/Test: Add unit test for CryptoBn
>   CryptoPkg/Test: Add unit test for CryptoEc
> 2. Fuzzing test:
> Various Fuzz Testing are employed across the all introduced APIs, and the
> test is used AFL (2.52b) and Libfuzzer (clang+llvm-11.0.0) as the fuzzer,
> based on HBFA.
> Fuzzing Pass Rate is 100%;
> The Code Coverage of CryptBn is 100%;
> The Code Coverage of CryptEc is 90.3%.
> All test case show in:
> https://github.com/liyi77/edk2-
> staging/tree/HBFA/HBFA/UefiHostFuzzTestCasePkg/TestCase/CryptoPkg
> 
> Tested-by: Yi Li <yi1.li@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> 
> Signed-off-by: Yi Li <yi1.li@intel.com>
> 
> Yi Li (7):
>   CryptoPkg: Add BigNum support
>   CryptoPkg: Add BigNum API to DXE and protocol
>   CryptoPkg: Add EC support
>   CryptoPkg: Add EC APIs to DXE and protocol
>   CryptoPkg/Test: Add unit test for CryptoBn
>   CryptoPkg/Test: Add unit test for CryptoEc
>   CryptoPkg: Run uncrustify tools on EC and BN change
> 
>  CryptoPkg/CryptoPkg.dsc                       |    2 +
>  CryptoPkg/Driver/Crypto.c                     | 1016 +++++++++++++-
>  CryptoPkg/Include/Library/BaseCryptLib.h      |  842 ++++++++++++
>  .../Pcd/PcdCryptoServiceFamilyEnable.h        |   55 +
>  .../Library/BaseCryptLib/BaseCryptLib.inf     |    3 +
>  CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   |  581 ++++++++
>  .../Library/BaseCryptLib/Bn/CryptBnNull.c     |  520 ++++++++
>  .../Library/BaseCryptLib/PeiCryptLib.inf      |    2 +
>  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   |  765 +++++++++++
>  .../Library/BaseCryptLib/Pk/CryptEcNull.c     |  496 +++++++
>  .../Library/BaseCryptLib/SmmCryptLib.inf      |    2 +
>  .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |    3 +
>  .../BaseCryptLibNull/BaseCryptLibNull.inf     |    2 +
>  .../Library/BaseCryptLibNull/Bn/CryptBnNull.c |  520 ++++++++
>  .../Library/BaseCryptLibNull/Pk/CryptEcNull.c |  496 +++++++
>  .../BaseCryptLibOnProtocolPpi/CryptLib.c      |  961 ++++++++++++++
>  CryptoPkg/Private/Protocol/Crypto.h           | 1176 ++++++++++++++---
>  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |    3 +
>  .../BaseCryptLib/BaseCryptLibUnitTests.c      |    2 +
>  .../UnitTest/Library/BaseCryptLib/BnTests.c   |  266 ++++
>  .../UnitTest/Library/BaseCryptLib/EcTests.c   |  290 ++++
>  .../Library/BaseCryptLib/TestBaseCryptLib.h   |    5 +
>  .../BaseCryptLib/TestBaseCryptLibHost.inf     |    2 +
>  .../BaseCryptLib/TestBaseCryptLibShell.inf    |    2 +
>  24 files changed, 7852 insertions(+), 160 deletions(-)
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
>  create mode 100644
> CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
>  create mode 100644
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
>  create mode 100644
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
> 
> --
> 2.31.1.windows.1


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

* Re: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib
  2022-09-20 16:01 ` [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib Yao, Jiewen
@ 2022-09-21  4:56   ` yi1 li
  2022-09-21 10:46     ` Yao, Jiewen
  0 siblings, 1 reply; 11+ messages in thread
From: yi1 li @ 2022-09-21  4:56 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Hi Jiewen,
Thanks for review, changes done.
Since both BN and EC extend many structures, splitting them will cause git conflicts,
I've adjusted the order of patches: Ec commits are based on Bn commits. Just convenient for merge.

Thanks,
Yi
-----Original Message-----
From: Yao, Jiewen <jiewen.yao@intel.com> 
Sent: Wednesday, September 21, 2022 12:02 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Xiaoyu Lu <xiaoyux.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib

Thanks for the patch. Please:
1) Separate BN and EC. Please submit 2 different patch sets. One for EC, the other for BN.
2) Please squash uncrustify tool update into previous patch. No need to submit a standalone one.
3) Please increase EDKII_CRYPTO_VERSION.

With that change, reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 7, 2022 4:29 PM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; 
> Wang, Jian J <jian.j.wang@intel.com>; Xiaoyu Lu 
> <xiaoyux.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to 
> BaseCryptLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> 
> Review PR: https://github.com/tianocore/edk2/pull/3309
> This patch sequence is used to add CryptBn and CryptEc library, which 
> are wrapped over OpenSSL. The implementation provides library 
> functions for EFI BaseCrypt protocol and EFI BaseCrypt Configuration Protocol.
> 
> All APIs passed unit test and fuzzing test, detail as:
> 1. Unit test:
> The purpose of unit testing is to ensure that the function obtains the 
> expected result under specific input, that is, to ensure the 
> correctness of APIs.
> All test case show in patch 5 and patch 6:
>   CryptoPkg/Test: Add unit test for CryptoBn
>   CryptoPkg/Test: Add unit test for CryptoEc 2. Fuzzing test:
> Various Fuzz Testing are employed across the all introduced APIs, and 
> the test is used AFL (2.52b) and Libfuzzer (clang+llvm-11.0.0) as the 
> fuzzer, based on HBFA.
> Fuzzing Pass Rate is 100%;
> The Code Coverage of CryptBn is 100%;
> The Code Coverage of CryptEc is 90.3%.
> All test case show in:
> https://github.com/liyi77/edk2-
> staging/tree/HBFA/HBFA/UefiHostFuzzTestCasePkg/TestCase/CryptoPkg
> 
> Tested-by: Yi Li <yi1.li@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> 
> Signed-off-by: Yi Li <yi1.li@intel.com>
> 
> Yi Li (7):
>   CryptoPkg: Add BigNum support
>   CryptoPkg: Add BigNum API to DXE and protocol
>   CryptoPkg: Add EC support
>   CryptoPkg: Add EC APIs to DXE and protocol
>   CryptoPkg/Test: Add unit test for CryptoBn
>   CryptoPkg/Test: Add unit test for CryptoEc
>   CryptoPkg: Run uncrustify tools on EC and BN change
> 
>  CryptoPkg/CryptoPkg.dsc                       |    2 +
>  CryptoPkg/Driver/Crypto.c                     | 1016 +++++++++++++-
>  CryptoPkg/Include/Library/BaseCryptLib.h      |  842 ++++++++++++
>  .../Pcd/PcdCryptoServiceFamilyEnable.h        |   55 +
>  .../Library/BaseCryptLib/BaseCryptLib.inf     |    3 +
>  CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   |  581 ++++++++
>  .../Library/BaseCryptLib/Bn/CryptBnNull.c     |  520 ++++++++
>  .../Library/BaseCryptLib/PeiCryptLib.inf      |    2 +
>  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   |  765 +++++++++++
>  .../Library/BaseCryptLib/Pk/CryptEcNull.c     |  496 +++++++
>  .../Library/BaseCryptLib/SmmCryptLib.inf      |    2 +
>  .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |    3 +
>  .../BaseCryptLibNull/BaseCryptLibNull.inf     |    2 +
>  .../Library/BaseCryptLibNull/Bn/CryptBnNull.c |  520 ++++++++  
> .../Library/BaseCryptLibNull/Pk/CryptEcNull.c |  496 +++++++
>  .../BaseCryptLibOnProtocolPpi/CryptLib.c      |  961 ++++++++++++++
>  CryptoPkg/Private/Protocol/Crypto.h           | 1176 ++++++++++++++---
>  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |    3 +
>  .../BaseCryptLib/BaseCryptLibUnitTests.c      |    2 +
>  .../UnitTest/Library/BaseCryptLib/BnTests.c   |  266 ++++
>  .../UnitTest/Library/BaseCryptLib/EcTests.c   |  290 ++++
>  .../Library/BaseCryptLib/TestBaseCryptLib.h   |    5 +
>  .../BaseCryptLib/TestBaseCryptLibHost.inf     |    2 +
>  .../BaseCryptLib/TestBaseCryptLibShell.inf    |    2 +
>  24 files changed, 7852 insertions(+), 160 deletions(-)  create mode 
> 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
>  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
>  create mode 100644
> CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
>  create mode 100644 
> CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
>  create mode 100644
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
>  create mode 100644
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
> 
> --
> 2.31.1.windows.1


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

* Re: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib
  2022-09-21  4:56   ` yi1 li
@ 2022-09-21 10:46     ` Yao, Jiewen
  0 siblings, 0 replies; 11+ messages in thread
From: Yao, Jiewen @ 2022-09-21 10:46 UTC (permalink / raw)
  To: Li, Yi1, devel@edk2.groups.io; +Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin

Thank you! I will take care of it.

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Wednesday, September 21, 2022 12:56 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: RE: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to
> BaseCryptLib
> 
> Hi Jiewen,
> Thanks for review, changes done.
> Since both BN and EC extend many structures, splitting them will cause git
> conflicts,
> I've adjusted the order of patches: Ec commits are based on Bn commits.
> Just convenient for merge.
> 
> Thanks,
> Yi
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Wednesday, September 21, 2022 12:02 AM
> To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Xiaoyu Lu
> <xiaoyux.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: RE: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to
> BaseCryptLib
> 
> Thanks for the patch. Please:
> 1) Separate BN and EC. Please submit 2 different patch sets. One for EC, the
> other for BN.
> 2) Please squash uncrustify tool update into previous patch. No need to
> submit a standalone one.
> 3) Please increase EDKII_CRYPTO_VERSION.
> 
> With that change, reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
> 
> > -----Original Message-----
> > From: Li, Yi1 <yi1.li@intel.com>
> > Sent: Wednesday, September 7, 2022 4:29 PM
> > To: devel@edk2.groups.io
> > Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > Wang, Jian J <jian.j.wang@intel.com>; Xiaoyu Lu
> > <xiaoyux.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> > Subject: [PATCH 0/7] CryptoPkg: Add BigNum and EC support to
> > BaseCryptLib
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3828
> >
> > Review PR: https://github.com/tianocore/edk2/pull/3309
> > This patch sequence is used to add CryptBn and CryptEc library, which
> > are wrapped over OpenSSL. The implementation provides library
> > functions for EFI BaseCrypt protocol and EFI BaseCrypt Configuration
> Protocol.
> >
> > All APIs passed unit test and fuzzing test, detail as:
> > 1. Unit test:
> > The purpose of unit testing is to ensure that the function obtains the
> > expected result under specific input, that is, to ensure the
> > correctness of APIs.
> > All test case show in patch 5 and patch 6:
> >   CryptoPkg/Test: Add unit test for CryptoBn
> >   CryptoPkg/Test: Add unit test for CryptoEc 2. Fuzzing test:
> > Various Fuzz Testing are employed across the all introduced APIs, and
> > the test is used AFL (2.52b) and Libfuzzer (clang+llvm-11.0.0) as the
> > fuzzer, based on HBFA.
> > Fuzzing Pass Rate is 100%;
> > The Code Coverage of CryptBn is 100%;
> > The Code Coverage of CryptEc is 90.3%.
> > All test case show in:
> > https://github.com/liyi77/edk2-
> > staging/tree/HBFA/HBFA/UefiHostFuzzTestCasePkg/TestCase/CryptoPkg
> >
> > Tested-by: Yi Li <yi1.li@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
> > Cc: Guomin Jiang <guomin.jiang@intel.com>
> >
> > Signed-off-by: Yi Li <yi1.li@intel.com>
> >
> > Yi Li (7):
> >   CryptoPkg: Add BigNum support
> >   CryptoPkg: Add BigNum API to DXE and protocol
> >   CryptoPkg: Add EC support
> >   CryptoPkg: Add EC APIs to DXE and protocol
> >   CryptoPkg/Test: Add unit test for CryptoBn
> >   CryptoPkg/Test: Add unit test for CryptoEc
> >   CryptoPkg: Run uncrustify tools on EC and BN change
> >
> >  CryptoPkg/CryptoPkg.dsc                       |    2 +
> >  CryptoPkg/Driver/Crypto.c                     | 1016 +++++++++++++-
> >  CryptoPkg/Include/Library/BaseCryptLib.h      |  842 ++++++++++++
> >  .../Pcd/PcdCryptoServiceFamilyEnable.h        |   55 +
> >  .../Library/BaseCryptLib/BaseCryptLib.inf     |    3 +
> >  CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c   |  581 ++++++++
> >  .../Library/BaseCryptLib/Bn/CryptBnNull.c     |  520 ++++++++
> >  .../Library/BaseCryptLib/PeiCryptLib.inf      |    2 +
> >  CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c   |  765 +++++++++++
> >  .../Library/BaseCryptLib/Pk/CryptEcNull.c     |  496 +++++++
> >  .../Library/BaseCryptLib/SmmCryptLib.inf      |    2 +
> >  .../BaseCryptLib/UnitTestHostBaseCryptLib.inf |    3 +
> >  .../BaseCryptLibNull/BaseCryptLibNull.inf     |    2 +
> >  .../Library/BaseCryptLibNull/Bn/CryptBnNull.c |  520 ++++++++
> > .../Library/BaseCryptLibNull/Pk/CryptEcNull.c |  496 +++++++
> >  .../BaseCryptLibOnProtocolPpi/CryptLib.c      |  961 ++++++++++++++
> >  CryptoPkg/Private/Protocol/Crypto.h           | 1176 ++++++++++++++---
> >  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc      |    3 +
> >  .../BaseCryptLib/BaseCryptLibUnitTests.c      |    2 +
> >  .../UnitTest/Library/BaseCryptLib/BnTests.c   |  266 ++++
> >  .../UnitTest/Library/BaseCryptLib/EcTests.c   |  290 ++++
> >  .../Library/BaseCryptLib/TestBaseCryptLib.h   |    5 +
> >  .../BaseCryptLib/TestBaseCryptLibHost.inf     |    2 +
> >  .../BaseCryptLib/TestBaseCryptLibShell.inf    |    2 +
> >  24 files changed, 7852 insertions(+), 160 deletions(-)  create mode
> > 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBn.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Bn/CryptBnNull.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
> >  create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
> >  create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Bn/CryptBnNull.c
> >  create mode 100644
> > CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
> >  create mode 100644
> > CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BnTests.c
> >  create mode 100644
> > CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
> >
> > --
> > 2.31.1.windows.1


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

end of thread, other threads:[~2022-09-21 10:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-07  8:29 [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib yi1 li
2022-09-07  8:29 ` [PATCH 1/7] CryptoPkg: Add BigNum support yi1 li
2022-09-07  8:29 ` [PATCH 2/7] CryptoPkg: Add BigNum API to DXE and protocol yi1 li
2022-09-07  8:29 ` [PATCH 3/7] CryptoPkg: Add EC support yi1 li
2022-09-07  8:29 ` [PATCH 4/7] CryptoPkg: Add EC APIs to DXE and protocol yi1 li
2022-09-07  8:29 ` [PATCH 5/7] CryptoPkg/Test: Add unit test for CryptoBn yi1 li
2022-09-07  8:29 ` [PATCH 6/7] CryptoPkg/Test: Add unit test for CryptoEc yi1 li
2022-09-07  8:29 ` [PATCH 7/7] CryptoPkg: Run uncrustify tools on EC and BN change yi1 li
2022-09-20 16:01 ` [PATCH 0/7] CryptoPkg: Add BigNum and EC support to BaseCryptLib Yao, Jiewen
2022-09-21  4:56   ` yi1 li
2022-09-21 10:46     ` Yao, Jiewen

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