public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls
@ 2024-04-16  7:51 Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 1/9] CryptoPkg: Add AeadAesGcm " Wenxing Hou
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Add AeadAesGcm/Pem(only RSA)/X509(only RSA)/More RSA/PKCS5
/pKCS7/Authenticode/Timestamp implementation based on Mbedtls.

The patch has passed the EDKII CI check:
https://github.com/tianocore/edk2/pull/5552

And the patch has passed unit_test in EDKII and integration test for platform.
And the patch hass passed the fuzz test:
https://github.com/tianocore/edk2-staging/commit/4f19398053c92e4f7791d468a184530b6ab89128

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>

Wenxing Hou (9):
  CryptoPkg: Add AeadAesGcm based on Mbedtls
  CryptoPkg: Add rand function for BaseCryptLibMbedTls
  CryptoPkg: Add Pem APIs based on Mbedtls
  CryptoPkg: Add X509 functions based on Mbedtls
  CryptoPkg: Add Pkcs7 related functions based on Mbedtls
  CryptoPkg: Add Pkcs5 functions based on Mbedtls
  CryptoPkg: Add more RSA related functions based on Mbedtls
  CryptoPkg: Add AuthenticodeVerify based on Mbedtls
  CryptoPkg: Add ImageTimestampVerify based on Mbedtls

 CryptoPkg/CryptoPkg.ci.yaml                   |    1 +
 .../Cipher/CryptAeadAesGcm.c                  |  227 ++
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |   49 +
 .../BaseCryptLibMbedTls/Pem/CryptPem.c        |  138 ++
 .../Pk/CryptAuthenticode.c                    |  214 ++
 .../BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c   |  278 +++
 .../BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c |  100 +
 .../Pk/CryptPkcs7Internal.h                   |   20 +-
 .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c   |  615 ++++++
 .../Pk/CryptPkcs7VerifyBase.c                 |  113 +
 .../Pk/CryptPkcs7VerifyCommon.c               | 1315 +++++++++++
 .../Pk/CryptPkcs7VerifyEku.c                  |  689 ++++++
 .../BaseCryptLibMbedTls/Pk/CryptRsaExt.c      |  346 +++
 .../BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c  |  137 ++
 .../Library/BaseCryptLibMbedTls/Pk/CryptTs.c  |  381 ++++
 .../BaseCryptLibMbedTls/Pk/CryptX509.c        | 1924 +++++++++++++++++
 .../BaseCryptLibMbedTls/Rand/CryptRand.c      |  105 +
 .../BaseCryptLibMbedTls/Rand/CryptRandTsc.c   |  105 +
 18 files changed, 6745 insertions(+), 12 deletions(-)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c

-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117857): https://edk2.groups.io/g/devel/message/117857
Mute This Topic: https://groups.io/mt/105552830/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 1/9] CryptoPkg: Add AeadAesGcm based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 2/9] CryptoPkg: Add rand function for BaseCryptLibMbedTls Wenxing Hou
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

AeadAesGcm implementation based on Mbedtls.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../Cipher/CryptAeadAesGcm.c                  | 227 ++++++++++++++++++
 1 file changed, 227 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
new file mode 100644
index 0000000000..73104e42fa
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
@@ -0,0 +1,227 @@
+/** @file
+  AEAD (AES-GCM) Wrapper Implementation over MbedTLS.
+
+  RFC 5116 - An Interface and Algorithms for Authenticated Encryption
+  NIST SP800-38d - Cipher Modes of Operation: Galois / Counter Mode(GCM) and GMAC
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/gcm.h>
+
+/**
+  Performs AEAD AES-GCM authenticated encryption on a data buffer and additional authenticated data (AAD).
+
+  IvSize must be 12, otherwise FALSE is returned.
+  KeySize must be 16, 24 or 32, otherwise FALSE is returned.
+  TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned.
+
+  @param[in]   Key         Pointer to the encryption key.
+  @param[in]   KeySize     Size of the encryption key in bytes.
+  @param[in]   Iv          Pointer to the IV value.
+  @param[in]   IvSize      Size of the IV value in bytes.
+  @param[in]   AData       Pointer to the additional authenticated data (AAD).
+  @param[in]   ADataSize   Size of the additional authenticated data (AAD) in bytes.
+  @param[in]   DataIn      Pointer to the input data buffer to be encrypted.
+  @param[in]   DataInSize  Size of the input data buffer in bytes.
+  @param[out]  TagOut      Pointer to a buffer that receives the authentication tag output.
+  @param[in]   TagSize     Size of the authentication tag in bytes.
+  @param[out]  DataOut     Pointer to a buffer that receives the encryption output.
+  @param[out]  DataOutSize Size of the output data buffer in bytes.
+
+  @retval TRUE   AEAD AES-GCM authenticated encryption succeeded.
+  @retval FALSE  AEAD AES-GCM authenticated encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AeadAesGcmEncrypt (
+  IN   CONST UINT8  *Key,
+  IN   UINTN        KeySize,
+  IN   CONST UINT8  *Iv,
+  IN   UINTN        IvSize,
+  IN   CONST UINT8  *AData,
+  IN   UINTN        ADataSize,
+  IN   CONST UINT8  *DataIn,
+  IN   UINTN        DataInSize,
+  OUT  UINT8        *TagOut,
+  IN   UINTN        TagSize,
+  OUT  UINT8        *DataOut,
+  OUT  UINTN        *DataOutSize
+  )
+{
+  mbedtls_gcm_context  ctx;
+  INT32                Ret;
+
+  if (DataInSize > INT_MAX) {
+    return FALSE;
+  }
+
+  if (ADataSize > INT_MAX) {
+    return FALSE;
+  }
+
+  if (IvSize != 12) {
+    return FALSE;
+  }
+
+  switch (KeySize) {
+    case 16:
+    case 24:
+    case 32:
+      break;
+    default:
+      return FALSE;
+  }
+
+  if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) {
+    return FALSE;
+  }
+
+  if (DataOutSize != NULL) {
+    if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) {
+      return FALSE;
+    }
+  }
+
+  mbedtls_gcm_init (&ctx);
+
+  Ret = mbedtls_gcm_setkey (&ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8));
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  Ret = mbedtls_gcm_crypt_and_tag (
+          &ctx,
+          MBEDTLS_GCM_ENCRYPT,
+          (UINT32)DataInSize,
+          Iv,
+          (UINT32)IvSize,
+          AData,
+          (UINT32)ADataSize,
+          DataIn,
+          DataOut,
+          TagSize,
+          TagOut
+          );
+  mbedtls_gcm_free (&ctx);
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  if (DataOutSize != NULL) {
+    *DataOutSize = DataInSize;
+  }
+
+  return TRUE;
+}
+
+/**
+  Performs AEAD AES-GCM authenticated decryption on a data buffer and additional authenticated data (AAD).
+
+  IvSize must be 12, otherwise FALSE is returned.
+  KeySize must be 16, 24 or 32, otherwise FALSE is returned.
+  TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned.
+  If additional authenticated data verification fails, FALSE is returned.
+
+  @param[in]   Key         Pointer to the encryption key.
+  @param[in]   KeySize     Size of the encryption key in bytes.
+  @param[in]   Iv          Pointer to the IV value.
+  @param[in]   IvSize      Size of the IV value in bytes.
+  @param[in]   AData       Pointer to the additional authenticated data (AAD).
+  @param[in]   ADataSize   Size of the additional authenticated data (AAD) in bytes.
+  @param[in]   DataIn      Pointer to the input data buffer to be decrypted.
+  @param[in]   DataInSize  Size of the input data buffer in bytes.
+  @param[in]   Tag         Pointer to a buffer that contains the authentication tag.
+  @param[in]   TagSize     Size of the authentication tag in bytes.
+  @param[out]  DataOut     Pointer to a buffer that receives the decryption output.
+  @param[out]  DataOutSize Size of the output data buffer in bytes.
+
+  @retval TRUE   AEAD AES-GCM authenticated decryption succeeded.
+  @retval FALSE  AEAD AES-GCM authenticated decryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AeadAesGcmDecrypt (
+  IN   CONST UINT8  *Key,
+  IN   UINTN        KeySize,
+  IN   CONST UINT8  *Iv,
+  IN   UINTN        IvSize,
+  IN   CONST UINT8  *AData,
+  IN   UINTN        ADataSize,
+  IN   CONST UINT8  *DataIn,
+  IN   UINTN        DataInSize,
+  IN   CONST UINT8  *Tag,
+  IN   UINTN        TagSize,
+  OUT  UINT8        *DataOut,
+  OUT  UINTN        *DataOutSize
+  )
+{
+  mbedtls_gcm_context  ctx;
+  INT32                Ret;
+
+  if (DataInSize > INT_MAX) {
+    return FALSE;
+  }
+
+  if (ADataSize > INT_MAX) {
+    return FALSE;
+  }
+
+  if (IvSize != 12) {
+    return FALSE;
+  }
+
+  switch (KeySize) {
+    case 16:
+    case 24:
+    case 32:
+      break;
+    default:
+      return FALSE;
+  }
+
+  if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) {
+    return FALSE;
+  }
+
+  if (DataOutSize != NULL) {
+    if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) {
+      return FALSE;
+    }
+  }
+
+  mbedtls_gcm_init (&ctx);
+
+  Ret = mbedtls_gcm_setkey (&ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8));
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  Ret = mbedtls_gcm_auth_decrypt (
+          &ctx,
+          (UINT32)DataInSize,
+          Iv,
+          (UINT32)IvSize,
+          AData,
+          (UINT32)ADataSize,
+          Tag,
+          (UINT32)TagSize,
+          DataIn,
+          DataOut
+          );
+  mbedtls_gcm_free (&ctx);
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  if (DataOutSize != NULL) {
+    *DataOutSize = DataInSize;
+  }
+
+  return TRUE;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117858): https://edk2.groups.io/g/devel/message/117858
Mute This Topic: https://groups.io/mt/105552831/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 2/9] CryptoPkg: Add rand function for BaseCryptLibMbedTls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 1/9] CryptoPkg: Add AeadAesGcm " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 3/9] CryptoPkg: Add Pem APIs based on Mbedtls Wenxing Hou
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Add rand function for BaseCryptLibMbedTls.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 CryptoPkg/CryptoPkg.ci.yaml                   |   1 +
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |  16 +++
 .../BaseCryptLibMbedTls/Rand/CryptRand.c      | 105 ++++++++++++++++++
 .../BaseCryptLibMbedTls/Rand/CryptRandTsc.c   | 105 ++++++++++++++++++
 4 files changed, 227 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c

diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
index b601bcf85c..2fbc021c84 100644
--- a/CryptoPkg/CryptoPkg.ci.yaml
+++ b/CryptoPkg/CryptoPkg.ci.yaml
@@ -45,6 +45,7 @@
             "Library/Include/stdint.h",
             "Library/Include/stubs-32.h",
             "Library/Include/inttypes.h",
+            "Library/BaseCryptLibMbedTls/InternalCryptLib.h",
             # These directories contain auto-generated OpenSSL content
             "Library/OpensslLib",
             "Library/IntrinsicLib",
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
index 039aa32028..e2c7e42ecb 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
@@ -22,4 +22,20 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 //
 #include <mbedtls/mbedtls_config.h>
 
+/**
+  The MbedTLS function f_rng, which MbedtlsRand implements.
+
+  @param[in]   rng_state Not used, just for compatibility with mbedlts.
+  @param[out]  output  Pointer to buffer to receive random value.
+  @param[in]   len    Size of random bytes to generate.
+
+  @retval 0      Pseudorandom byte stream generated successfully.
+  @retval Non-0  Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INTN
+MbedtlsRand (
+  VOID   *rng_state,
+  UINT8  *output,
+  UINTN  len
+  );
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
new file mode 100644
index 0000000000..081b413740
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
@@ -0,0 +1,105 @@
+/** @file
+  Pseudorandom Number Generator Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <Library/RngLib.h>
+
+/**
+  Sets up the seed value for the pseudorandom number generator.
+
+  This function sets up the seed value for the pseudorandom number generator.
+  If Seed is not NULL, then the seed passed in is used.
+  If Seed is NULL, then default seed is used.
+
+  @param[in]  Seed      Pointer to seed value.
+                        If NULL, default seed is used.
+  @param[in]  SeedSize  Size of seed value.
+                        If Seed is NULL, this parameter is ignored.
+
+  @retval TRUE   Pseudorandom number generator has enough entropy for random generation.
+  @retval FALSE  Pseudorandom number generator does not have enough entropy for random generation.
+
+**/
+BOOLEAN
+EFIAPI
+RandomSeed (
+  IN  CONST  UINT8  *Seed  OPTIONAL,
+  IN  UINTN         SeedSize
+  )
+{
+  return TRUE;
+}
+
+/**
+  Generates a pseudorandom byte stream of the specified size.
+
+  If Output is NULL, then return FALSE.
+
+  @param[out]  Output  Pointer to buffer to receive random value.
+  @param[in]   Size    Size of random bytes to generate.
+
+  @retval TRUE   Pseudorandom byte stream generated successfully.
+  @retval FALSE  Pseudorandom number generator fails to generate due to lack of entropy.
+
+**/
+BOOLEAN
+EFIAPI
+RandomBytes (
+  OUT  UINT8  *Output,
+  IN   UINTN  Size
+  )
+{
+  BOOLEAN  Ret;
+  UINT64   TempRand;
+
+  Ret = FALSE;
+
+  while (Size > 0) {
+    // Use RngLib to get random number
+    Ret = GetRandomNumber64 (&TempRand);
+
+    if (!Ret) {
+      return Ret;
+    }
+
+    if (Size >= sizeof (TempRand)) {
+      *((UINT64 *)Output) = TempRand;
+      Output             += sizeof (UINT64);
+      Size               -= sizeof (TempRand);
+    } else {
+      CopyMem (Output, &TempRand, Size);
+      Size = 0;
+    }
+  }
+
+  return Ret;
+}
+
+/**
+  The MbedTLS function f_rng, which MbedtlsRand implements.
+
+  @param[in]   rng_state Not used, just for compatibility with mbedlts.
+  @param[out]  output  Pointer to buffer to receive random value.
+  @param[in]   len    Size of random bytes to generate.
+
+  @retval 0      Pseudorandom byte stream generated successfully.
+  @retval Non-0  Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INTN
+MbedtlsRand (
+  VOID   *rng_state,
+  UINT8  *output,
+  UINTN  len
+  )
+{
+  BOOLEAN  Result;
+
+  Result = RandomBytes (output, len);
+
+  return Result ? 0 : -1;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c
new file mode 100644
index 0000000000..081b413740
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c
@@ -0,0 +1,105 @@
+/** @file
+  Pseudorandom Number Generator Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <Library/RngLib.h>
+
+/**
+  Sets up the seed value for the pseudorandom number generator.
+
+  This function sets up the seed value for the pseudorandom number generator.
+  If Seed is not NULL, then the seed passed in is used.
+  If Seed is NULL, then default seed is used.
+
+  @param[in]  Seed      Pointer to seed value.
+                        If NULL, default seed is used.
+  @param[in]  SeedSize  Size of seed value.
+                        If Seed is NULL, this parameter is ignored.
+
+  @retval TRUE   Pseudorandom number generator has enough entropy for random generation.
+  @retval FALSE  Pseudorandom number generator does not have enough entropy for random generation.
+
+**/
+BOOLEAN
+EFIAPI
+RandomSeed (
+  IN  CONST  UINT8  *Seed  OPTIONAL,
+  IN  UINTN         SeedSize
+  )
+{
+  return TRUE;
+}
+
+/**
+  Generates a pseudorandom byte stream of the specified size.
+
+  If Output is NULL, then return FALSE.
+
+  @param[out]  Output  Pointer to buffer to receive random value.
+  @param[in]   Size    Size of random bytes to generate.
+
+  @retval TRUE   Pseudorandom byte stream generated successfully.
+  @retval FALSE  Pseudorandom number generator fails to generate due to lack of entropy.
+
+**/
+BOOLEAN
+EFIAPI
+RandomBytes (
+  OUT  UINT8  *Output,
+  IN   UINTN  Size
+  )
+{
+  BOOLEAN  Ret;
+  UINT64   TempRand;
+
+  Ret = FALSE;
+
+  while (Size > 0) {
+    // Use RngLib to get random number
+    Ret = GetRandomNumber64 (&TempRand);
+
+    if (!Ret) {
+      return Ret;
+    }
+
+    if (Size >= sizeof (TempRand)) {
+      *((UINT64 *)Output) = TempRand;
+      Output             += sizeof (UINT64);
+      Size               -= sizeof (TempRand);
+    } else {
+      CopyMem (Output, &TempRand, Size);
+      Size = 0;
+    }
+  }
+
+  return Ret;
+}
+
+/**
+  The MbedTLS function f_rng, which MbedtlsRand implements.
+
+  @param[in]   rng_state Not used, just for compatibility with mbedlts.
+  @param[out]  output  Pointer to buffer to receive random value.
+  @param[in]   len    Size of random bytes to generate.
+
+  @retval 0      Pseudorandom byte stream generated successfully.
+  @retval Non-0  Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INTN
+MbedtlsRand (
+  VOID   *rng_state,
+  UINT8  *output,
+  UINTN  len
+  )
+{
+  BOOLEAN  Result;
+
+  Result = RandomBytes (output, len);
+
+  return Result ? 0 : -1;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117859): https://edk2.groups.io/g/devel/message/117859
Mute This Topic: https://groups.io/mt/105552832/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 3/9] CryptoPkg: Add Pem APIs based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 1/9] CryptoPkg: Add AeadAesGcm " Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 2/9] CryptoPkg: Add rand function for BaseCryptLibMbedTls Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 4/9] CryptoPkg: Add X509 functions " Wenxing Hou
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Implement Pem API based on Mbedtls.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/Pem/CryptPem.c        | 138 ++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
new file mode 100644
index 0000000000..def1478b8b
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
@@ -0,0 +1,138 @@
+/** @file
+  PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pem.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecdsa.h>
+
+/**
+  Retrieve the RSA Private Key from the password-protected PEM key data.
+
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.
+  @param[in]  PemSize      Size of the PEM key data in bytes.
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.
+  @param[out] RsaContext   Pointer to new-generated RSA context which contain the retrieved
+                           RSA private key component. Use RsaFree() function to free the
+                           resource.
+
+  If PemData is NULL, then return FALSE.
+  If RsaContext is NULL, then return FALSE.
+
+  @retval  TRUE   RSA Private Key was retrieved successfully.
+  @retval  FALSE  Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetPrivateKeyFromPem (
+  IN   CONST UINT8  *PemData,
+  IN   UINTN        PemSize,
+  IN   CONST CHAR8  *Password,
+  OUT  VOID         **RsaContext
+  )
+{
+  INT32                Ret;
+  mbedtls_pk_context   pk;
+  mbedtls_rsa_context  *rsa;
+  UINT8                *NewPemData;
+  UINTN                PasswordLen;
+
+  if ((PemData == NULL) || (RsaContext == NULL) || (PemSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  NewPemData = NULL;
+  if (PemData[PemSize - 1] != 0) {
+    NewPemData = AllocateZeroPool (PemSize + 1);
+    if (NewPemData == NULL) {
+      return FALSE;
+    }
+
+    CopyMem (NewPemData, PemData, PemSize + 1);
+    NewPemData[PemSize] = 0;
+    PemData             = NewPemData;
+    PemSize            += 1;
+  }
+
+  mbedtls_pk_init (&pk);
+
+  if (Password != NULL) {
+    PasswordLen = AsciiStrLen (Password);
+  } else {
+    PasswordLen = 0;
+  }
+
+  Ret = mbedtls_pk_parse_key (&pk, PemData, PemSize, (CONST UINT8 *)Password, PasswordLen, NULL, NULL);
+
+  if (NewPemData != NULL) {
+    FreePool (NewPemData);
+    NewPemData = NULL;
+  }
+
+  if (Ret != 0) {
+    mbedtls_pk_free (&pk);
+    return FALSE;
+  }
+
+  if (mbedtls_pk_get_type (&pk) != MBEDTLS_PK_RSA) {
+    mbedtls_pk_free (&pk);
+    return FALSE;
+  }
+
+  rsa = RsaNew ();
+  if (rsa == NULL) {
+    mbedtls_pk_free (&pk);
+    return FALSE;
+  }
+
+  Ret = mbedtls_rsa_copy (rsa, mbedtls_pk_rsa (pk));
+  if (Ret != 0) {
+    RsaFree (rsa);
+    mbedtls_pk_free (&pk);
+    return FALSE;
+  }
+
+  mbedtls_pk_free (&pk);
+
+  *RsaContext = rsa;
+  return TRUE;
+}
+
+/**
+  Retrieve the EC Private Key from the password-protected PEM key data.
+
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.
+  @param[in]  PemSize      Size of the PEM key data in bytes.
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved
+                           EC private key component. Use EcFree() function to free the
+                           resource.
+
+  If PemData is NULL, then return FALSE.
+  If EcContext is NULL, then return FALSE.
+
+  @retval  TRUE   EC Private Key was retrieved successfully.
+  @retval  FALSE  Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+  IN   CONST UINT8  *PemData,
+  IN   UINTN        PemSize,
+  IN   CONST CHAR8  *Password,
+  OUT  VOID         **EcContext
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117860): https://edk2.groups.io/g/devel/message/117860
Mute This Topic: https://groups.io/mt/105552833/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 4/9] CryptoPkg: Add X509 functions based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (2 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 3/9] CryptoPkg: Add Pem APIs based on Mbedtls Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related " Wenxing Hou
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

X.509 Certificate Handler Wrapper Implementation over MbedTLS.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/Pk/CryptX509.c        | 1924 +++++++++++++++++
 1 file changed, 1924 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
new file mode 100644
index 0000000000..791fe78cd2
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
@@ -0,0 +1,1924 @@
+/** @file
+  X.509 Certificate Handler Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecdsa.h>
+
+///
+/// OID
+///
+STATIC CONST UINT8  OID_commonName[] = {
+  0x55, 0x04, 0x03
+};
+STATIC CONST UINT8  OID_organizationName[] = {
+  0x55, 0x04, 0x0A
+};
+STATIC CONST UINT8  OID_extKeyUsage[] = {
+  0x55, 0x1D, 0x25
+};
+STATIC CONST UINT8  OID_BasicConstraints[] = {
+  0x55, 0x1D, 0x13
+};
+
+/* Profile for backward compatibility. Allows RSA 1024, unlike the default
+   profile. */
+STATIC mbedtls_x509_crt_profile  gCompatProfile =
+{
+  /* Hashes from SHA-256 and above. Note that this selection
+   * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),
+  0xFFFFFFF,       /* Any PK alg    */
+
+  /* Curves at or above 128-bit security level. Note that this selection
+   * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |
+  0,
+  1024,
+};
+
+/**
+  Construct a X509 object from DER-encoded certificate data.
+
+  If Cert is NULL, then return FALSE.
+  If SingleX509Cert is NULL, then return FALSE.
+
+  @param[in]  Cert            Pointer to the DER-encoded certificate data.
+  @param[in]  CertSize        The size of certificate data in bytes.
+  @param[out] SingleX509Cert  The generated X509 object.
+
+  @retval     TRUE            The X509 object generation succeeded.
+  @retval     FALSE           The operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificate (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       **SingleX509Cert
+  )
+{
+  mbedtls_x509_crt  *MbedTlsCert;
+  INT32             Ret;
+
+  if ((Cert == NULL) || (SingleX509Cert == NULL) || (CertSize == 0)) {
+    return FALSE;
+  }
+
+  MbedTlsCert = AllocateZeroPool (sizeof (mbedtls_x509_crt));
+  if (MbedTlsCert == NULL) {
+    return FALSE;
+  }
+
+  mbedtls_x509_crt_init (MbedTlsCert);
+
+  *SingleX509Cert = (UINT8 *)(VOID *)MbedTlsCert;
+  Ret             = mbedtls_x509_crt_parse_der (MbedTlsCert, Cert, CertSize);
+
+  return Ret == 0;
+}
+
+/**
+  Construct a X509 stack object from a list of DER-encoded certificate data.
+
+  If X509Stack is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in, out]  X509Stack  On input, pointer to an existing or NULL X509 stack object.
+                              On output, pointer to the X509 stack object with new
+                              inserted X509 certificate.
+  @param[in]       Args       VA_LIST marker for the variable argument list.
+                              A list of DER-encoded single certificate data followed
+                              by certificate size. A NULL terminates the list. The
+                              pairs are the arguments to X509ConstructCertificate().
+
+  @retval     TRUE            The X509 stack construction succeeded.
+  @retval     FALSE           The construction operation failed.
+  @retval     FALSE           This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificateStackV (
+  IN OUT UINT8  **X509Stack,
+  IN VA_LIST    Args
+  )
+{
+  UINT8             *Cert;
+  UINTN             CertSize;
+  INT32             Index;
+  INT32             Ret;
+  mbedtls_x509_crt  *Crt;
+
+  if (X509Stack == NULL) {
+    return FALSE;
+  }
+
+  Ret = 0;
+  Crt = (mbedtls_x509_crt *)*X509Stack;
+  if (Crt == NULL) {
+    Crt = AllocateZeroPool (sizeof (mbedtls_x509_crt));
+    if (Crt == NULL) {
+      return FALSE;
+    }
+
+    mbedtls_x509_crt_init (Crt);
+    *X509Stack = (UINT8 *)Crt;
+  }
+
+  for (Index = 0; ; Index++) {
+    //
+    // If Cert is NULL, then it is the end of the list.
+    //
+    Cert = VA_ARG (Args, UINT8 *);
+    if (Cert == NULL) {
+      break;
+    }
+
+    CertSize = VA_ARG (Args, UINTN);
+    if (CertSize == 0) {
+      break;
+    }
+
+    Ret = mbedtls_x509_crt_parse_der (Crt, Cert, CertSize);
+
+    if (Ret != 0) {
+      break;
+    }
+  }
+
+  return Ret == 0;
+}
+
+/**
+  Construct a X509 stack object from a list of DER-encoded certificate data.
+
+  If X509Stack is NULL, then return FALSE.
+
+  @param[in, out]  X509Stack  On input, pointer to an existing or NULL X509 stack object.
+                              On output, pointer to the X509 stack object with new
+                              inserted X509 certificate.
+  @param           ...        A list of DER-encoded single certificate data followed
+                              by certificate size. A NULL terminates the list. The
+                              pairs are the arguments to X509ConstructCertificate().
+
+  @retval     TRUE            The X509 stack construction succeeded.
+  @retval     FALSE           The construction operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificateStack (
+  IN OUT UINT8  **X509Stack,
+  ...
+  )
+{
+  VA_LIST  Args;
+  BOOLEAN  Result;
+
+  VA_START (Args, X509Stack);
+  Result = X509ConstructCertificateStackV (X509Stack, Args);
+  VA_END (Args);
+  return Result;
+}
+
+/**
+  Release the specified X509 object.
+
+  If X509Cert is NULL, then return FALSE.
+
+  @param[in]  X509Cert  Pointer to the X509 object to be released.
+
+**/
+VOID
+EFIAPI
+X509Free (
+  IN VOID  *X509Cert
+  )
+{
+  if (X509Cert != NULL) {
+    mbedtls_x509_crt_free (X509Cert);
+    FreePool (X509Cert);
+  }
+}
+
+/**
+  Release the specified X509 stack object.
+
+  If X509Stack is NULL, then return FALSE.
+
+  @param[in]  X509Stack  Pointer to the X509 stack object to be released.
+
+**/
+VOID
+EFIAPI
+X509StackFree (
+  IN VOID  *X509Stack
+  )
+{
+  if (X509Stack == NULL) {
+    return;
+  }
+
+  mbedtls_x509_crt_free (X509Stack);
+}
+
+/**
+  Retrieve the tag and length of the tag.
+
+  @param Ptr      The position in the ASN.1 data
+  @param End      End of data
+  @param Length   The variable that will receive the length
+  @param Tag      The expected tag
+
+  @retval      TRUE   Get tag successful
+  @retval      FALSe  Failed to get tag or tag not match
+**/
+BOOLEAN
+EFIAPI
+Asn1GetTag (
+  IN OUT UINT8    **Ptr,
+  IN CONST UINT8  *End,
+  OUT UINTN       *Length,
+  IN UINT32       Tag
+  )
+{
+  if (mbedtls_asn1_get_tag (Ptr, End, Length, (INT32)Tag) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Retrieve the subject bytes from one X.509 certificate.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[out]     CertSubject  Pointer to the retrieved certificate subject bytes.
+  @param[in, out] SubjectSize  The size in bytes of the CertSubject buffer on input,
+                               and the size of buffer returned CertSubject on output.
+
+  If Cert is NULL, then return FALSE.
+  If SubjectSize is NULL, then return FALSE.
+
+  @retval  TRUE   The certificate subject retrieved successfully.
+  @retval  FALSE  Invalid certificate, or the SubjectSize is too small for the result.
+                  The SubjectSize will be updated with the required size.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetSubjectName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       *CertSubject,
+  IN OUT UINTN    *SubjectSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    if (CertSubject != NULL) {
+      CopyMem (CertSubject, Crt.subject_raw.p, Crt.subject_raw.len);
+    }
+
+    *SubjectSize = Crt.subject_raw.len;
+  }
+
+  mbedtls_x509_crt_free (&Crt);
+
+  return Ret == 0;
+}
+
+/**
+  Retrieve a string from one X.509 certificate base on the Request_NID.
+
+  @param[in]      Name             mbedtls_x509_name
+  @param[in]      Oid              Oid
+  @param[in]      OidSize          Size of Oid
+  @param[in,out]     CommonName    Buffer to contain the retrieved certificate common
+                                   name string (UTF8). At most CommonNameSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,
+                                   and the size of buffer returned CommonName on output.
+                                   If CommonName is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If CommonNameSize is NULL.
+                                   If CommonName is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no NID Name entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetNIDName (
+  IN mbedtls_x509_name  *Name,
+  IN CHAR8              *Oid,
+  IN UINTN              OidSize,
+  IN OUT CHAR8          *CommonName OPTIONAL,
+  IN OUT UINTN          *CommonNameSize
+  )
+{
+  CONST mbedtls_asn1_named_data  *data;
+
+  data = mbedtls_asn1_find_named_data (Name, Oid, OidSize);
+  if (data != NULL) {
+    if (*CommonNameSize <= data->val.len) {
+      *CommonNameSize = data->val.len + 1;
+      return RETURN_BUFFER_TOO_SMALL;
+    }
+
+    if (CommonName != NULL) {
+      CopyMem (CommonName, data->val.p, data->val.len);
+      CommonName[data->val.len] = '\0';
+    }
+
+    *CommonNameSize = data->val.len + 1;
+    return RETURN_SUCCESS;
+  } else {
+    return RETURN_NOT_FOUND;
+  }
+}
+
+/**
+  Get X509 SubjectNIDName by OID.
+
+  @param[in]      Cert             certificate
+  @param[in]      CertSize         certificate size.
+  @param[in]      Oid              Oid
+  @param[in]      OidSize          Size of Oid
+  @param[in,out]  CommonName       Buffer to contain the retrieved certificate common
+                                   name string (UTF8). At most CommonNameSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,
+                                   and the size of buffer returned CommonName on output.
+                                   If CommonName is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If CommonNameSize is NULL.
+                                   If CommonName is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no NID Name entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetSubjectNIDName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  IN CHAR8        *Oid,
+  IN UINTN        OidSize,
+  IN OUT CHAR8    *CommonName OPTIONAL,
+  IN OUT UINTN    *CommonNameSize
+  )
+{
+  mbedtls_x509_crt   Crt;
+  INT32              Ret;
+  mbedtls_x509_name  *Name;
+  RETURN_STATUS      ReturnStatus;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  ReturnStatus = RETURN_INVALID_PARAMETER;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    Name         = &(Crt.subject);
+    ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize);
+  }
+
+  mbedtls_x509_crt_free (&Crt);
+
+  return ReturnStatus;
+}
+
+/**
+  Get X509 IssuerNIDName by OID.
+
+  @param[in]      Cert             certificate
+  @param[in]      CertSize         certificate size.
+  @param[in]      Oid              Oid
+  @param[in]      OidSize          Size of Oid
+  @param[out]     CommonName       Buffer to contain the retrieved certificate common
+                                   name string (UTF8). At most CommonNameSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,
+                                   and the size of buffer returned CommonName on output.
+                                   If CommonName is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If CommonNameSize is NULL.
+                                   If CommonName is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no NID Name entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetIssuerNIDName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  IN CHAR8        *Oid,
+  IN UINTN        OidSize,
+  OUT CHAR8       *CommonName OPTIONAL,
+  IN OUT UINTN    *CommonNameSize
+  )
+{
+  mbedtls_x509_crt   Crt;
+  INT32              Ret;
+  mbedtls_x509_name  *Name;
+  RETURN_STATUS      ReturnStatus;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  ReturnStatus = RETURN_INVALID_PARAMETER;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    Name         = &(Crt.issuer);
+    ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize);
+  }
+
+  mbedtls_x509_crt_free (&Crt);
+
+  return ReturnStatus;
+}
+
+/**
+  Retrieve the common name (CN) string from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     CommonName       Buffer to contain the retrieved certificate common
+                                   name string. At most CommonNameSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,
+                                   and the size of buffer returned CommonName on output.
+                                   If CommonName is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If CommonNameSize is NULL.
+                                   If CommonName is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no CommonName entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetCommonName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT CHAR8       *CommonName OPTIONAL,
+  IN OUT UINTN    *CommonNameSize
+  )
+{
+  return InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize);
+}
+
+/**
+  Retrieve the organization name (O) string from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     NameBuffer       Buffer to contain the retrieved certificate organization
+                                   name string. At most NameBufferSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  NameBufferSize   The size in bytes of the Name buffer on input,
+                                   and the size of buffer returned Name on output.
+                                   If NameBuffer is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate Organization Name retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If NameBufferSize is NULL.
+                                   If NameBuffer is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no Organization Name entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the NameBuffer is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetOrganizationName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT CHAR8       *NameBuffer OPTIONAL,
+  IN OUT UINTN    *NameBufferSize
+  )
+{
+  return InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize);
+}
+
+/**
+  Retrieve the RSA Public Key from one DER-encoded X509 certificate.
+
+  @param[in]  Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]  CertSize     Size of the X509 certificate in bytes.
+  @param[out] RsaContext   Pointer to new-generated RSA context which contain the retrieved
+                           RSA public key component. Use RsaFree() function to free the
+                           resource.
+
+  If Cert is NULL, then return FALSE.
+  If RsaContext is NULL, then return FALSE.
+
+  @retval  TRUE   RSA Public Key was retrieved successfully.
+  @retval  FALSE  Fail to retrieve RSA public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetPublicKeyFromX509 (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT VOID        **RsaContext
+  )
+{
+  mbedtls_x509_crt     crt;
+  mbedtls_rsa_context  *rsa;
+  INT32                Ret;
+
+  mbedtls_x509_crt_init (&crt);
+
+  if (mbedtls_x509_crt_parse_der (&crt, Cert, CertSize) != 0) {
+    return FALSE;
+  }
+
+  if (mbedtls_pk_get_type (&crt.pk) != MBEDTLS_PK_RSA) {
+    mbedtls_x509_crt_free (&crt);
+    return FALSE;
+  }
+
+  rsa = RsaNew ();
+  if (rsa == NULL) {
+    mbedtls_x509_crt_free (&crt);
+    return FALSE;
+  }
+
+  Ret = mbedtls_rsa_copy (rsa, mbedtls_pk_rsa (crt.pk));
+  if (Ret != 0) {
+    RsaFree (rsa);
+    mbedtls_x509_crt_free (&crt);
+    return FALSE;
+  }
+
+  mbedtls_x509_crt_free (&crt);
+
+  *RsaContext = rsa;
+  return TRUE;
+}
+
+/**
+  Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+  @param[in]  Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]  CertSize     Size of the X509 certificate in bytes.
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved
+                           EC public key component. Use EcFree() function to free the
+                           resource.
+
+  If Cert is NULL, then return FALSE.
+  If EcContext is NULL, then return FALSE.
+
+  @retval  TRUE   EC Public Key was retrieved successfully.
+  @retval  FALSE  Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT VOID        **EcContext
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Verify one X509 certificate was issued by the trusted CA.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate to be verified.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[in]      CACert       Pointer to the DER-encoded trusted CA certificate.
+  @param[in]      CACertSize   Size of the CA Certificate in bytes.
+
+  If Cert is NULL, then return FALSE.
+  If CACert is NULL, then return FALSE.
+
+  @retval  TRUE   The certificate was issued by the trusted CA.
+  @retval  FALSE  Invalid certificate or the certificate was not issued by the given
+                  trusted CA.
+
+**/
+BOOLEAN
+EFIAPI
+X509VerifyCert (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  IN CONST UINT8  *CACert,
+  IN UINTN        CACertSize
+  )
+{
+  INT32                     Ret;
+  mbedtls_x509_crt          Ca, End;
+  UINT32                    VFlag;
+  mbedtls_x509_crt_profile  Profile;
+
+  if ((Cert == NULL) || (CACert == NULL)) {
+    return FALSE;
+  }
+
+  VFlag = 0;
+  CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));
+
+  mbedtls_x509_crt_init (&Ca);
+  mbedtls_x509_crt_init (&End);
+
+  Ret = mbedtls_x509_crt_parse_der (&Ca, CACert, CACertSize);
+
+  if (Ret == 0) {
+    Ret = mbedtls_x509_crt_parse_der (&End, Cert, CertSize);
+  }
+
+  if (Ret == 0) {
+    Ret = mbedtls_x509_crt_verify_with_profile (&End, &Ca, NULL, &Profile, NULL, &VFlag, NULL, NULL);
+  }
+
+  mbedtls_x509_crt_free (&Ca);
+  mbedtls_x509_crt_free (&End);
+
+  return Ret == 0;
+}
+
+/**
+  Verify one X509 certificate was issued by the trusted CA.
+
+  @param[in]      RootCert          Trusted Root Certificate buffer
+  @param[in]      RootCertLength    Trusted Root Certificate buffer length
+  @param[in]      CertChain         One or more ASN.1 DER-encoded X.509 certificates
+                                    where the first certificate is signed by the Root
+                                    Certificate or is the Root Cerificate itself. and
+                                    subsequent cerificate is signed by the preceding
+                                    cerificate.
+  @param[in]      CertChainLength   Total length of the certificate chain, in bytes.
+
+  @retval  TRUE   All cerificates was issued by the first certificate in X509Certchain.
+  @retval  FALSE  Invalid certificate or the certificate was not issued by the given
+                  trusted CA.
+**/
+BOOLEAN
+EFIAPI
+X509VerifyCertChain (
+  IN CONST UINT8  *RootCert,
+  IN UINTN        RootCertLength,
+  IN CONST UINT8  *CertChain,
+  IN UINTN        CertChainLength
+  )
+{
+  UINTN        Asn1Len;
+  UINTN        PrecedingCertLen;
+  CONST UINT8  *PrecedingCert;
+  UINTN        CurrentCertLen;
+  CONST UINT8  *CurrentCert;
+  CONST UINT8  *TmpPtr;
+  UINT32       Ret;
+  BOOLEAN      VerifyFlag;
+
+  VerifyFlag       = FALSE;
+  PrecedingCert    = RootCert;
+  PrecedingCertLen = RootCertLength;
+
+  CurrentCert = CertChain;
+
+  //
+  // Get Current certificate from Certificates buffer and Verify with preciding cert
+  //
+  do {
+    TmpPtr = CurrentCert;
+    Ret    = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (Ret != 0) {
+      break;
+    }
+
+    CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert);
+
+    if (!X509VerifyCert (CurrentCert, CurrentCertLen, PrecedingCert, PrecedingCertLen)) {
+      VerifyFlag = FALSE;
+      break;
+    } else {
+      VerifyFlag = TRUE;
+    }
+
+    //
+    // Save preceding certificate
+    //
+    PrecedingCert    = CurrentCert;
+    PrecedingCertLen = CurrentCertLen;
+
+    //
+    // Move current certificate to next;
+    //
+    CurrentCert = CurrentCert + CurrentCertLen;
+  } while (1);
+
+  return VerifyFlag;
+}
+
+/**
+  Get one X509 certificate from CertChain.
+
+  @param[in]      CertChain         One or more ASN.1 DER-encoded X.509 certificates
+                                    where the first certificate is signed by the Root
+                                    Certificate or is the Root Cerificate itself. and
+                                    subsequent cerificate is signed by the preceding
+                                    cerificate.
+  @param[in]      CertChainLength   Total length of the certificate chain, in bytes.
+
+  @param[in]      CertIndex         Index of certificate.
+
+  @param[out]     Cert              The certificate at the index of CertChain.
+  @param[out]     CertLength        The length certificate at the index of CertChain.
+
+  @retval  TRUE   Success.
+  @retval  FALSE  Failed to get certificate from certificate chain.
+**/
+BOOLEAN
+EFIAPI
+X509GetCertFromCertChain (
+  IN CONST UINT8   *CertChain,
+  IN UINTN         CertChainLength,
+  IN CONST INT32   CertIndex,
+  OUT CONST UINT8  **Cert,
+  OUT UINTN        *CertLength
+  )
+{
+  UINTN        Asn1Len;
+  INT32        CurrentIndex;
+  UINTN        CurrentCertLen;
+  CONST UINT8  *CurrentCert;
+  CONST UINT8  *TmpPtr;
+  INT32        Ret;
+
+  //
+  // Check input parameters.
+  //
+  if ((CertChain == NULL) || (Cert == NULL) ||
+      (CertIndex < -1) || (CertLength == NULL))
+  {
+    return FALSE;
+  }
+
+  CurrentCert  = CertChain;
+  CurrentIndex = -1;
+
+  //
+  // Traverse the certificate chain
+  //
+  while (TRUE) {
+    //
+    // Get asn1 tag len
+    //
+    TmpPtr = CurrentCert;
+    Ret    = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (Ret != 0) {
+      break;
+    }
+
+    CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert);
+    CurrentIndex++;
+
+    if (CurrentIndex == CertIndex) {
+      *Cert       = CurrentCert;
+      *CertLength = CurrentCertLen;
+      return TRUE;
+    }
+
+    //
+    // Move to next
+    //
+    CurrentCert = CurrentCert + CurrentCertLen;
+  }
+
+  //
+  // If CertIndex is -1, Return the last certificate
+  //
+  if ((CertIndex == -1) && (CurrentIndex >= 0)) {
+    *Cert       = CurrentCert - CurrentCertLen;
+    *CertLength = CurrentCertLen;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Retrieve the TBSCertificate from one given X.509 certificate.
+
+  @param[in]      Cert         Pointer to the given DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[out]     TBSCert      DER-Encoded To-Be-Signed certificate.
+  @param[out]     TBSCertSize  Size of the TBS certificate in bytes.
+
+  If Cert is NULL, then return FALSE.
+  If TBSCert is NULL, then return FALSE.
+  If TBSCertSize is NULL, then return FALSE.
+
+  @retval  TRUE   The TBSCertificate was retrieved successfully.
+  @retval  FALSE  Invalid X.509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetTBSCert (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       **TBSCert,
+  OUT UINTN       *TBSCertSize
+  )
+{
+  UINTN        Length;
+  UINTN        Ret;
+  UINT8        *Ptr;
+  CONST UINT8  *Temp;
+  CONST UINT8  *End;
+
+  //
+  // Check input parameters.
+  //
+  if ((Cert == NULL) || (TBSCert == NULL) ||
+      (TBSCertSize == NULL) || (CertSize > INT_MAX))
+  {
+    return FALSE;
+  }
+
+  //
+  // An X.509 Certificate is: (defined in RFC3280)
+  //   Certificate  ::=  SEQUENCE  {
+  //     tbsCertificate       TBSCertificate,
+  //     signatureAlgorithm   AlgorithmIdentifier,
+  //     signature            BIT STRING }
+  //
+  // and
+  //
+  //  TBSCertificate  ::=  SEQUENCE  {
+  //    version         [0]  Version DEFAULT v1,
+  //    ...
+  //    }
+  //
+  // So we can just ASN1-parse the x.509 DER-encoded data. If we strip
+  // the first SEQUENCE, the second SEQUENCE is the TBSCertificate.
+  //
+
+  Length = 0;
+
+  Ptr = (UINT8 *)Cert;
+  End = Cert + CertSize;
+
+  Ret = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  Temp = Ptr;
+  End  = Ptr + Length;
+  Ret  = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  *TBSCert     = (UINT8 *)Temp;
+  *TBSCertSize = Length + (Ptr - Temp);
+
+  return TRUE;
+}
+
+/**
+  Retrieve the version from one X.509 certificate.
+
+  If Cert is NULL, then return FALSE.
+  If CertSize is 0, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[out]     Version      Pointer to the retrieved version integer.
+
+  @retval TRUE           The certificate version retrieved successfully.
+  @retval FALSE          If  Cert is NULL or CertSize is Zero.
+  @retval FALSE          The operation is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetVersion (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINTN       *Version
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           ReturnStatus;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  ReturnStatus = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    *Version     = Crt.version - 1;
+    ReturnStatus = TRUE;
+  }
+
+  mbedtls_x509_crt_free (&Crt);
+
+  return ReturnStatus;
+}
+
+/**
+  Retrieve the serialNumber from one X.509 certificate.
+
+  If Cert is NULL, then return FALSE.
+  If CertSize is 0, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[out]     SerialNumber  Pointer to the retrieved certificate SerialNumber bytes.
+  @param[in, out] SerialNumberSize  The size in bytes of the SerialNumber buffer on input,
+                               and the size of buffer returned SerialNumber on output.
+
+  @retval TRUE                     The certificate serialNumber retrieved successfully.
+  @retval FALSE                    If Cert is NULL or CertSize is Zero.
+                                   If SerialNumberSize is NULL.
+                                   If Certificate is invalid.
+  @retval FALSE                    If no SerialNumber exists.
+  @retval FALSE                    If the SerialNumber is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   SerialNumberSize parameter.
+  @retval FALSE                    The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetSerialNumber (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       *SerialNumber OPTIONAL,
+  IN OUT UINTN    *SerialNumberSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           ReturnStatus;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  ReturnStatus = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    if (*SerialNumberSize <= Crt.serial.len) {
+      *SerialNumberSize = Crt.serial.len + 1;
+      ReturnStatus      = FALSE;
+      goto Cleanup;
+    }
+
+    if (SerialNumber != NULL) {
+      CopyMem (SerialNumber, Crt.serial.p, Crt.serial.len);
+      SerialNumber[Crt.serial.len] = '\0';
+    }
+
+    *SerialNumberSize = Crt.serial.len + 1;
+    ReturnStatus      = TRUE;
+  }
+
+Cleanup:
+  mbedtls_x509_crt_free (&Crt);
+
+  return ReturnStatus;
+}
+
+/**
+  Retrieve the issuer bytes from one X.509 certificate.
+
+  If Cert is NULL, then return FALSE.
+  If CertIssuerSize is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[out]     CertIssuer  Pointer to the retrieved certificate subject bytes.
+  @param[in, out] CertIssuerSize  The size in bytes of the CertIssuer buffer on input,
+                               and the size of buffer returned CertSubject on output.
+
+  @retval  TRUE   The certificate issuer retrieved successfully.
+  @retval  FALSE  Invalid certificate, or the CertIssuerSize is too small for the result.
+                  The CertIssuerSize will be updated with the required size.
+  @retval  FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetIssuerName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       *CertIssuer,
+  IN OUT UINTN    *CertIssuerSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           Status;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  Status = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    if (*CertIssuerSize < Crt.serial.len) {
+      *CertIssuerSize = Crt.serial.len;
+      Status          = FALSE;
+      goto Cleanup;
+    }
+
+    if (CertIssuer != NULL) {
+      CopyMem (CertIssuer, Crt.serial.p, Crt.serial.len);
+    }
+
+    *CertIssuerSize = Crt.serial.len;
+    Status          = TRUE;
+  }
+
+Cleanup:
+  mbedtls_x509_crt_free (&Crt);
+
+  return Status;
+}
+
+/**
+  Retrieve the issuer common name (CN) string from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     CommonName       Buffer to contain the retrieved certificate issuer common
+                                   name string. At most CommonNameSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,
+                                   and the size of buffer returned CommonName on output.
+                                   If CommonName is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate Issuer CommonName retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If CommonNameSize is NULL.
+                                   If CommonName is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no CommonName entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetIssuerCommonName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT CHAR8       *CommonName OPTIONAL,
+  IN OUT UINTN    *CommonNameSize
+  )
+{
+  return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize);
+}
+
+/**
+  Retrieve the issuer organization name (O) string from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     NameBuffer       Buffer to contain the retrieved certificate issuer organization
+                                   name string. At most NameBufferSize bytes will be
+                                   written and the string will be null terminated. May be
+                                   NULL in order to determine the size buffer needed.
+  @param[in,out]  NameBufferSize   The size in bytes of the Name buffer on input,
+                                   and the size of buffer returned Name on output.
+                                   If NameBuffer is NULL then the amount of space needed
+                                   in buffer (including the final null) is returned.
+
+  @retval RETURN_SUCCESS           The certificate issuer Organization Name retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                   If NameBufferSize is NULL.
+                                   If NameBuffer is not NULL and *CommonNameSize is 0.
+                                   If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no Organization Name entry exists.
+  @retval RETURN_BUFFER_TOO_SMALL  If the NameBuffer is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   CommonNameSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetIssuerOrganizationName (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT CHAR8       *NameBuffer OPTIONAL,
+  IN OUT UINTN    *NameBufferSize
+  )
+{
+  return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize);
+}
+
+/**
+  Retrieve the Signature Algorithm from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     Oid              Signature Algorithm Object identifier buffer.
+  @param[in,out]  OidSize          Signature Algorithm Object identifier buffer size
+
+  @retval TRUE           The certificate Extension data retrieved successfully.
+  @retval FALSE                    If Cert is NULL.
+                                   If OidSize is NULL.
+                                   If Oid is not NULL and *OidSize is 0.
+                                   If Certificate is invalid.
+  @retval FALSE                    If no SignatureType.
+  @retval FALSE                    If the Oid is NULL. The required buffer size
+                                   is returned in the OidSize.
+  @retval FALSE                    The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetSignatureAlgorithm (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       *Oid OPTIONAL,
+  IN OUT UINTN    *OidSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           ReturnStatus;
+
+  if ((Cert == NULL) || (CertSize == 0) || (OidSize == NULL)) {
+    return FALSE;
+  }
+
+  ReturnStatus = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    if (*OidSize < Crt.sig_oid.len) {
+      *OidSize     = Crt.serial.len;
+      ReturnStatus = FALSE;
+      goto Cleanup;
+    }
+
+    if (Oid != NULL) {
+      CopyMem (Oid, Crt.sig_oid.p, Crt.sig_oid.len);
+    }
+
+    *OidSize     = Crt.sig_oid.len;
+    ReturnStatus = TRUE;
+  }
+
+Cleanup:
+  mbedtls_x509_crt_free (&Crt);
+
+  return ReturnStatus;
+}
+
+/**
+ Find first Extension data match with given OID
+
+  @param[in]      Start             Pointer to the DER-encoded Extensions Data
+  @param[in]      End               Extensions Data size in bytes
+  @param[in ]     Oid               OID for match
+  @param[in ]     OidSize           OID size in bytes
+  @param[out]     FindExtensionData output matched extension data.
+  @param[out]     FindExtensionDataLen matched extension data size.
+
+ **/
+STATIC
+RETURN_STATUS
+InternalX509FindExtensionData (
+  UINT8        *Start,
+  UINT8        *End,
+  CONST UINT8  *Oid,
+  UINTN        OidSize,
+  UINT8        **FindExtensionData,
+  UINTN        *FindExtensionDataLen
+  )
+{
+  UINT8          *Ptr;
+  UINT8          *ExtensionPtr;
+  size_t         ObjLen;
+  INT32          Ret;
+  RETURN_STATUS  ReturnStatus;
+  size_t         FindExtensionLen;
+  size_t         HeaderLen;
+
+  ReturnStatus = RETURN_INVALID_PARAMETER;
+  Ptr          = Start;
+
+  Ret = 0;
+
+  while (TRUE) {
+    /*
+     * Extension  ::=  SEQUENCE  {
+     *      extnID      OBJECT IDENTIFIER,
+     *      critical    BOOLEAN DEFAULT FALSE,
+     *      extnValue   OCTET STRING  }
+     */
+    ExtensionPtr = Ptr;
+    Ret          = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (Ret == 0) {
+      HeaderLen        = (size_t)(Ptr - ExtensionPtr);
+      FindExtensionLen = ObjLen;
+      // Get Object Identifier
+      Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID);
+    } else {
+      break;
+    }
+
+    if ((Ret == 0) && (CompareMem (Ptr, Oid, OidSize) == 0)) {
+      Ptr += ObjLen;
+
+      Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_BOOLEAN);
+      if (Ret == 0) {
+        Ptr += ObjLen;
+      }
+
+      Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING);
+    } else {
+      Ret = 1;
+    }
+
+    if (Ret == 0) {
+      *FindExtensionData    = Ptr;
+      *FindExtensionDataLen = ObjLen;
+      ReturnStatus          = RETURN_SUCCESS;
+      break;
+    }
+
+    // move to next
+    Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
+    Ret = 0;
+  }
+
+  return ReturnStatus;
+}
+
+/**
+  Retrieve Extension data from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[in]      Oid              Object identifier buffer
+  @param[in]      OidSize          Object identifier buffer size
+  @param[out]     ExtensionData    Extension bytes.
+  @param[in, out] ExtensionDataSize Extension bytes size.
+
+  @retval TRUE                     The certificate Extension data retrieved successfully.
+  @retval FALSE                    If Cert is NULL.
+                                   If ExtensionDataSize is NULL.
+                                   If ExtensionData is not NULL and *ExtensionDataSize is 0.
+                                   If Certificate is invalid.
+  @retval FALSE                    If no Extension entry match Oid.
+  @retval FALSE                    If the ExtensionData is NULL. The required buffer size
+                                   is returned in the ExtensionDataSize parameter.
+  @retval FALSE                    The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetExtensionData (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  IN CONST UINT8  *Oid,
+  IN UINTN        OidSize,
+  OUT UINT8       *ExtensionData,
+  IN OUT UINTN    *ExtensionDataSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  RETURN_STATUS     ReturnStatus;
+  BOOLEAN           Status;
+  UINT8             *Ptr;
+  UINT8             *End;
+  size_t            ObjLen;
+
+  if ((Cert == NULL) ||
+      (CertSize == 0) ||
+      (Oid == NULL) ||
+      (OidSize == 0) ||
+      (ExtensionDataSize == NULL))
+  {
+    return FALSE;
+  }
+
+  ReturnStatus = RETURN_INVALID_PARAMETER;
+  Status       = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    Ptr = Crt.v3_ext.p;
+    End = Crt.v3_ext.p + Crt.v3_ext.len;
+    Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+  }
+
+  if (Ret == 0) {
+    ReturnStatus = InternalX509FindExtensionData (Ptr, End, Oid, OidSize, &Ptr, &ObjLen);
+  }
+
+  if (ReturnStatus == RETURN_SUCCESS) {
+    if (*ExtensionDataSize < ObjLen) {
+      *ExtensionDataSize = ObjLen;
+      Status             = FALSE;
+      goto Cleanup;
+    }
+
+    if (Oid != NULL) {
+      CopyMem (ExtensionData, Ptr, ObjLen);
+    }
+
+    *ExtensionDataSize = ObjLen;
+    Status             = TRUE;
+  }
+
+Cleanup:
+  mbedtls_x509_crt_free (&Crt);
+
+  return Status;
+}
+
+/**
+  Retrieve the Validity from one X.509 certificate
+
+  If Cert is NULL, then return FALSE.
+  If CertIssuerSize is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize     Size of the X509 certificate in bytes.
+  @param[in]      From         notBefore Pointer to DateTime object.
+  @param[in,out]  FromSize     notBefore DateTime object size.
+  @param[in]      To           notAfter Pointer to DateTime object.
+  @param[in,out]  ToSize       notAfter DateTime object size.
+
+  Note: X509CompareDateTime to compare DateTime oject
+        x509SetDateTime to get a DateTime object from a DateTimeStr
+
+  @retval  TRUE   The certificate Validity retrieved successfully.
+  @retval  FALSE  Invalid certificate, or Validity retrieve failed.
+  @retval  FALSE  This interface is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetValidity (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  IN UINT8        *From,
+  IN OUT UINTN    *FromSize,
+  IN UINT8        *To,
+  IN OUT UINTN    *ToSize
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           Status;
+  UINTN             TSize;
+  UINTN             FSize;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  Status = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    FSize = sizeof (mbedtls_x509_time);
+    if (*FromSize < FSize) {
+      *FromSize = FSize;
+      goto _Exit;
+    }
+
+    *FromSize = FSize;
+    if (From != NULL) {
+      CopyMem (From, &(Crt.valid_from), FSize);
+    }
+
+    TSize = sizeof (mbedtls_x509_time);
+    if (*ToSize < TSize) {
+      *ToSize = TSize;
+      goto _Exit;
+    }
+
+    *ToSize = TSize;
+    if (To != NULL) {
+      CopyMem (To, &(Crt.valid_to), sizeof (mbedtls_x509_time));
+    }
+
+    Status = TRUE;
+  }
+
+_Exit:
+  mbedtls_x509_crt_free (&Crt);
+
+  return Status;
+}
+
+/**
+  Retrieve the Key Usage from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     Usage            Key Usage (CRYPTO_X509_KU_*)
+
+  @retval  TRUE   The certificate Key Usage retrieved successfully.
+  @retval  FALSE  Invalid certificate, or Usage is NULL
+  @retval  FALSE  This interface is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetKeyUsage (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINTN       *Usage
+  )
+{
+  mbedtls_x509_crt  Crt;
+  INT32             Ret;
+  BOOLEAN           Status;
+
+  if (Cert == NULL) {
+    return FALSE;
+  }
+
+  Status = FALSE;
+
+  mbedtls_x509_crt_init (&Crt);
+
+  Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+  if (Ret == 0) {
+    *Usage = Crt.key_usage;
+    Status = TRUE;
+  }
+
+  mbedtls_x509_crt_free (&Crt);
+
+  return Status;
+}
+
+/**
+  Retrieve the Extended Key Usage from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize         Size of the X509 certificate in bytes.
+  @param[out]     Usage            Key Usage bytes.
+  @param[in, out] UsageSize        Key Usage buffer sizs in bytes.
+
+  @retval TRUE                     The Usage bytes retrieve successfully.
+  @retval FALSE                    If Cert is NULL.
+                                   If CertSize is NULL.
+                                   If Usage is not NULL and *UsageSize is 0.
+                                   If Cert is invalid.
+  @retval FALSE                    If the Usage is NULL. The required buffer size
+                                   is returned in the UsageSize parameter.
+  @retval FALSE                    The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetExtendedKeyUsage (
+  IN CONST UINT8  *Cert,
+  IN UINTN        CertSize,
+  OUT UINT8       *Usage,
+  IN OUT UINTN    *UsageSize
+  )
+{
+  BOOLEAN  ReturnStatus;
+
+  if ((Cert == NULL) || (CertSize == 0) || (UsageSize == NULL)) {
+    return FALSE;
+  }
+
+  ReturnStatus = X509GetExtensionData ((UINT8 *)Cert, CertSize, (UINT8 *)OID_extKeyUsage, sizeof (OID_extKeyUsage), Usage, UsageSize);
+
+  return ReturnStatus;
+}
+
+/**
+  Compare DateTime1 object and DateTime2 object time.
+
+  @param[in]      Before         Pointer to a DateTime Ojbect
+  @param[in]      After          Pointer to a DateTime Object
+
+  @retval  0      If DateTime1 <= DateTime2
+  @retval  1      If DateTime1 > DateTime2
+**/
+STATIC
+INTN
+InternalX509CheckTime (
+  CONST mbedtls_x509_time  *Before,
+  CONST mbedtls_x509_time  *After
+  )
+{
+  if (Before->year > After->year) {
+    return (1);
+  }
+
+  if ((Before->year == After->year) &&
+      (Before->mon > After->mon))
+  {
+    return (1);
+  }
+
+  if ((Before->year == After->year) &&
+      (Before->mon == After->mon) &&
+      (Before->day > After->day))
+  {
+    return (1);
+  }
+
+  if ((Before->year == After->year) &&
+      (Before->mon == After->mon) &&
+      (Before->day == After->day) &&
+      (Before->hour > After->hour))
+  {
+    return (1);
+  }
+
+  if ((Before->year == After->year) &&
+      (Before->mon == After->mon) &&
+      (Before->day == After->day) &&
+      (Before->hour == After->hour) &&
+      (Before->min > After->min))
+  {
+    return (1);
+  }
+
+  if ((Before->year == After->year) &&
+      (Before->mon == After->mon) &&
+      (Before->day == After->day) &&
+      (Before->hour == After->hour) &&
+      (Before->min == After->min) &&
+      (Before->sec > After->sec))
+  {
+    return (1);
+  }
+
+  return (0);
+}
+
+/**
+  change string to int.
+
+  @param[in] PStart         Pointer to a string Start
+  @param[in] PEnd           Pointer to a string End
+
+  @return number
+**/
+STATIC
+INT32
+InternalAtoI (
+  CHAR8  *PStart,
+  CHAR8  *PEnd
+  )
+{
+  CHAR8  *Ptr;
+  INT32  Knum;
+
+  Knum = 0;
+  Ptr  = PStart;
+
+  while (Ptr < PEnd) {
+    ///
+    /// k = k * 2^3 + k * 2^1 = k * 8 + k * 2 = k * 10
+    ///
+    Knum = (Knum << 3) + (Knum << 1) + (*Ptr) - '0';
+    Ptr++;
+  }
+
+  return Knum;
+}
+
+/**
+  Format a DateTime object into DataTime Buffer
+
+  If DateTimeStr is NULL, then return FALSE.
+  If DateTimeSize is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      DateTimeStr      DateTime string like YYYYMMDDhhmmssZ
+                                   Ref: https://www.w3.org/TR/NOTE-datetime
+                                   Z stand for UTC time
+  @param[in,out]  DateTime         Pointer to a DateTime object.
+  @param[in,out]  DateTimeSize     DateTime object buffer size.
+
+  @retval RETURN_SUCCESS           The DateTime object create successfully.
+  @retval RETURN_INVALID_PARAMETER If DateTimeStr is NULL.
+                                   If DateTimeSize is NULL.
+                                   If DateTime is not NULL and *DateTimeSize is 0.
+                                   If Year Month Day Hour Minute Second combination is invalid datetime.
+  @retval RETURN_BUFFER_TOO_SMALL  If the DateTime is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   DateTimeSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+**/
+RETURN_STATUS
+EFIAPI
+X509SetDateTime (
+  CHAR8         *DateTimeStr,
+  IN OUT VOID   *DateTime,
+  IN OUT UINTN  *DateTimeSize
+  )
+{
+  mbedtls_x509_time  Dt;
+
+  INT32          Year;
+  INT32          Month;
+  INT32          Day;
+  INT32          Hour;
+  INT32          Minute;
+  INT32          Second;
+  RETURN_STATUS  ReturnStatus;
+  CHAR8          *Ptr;
+
+  Ptr = DateTimeStr;
+
+  Year    = InternalAtoI (Ptr, Ptr + 4);
+  Ptr    += 4;
+  Month   = InternalAtoI (Ptr, Ptr + 2);
+  Ptr    += 2;
+  Day     = InternalAtoI (Ptr, Ptr + 2);
+  Ptr    += 2;
+  Hour    = InternalAtoI (Ptr, Ptr + 2);
+  Ptr    += 2;
+  Minute  = InternalAtoI (Ptr, Ptr + 2);
+  Ptr    += 2;
+  Second  = InternalAtoI (Ptr, Ptr + 2);
+  Ptr    += 2;
+  Dt.year = (int)Year;
+  Dt.mon  = (int)Month;
+  Dt.day  = (int)Day;
+  Dt.hour = (int)Hour;
+  Dt.min  = (int)Minute;
+  Dt.sec  = (int)Second;
+
+  if (*DateTimeSize < sizeof (mbedtls_x509_time)) {
+    *DateTimeSize = sizeof (mbedtls_x509_time);
+    ReturnStatus  = RETURN_BUFFER_TOO_SMALL;
+    goto Cleanup;
+  }
+
+  if (DateTime != NULL) {
+    CopyMem (DateTime, &Dt, sizeof (mbedtls_x509_time));
+  }
+
+  *DateTimeSize = sizeof (mbedtls_x509_time);
+  ReturnStatus  = RETURN_SUCCESS;
+Cleanup:
+  return ReturnStatus;
+}
+
+/**
+  Compare DateTime1 object and DateTime2 object.
+
+  If DateTime1 is NULL, then return -2.
+  If DateTime2 is NULL, then return -2.
+  If DateTime1 == DateTime2, then return 0
+  If DateTime1 > DateTime2, then return 1
+  If DateTime1 < DateTime2, then return -1
+
+  @param[in]      DateTime1         Pointer to a DateTime Ojbect
+  @param[in]      DateTime2         Pointer to a DateTime Object
+
+  @retval  0      If DateTime1 == DateTime2
+  @retval  1      If DateTime1 > DateTime2
+  @retval  -1     If DateTime1 < DateTime2
+**/
+INT32
+EFIAPI
+X509CompareDateTime (
+  IN CONST VOID  *DateTime1,
+  IN CONST VOID  *DateTime2
+  )
+{
+  if ((DateTime1 == NULL) || (DateTime2 == NULL)) {
+    return -2;
+  }
+
+  if (CompareMem (DateTime2, DateTime1, sizeof (mbedtls_x509_time)) == 0) {
+    return 0;
+  }
+
+  if (InternalX509CheckTime ((mbedtls_x509_time *)DateTime1, (mbedtls_x509_time *)DateTime2) == 0) {
+    return -1;
+  } else {
+    return 1;
+  }
+}
+
+/**
+  Retrieve the basic constraints from one X.509 certificate.
+
+  @param[in]      Cert                     Pointer to the DER-encoded X509 certificate.
+  @param[in]      CertSize                 size of the X509 certificate in bytes.
+  @param[out]     BasicConstraints         basic constraints bytes.
+  @param[in, out] BasicConstraintsSize     basic constraints buffer sizs in bytes.
+
+  @retval TRUE                     The basic constraints retrieve successfully.
+  @retval FALSE                    If cert is NULL.
+                                   If cert_size is NULL.
+                                   If basic_constraints is not NULL and *basic_constraints_size is 0.
+                                   If cert is invalid.
+  @retval FALSE                    The required buffer size is small.
+                                   The return buffer size is basic_constraints_size parameter.
+  @retval FALSE                    If no Extension entry match oid.
+  @retval FALSE                    The operation is not supported.
+ **/
+BOOLEAN
+EFIAPI
+X509GetExtendedBasicConstraints (
+  CONST UINT8  *Cert,
+  UINTN        CertSize,
+  UINT8        *BasicConstraints,
+  UINTN        *BasicConstraintsSize
+  )
+{
+  BOOLEAN  Status;
+
+  if ((Cert == NULL) || (CertSize == 0) || (BasicConstraintsSize == NULL)) {
+    return FALSE;
+  }
+
+  Status = X509GetExtensionData (
+             (UINT8 *)Cert,
+             CertSize,
+             OID_BasicConstraints,
+             sizeof (OID_BasicConstraints),
+             BasicConstraints,
+             BasicConstraintsSize
+             );
+
+  return Status;
+}
+
+/**
+  Format a DateTimeStr to DataTime object in DataTime Buffer
+
+  If DateTimeStr is NULL, then return FALSE.
+  If DateTimeSize is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      DateTimeStr      DateTime string like YYYYMMDDhhmmssZ
+                                   Ref: https://www.w3.org/TR/NOTE-datetime
+                                   Z stand for UTC time
+  @param[out]     DateTime         Pointer to a DateTime object.
+  @param[in,out]  DateTimeSize     DateTime object buffer size.
+
+  @retval TRUE                     The DateTime object create successfully.
+  @retval FALSE                    If DateTimeStr is NULL.
+                                   If DateTimeSize is NULL.
+                                   If DateTime is not NULL and *DateTimeSize is 0.
+                                   If Year Month Day Hour Minute Second combination is invalid datetime.
+  @retval FALSE                    If the DateTime is NULL. The required buffer size
+                                   (including the final null) is returned in the
+                                   DateTimeSize parameter.
+  @retval FALSE                    The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509FormatDateTime (
+  IN CONST CHAR8  *DateTimeStr,
+  OUT VOID        *DateTime,
+  IN OUT UINTN    *DateTimeSize
+  )
+{
+  mbedtls_x509_time  *tm;
+
+  if (*DateTimeSize < sizeof (mbedtls_x509_time)) {
+    return FALSE;
+  }
+
+  if (DateTime == NULL) {
+    return FALSE;
+  }
+
+  tm = (mbedtls_x509_time *)DateTime;
+
+  tm->year = (DateTimeStr[0] + '0') * 1000 + (DateTimeStr[1] + '0') * 100 +
+             (DateTimeStr[2] + '0') * 10 + (DateTimeStr[3] + '0') * 1;
+
+  tm->mon = (DateTimeStr[4] + '0') * 10 + (DateTimeStr[5] + '0') * 1;
+
+  tm->day = (DateTimeStr[6] + '0') * 10 + (DateTimeStr[7] + '0') * 1;
+
+  tm->hour = (DateTimeStr[8] + '0') * 10 + (DateTimeStr[9] + '0') * 1;
+
+  tm->min = (DateTimeStr[10] + '0') * 10 + (DateTimeStr[11] + '0') * 1;
+
+  tm->sec = (DateTimeStr[12] + '0') * 10 + (DateTimeStr[13] + '0') * 1;
+
+  return TRUE;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117861): https://edk2.groups.io/g/devel/message/117861
Mute This Topic: https://groups.io/mt/105552834/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related functions based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (3 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 4/9] CryptoPkg: Add X509 functions " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-22  7:52   ` Li, Yi
  2024-04-16  7:51 ` [edk2-devel] [PATCH 6/9] CryptoPkg: Add Pkcs5 " Wenxing Hou
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Because the current Mbedlts pkcs7 library doesn't support
authenticatedAttributes:
Mbed-TLS/mbedtls@bb82ab7
and only support 0 or 1 certificates in Signed data:
tianocore/edk2-staging@9c5b26b

The patch implement Pkcs7 by low Mbedtls Api.
And the implementation has pass unit_tes and integration test.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |   33 +
 .../Pk/CryptPkcs7Internal.h                   |   20 +-
 .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c   |  615 ++++++++
 .../Pk/CryptPkcs7VerifyBase.c                 |  113 ++
 .../Pk/CryptPkcs7VerifyCommon.c               | 1315 +++++++++++++++++
 .../Pk/CryptPkcs7VerifyEku.c                  |  689 +++++++++
 6 files changed, 2773 insertions(+), 12 deletions(-)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
index e2c7e42ecb..1b9742c166 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
@@ -38,4 +38,37 @@ MbedtlsRand (
   UINT8  *output,
   UINTN  len
   );
+
+/**
+  Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+  a new structure to wrap P7Data.
+
+  Caution: This function may receive untrusted input.
+  UEFI Authenticated Variable is external input, so this function will do basic
+  check for PKCS#7 data structure.
+
+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.
+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.
+  @param[out] WrapFlag     If TRUE P7Data is a ContentInfo structure, otherwise
+                           return FALSE.
+  @param[out] WrapData     If return status of this function is TRUE:
+                           1) when WrapFlag is TRUE, pointer to P7Data.
+                           2) when WrapFlag is FALSE, pointer to a new ContentInfo
+                           structure. It's caller's responsibility to free this
+                           buffer.
+  @param[out] WrapDataSize Length of ContentInfo structure in bytes.
+
+  @retval     TRUE         The operation is finished successfully.
+  @retval     FALSE        The operation is failed due to lack of resources.
+
+**/
+BOOLEAN
+WrapPkcs7Data (
+  IN  CONST UINT8  *P7Data,
+  IN  UINTN        P7Length,
+  OUT BOOLEAN      *WrapFlag,
+  OUT UINT8        **WrapData,
+  OUT UINTN        *WrapDataSize
+  );
+
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
index 207f493cbb..d4bdb0abf7 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
@@ -4,7 +4,7 @@
 
   RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5
 
-Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2023-2024, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -31,10 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define MBEDTLS_OID_PKCS7_DIGESTED_DATA              MBEDTLS_OID_PKCS7 "\x05"
 #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA             MBEDTLS_OID_PKCS7 "\x06"
 
-typedef mbedtls_asn1_buf         MBEDTLSPKCS7BUF;
-typedef mbedtls_asn1_named_data  MBEDTLSPKCS7NAME;
-typedef mbedtls_asn1_sequence    MBEDTLSPKCS7SEQUENCE;
-
 ///
 /// PKCS7 SignerInfo type
 /// https://tools.ietf.org/html/rfc2315#section-9.2
@@ -48,8 +44,8 @@ typedef struct MbedtlsPkcs7SignerInfo {
   mbedtls_x509_buf                 SigAlgIdentifier;
   mbedtls_x509_buf                 AuthAttr;
   mbedtls_x509_buf                 Sig;
-  struct MBEDTLSPKCS7SIGNERINFO    *Next;
-} MBEDTLSPKCS7SIGNERINFO;
+  struct MbedtlsPkcs7SignerInfo    *Next;
+} MbedtlsPkcs7SignerInfo;
 
 ///
 /// PKCS7 signed data attached data format
@@ -57,7 +53,7 @@ typedef struct MbedtlsPkcs7SignerInfo {
 typedef struct MbedtlsPkcs7Data {
   mbedtls_asn1_buf    Oid;
   mbedtls_asn1_buf    Data;
-} MBEDTLSPKCS7DATA;
+} MbedtlsPkcs7Data;
 
 ///
 /// Signed Data
@@ -66,18 +62,18 @@ typedef struct MbedtlsPkcs7Data {
 typedef struct MbedtlsPkcs7SignedData {
   INT32                            Version;
   mbedtls_asn1_buf                 DigestAlgorithms;
-  struct MBEDTLSPKCS7DATA          ContentInfo;
+  struct MbedtlsPkcs7Data          ContentInfo;
   mbedtls_x509_crt                 Certificates;
   mbedtls_x509_crl                 Crls;
   struct MbedtlsPkcs7SignerInfo    SignerInfos;
-} MBEDTLSPKCS7SIGNEDDATA;
+} MbedtlsPkcs7SignedData;
 
 ///
 /// PKCS7 struct, only support SignedData
 ///
 typedef struct MbedtlsPkcs7 {
   mbedtls_asn1_buf                 ContentTypeOid;
-  struct MBEDTLSPKCS7SIGNEDDATA    SignedData;
-} MBEDTLSPKCS7;
+  struct MbedtlsPkcs7SignedData    SignedData;
+} MbedtlsPkcs7;
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
new file mode 100644
index 0000000000..e4d2d7a2a8
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
@@ -0,0 +1,615 @@
+/** @file
+  PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper
+  Implementation over mbedtls.
+
+  RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
+  FIPS 186-4 - Digital Signature Standard (DSS)
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptPkcs7Internal.h"
+#include <mbedtls/ecdh.h>
+
+///
+/// Enough to store any signature generated by PKCS7
+///
+#define MAX_SIGNATURE_SIZE  1024
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8  MbedtlsOidDigestAlgSha256[] = MBEDTLS_OID_DIGEST_ALG_SHA256;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8  MbedtlsOidPkcs1Rsa[]        = MBEDTLS_OID_PKCS1_RSA;
+
+/**
+  Write DigestAlgorithmIdentifier.
+
+  @param[in, out]  P           The reference to the current position pointer.
+  @param[in]       Start       The start of the buffer, for bounds-checking.
+  @param[in]       DigestType  Digest Type
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDigestAlgorithm (
+  UINT8              **P,
+  UINT8              *Start,
+  mbedtls_md_type_t  DigestType
+  )
+{
+  UINT8  *OidPtr;
+  UINTN  OidLen;
+  INT32  Ret;
+
+  Ret = mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, &OidLen);
+  if (Ret == 0) {
+    return mbedtls_asn1_write_oid (P, (CONST UINT8 *)Start, (CONST CHAR8 *)OidPtr, OidLen);
+  }
+
+  return 0;
+}
+
+/**
+  DigestAlgorithmIdentifiers ::=
+  SET OF DigestAlgorithmIdentifier.
+
+  @param[in, out]  P           The reference to the current position pointer.
+  @param[in]       Start       The start of the buffer, for bounds-checking.
+  @param[in]       DigestTypes Digest Type array.
+  @param[in]       Count       The index for Digest Type.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDigestAlgorithmSet (
+  UINT8              **P,
+  UINT8              *Start,
+  mbedtls_md_type_t  *DigestTypes,
+  INTN               Count
+  )
+{
+  INTN   Idx;
+  INT32  Len;
+  INT32  ret;
+
+  Len = 0;
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (P, Start));
+
+  for (Idx = 0; Idx < Count; Idx++) {
+    MBEDTLS_ASN1_CHK_ADD (
+      Len,
+      MbedTlsPkcs7WriteDigestAlgorithm (P, Start, DigestTypes[Idx])
+      );
+  }
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, (UINTN)Len));
+
+  MBEDTLS_ASN1_CHK_ADD (
+    Len,
+    mbedtls_asn1_write_tag (
+      P,
+      Start,
+      (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
+      )
+    );
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, (UINTN)Len));
+
+  MBEDTLS_ASN1_CHK_ADD (
+    Len,
+    mbedtls_asn1_write_tag (
+      P,
+      Start,
+      (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)
+      )
+    );
+
+  return Len;
+}
+
+/**
+   ContentInfo ::= SEQUENCE {
+        contentType ContentType,
+        content
+                [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.
+
+  @param[in, out]  P           The reference to the current position pointer.
+  @param[in]       Start       The start of the buffer, for bounds-checking.
+  @param[in]       Content     ContentInfo.
+  @param[in]       ContentLen  Size of ContentInfo.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteContentInfo (
+  UINT8  **P,
+  UINT8  *Start,
+  UINT8  *Content,
+  INTN   ContentLen
+  )
+{
+  INT32  ret;
+  INT32  Len;
+
+  Len = 0;
+  if (Content != NULL) {
+    MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (P, Start, Content, ContentLen));
+  }
+
+  MBEDTLS_ASN1_CHK_ADD (
+    Len,
+    mbedtls_asn1_write_oid (
+      P,
+      Start,
+      MBEDTLS_OID_PKCS7_DATA,
+      sizeof (MBEDTLS_OID_PKCS7_DATA) - 1
+      )
+    );
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+  return Len;
+}
+
+/**
+   certificates :: SET OF ExtendedCertificateOrCertificate,
+   ExtendedCertificateOrCertificate ::= CHOICE {
+        certificate Certificate -- x509,
+        extendedCertificate[0] IMPLICIT ExtendedCertificate }.
+
+  @param[in, out]  P           The reference to the current position pointer.
+  @param[in]       Start       The start of the buffer, for bounds-checking.
+  @param[in]       Cert        Certificate.
+  @param[in]       OtherCerts  Ohter Certificate.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteCertificates (
+  UINT8             **P,
+  UINT8             *Start,
+  mbedtls_x509_crt  *Cert,
+  mbedtls_x509_crt  *OtherCerts
+  )
+{
+  INT32             ret;
+  INT32             Len;
+  mbedtls_x509_crt  *TmpCert;
+
+  Len = 0;
+
+  /// Write OtherCerts
+  TmpCert = OtherCerts;
+  while (TmpCert != NULL) {
+    MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, TmpCert->raw.p, TmpCert->raw.len));
+    TmpCert = TmpCert->next;
+  }
+
+  /// Write Cert
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, Cert->raw.p, Cert->raw.len));
+
+  /// Write NextContext
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
+  return Len;
+}
+
+/**
+  write Pkcs7 Int.
+
+  @param[in, out]  P            The reference to the current position pointer.
+  @param[in]       Start        The start of the buffer, for bounds-checking.
+  @param[in]       SerialRaw    SerialRaw.
+  @param[in]       SerialRawLen Size of SerialRaw.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteInt (
+  UINT8  **P,
+  UINT8  *Start,
+  UINT8  *SerialRaw,
+  INTN   SerialRawLen
+  )
+{
+  INT32  ret;
+  UINT8  *Ptr;
+  INT32  Len;
+
+  Len = 0;
+  Ptr = SerialRaw + SerialRawLen;
+  while (Ptr > SerialRaw) {
+    *--(*P) = *--Ptr;
+    Len++;
+  }
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_INTEGER));
+
+  return Len;
+}
+
+/**
+  write Pkcs7 Issuer And SerialNumber.
+
+  @param[in, out]  P            The reference to the current position pointer.
+  @param[in]       Start        The start of the buffer, for bounds-checking.
+  @param[in]       Serial       Serial.
+  @param[in]       SerialLen    Size of Serial.
+  @param[in]       IssuerRaw    IssuerRawLen.
+  @param[in]       IssuerRawLen Size of IssuerRawLen.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteIssuerAndSerialNumber (
+  UINT8  **P,
+  UINT8  *Start,
+  UINT8  *Serial,
+  INTN   SerialLen,
+  UINT8  *IssuerRaw,
+  INTN   IssuerRawLen
+  )
+{
+  INT32  ret;
+  INT32  Len;
+
+  Len = 0;
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (P, Start, Serial, SerialLen));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, IssuerRaw, IssuerRawLen));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+  return Len;
+}
+
+/**
+   SignerInfo ::= SEQUENCE {
+        version Version;
+        issuerAndSerialNumber   IssuerAndSerialNumber,
+        digestAlgorithm DigestAlgorithmIdentifier,
+        authenticatedAttributes
+                [0] IMPLICIT Attributes OPTIONAL,
+        digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+        encryptedDigest EncryptedDigest,
+        unauthenticatedAttributes
+                [1] IMPLICIT Attributes OPTIONAL.
+
+  @param[in, out]  P            The reference to the current position pointer.
+  @param[in]       Start        The start of the buffer, for bounds-checking.
+  @param[in]       SignerInfo    SignerInfo.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteSignerInfo (
+  UINT8                   **P,
+  UINT8                   *Start,
+  MbedtlsPkcs7SignerInfo  *SignerInfo
+  )
+{
+  INT32  ret;
+  INT32  Len;
+
+  Len = 0;
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (P, Start, SignerInfo->Sig.p, SignerInfo->Sig.len));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (P, Start, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIdentifier.len, 0));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (P, Start, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier.len, 0));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (P, Start, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p, SignerInfo->IssuerRaw.len));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (P, Start, SignerInfo->Version));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+  return Len;
+}
+
+/**
+  write Pkcs7 Signers Info Set.
+
+  @param[in, out]  P            The reference to the current position pointer.
+  @param[in]       Start        The start of the buffer, for bounds-checking.
+  @param[in]       SignersSet   SignerInfo Set.
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteSignersInfoSet (
+  UINT8                   **P,
+  UINT8                   *Start,
+  MbedtlsPkcs7SignerInfo  *SignersSet
+  )
+{
+  MbedtlsPkcs7SignerInfo  *SignerInfo;
+  INT32                   ret;
+  INT32                   Len;
+
+  SignerInfo = SignersSet;
+  Len        = 0;
+
+  while (SignerInfo != NULL) {
+    MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (P, Start, SignerInfo));
+    // move to next
+    SignerInfo = SignerInfo->Next;
+  }
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
+
+  return Len;
+}
+
+/**
+  Signed Data Type
+  SignedData ::= SEQUENCE {
+  version Version,
+  digestAlgorithms DigestAlgorithmIdentifiers,
+  contentInfo ContentInfo,
+  certificates
+      [0] IMPLICIT ExtendedCertificatesAndCertificates
+        OPTIONAL,
+  crls
+    [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+  signerInfos SignerInfos }
+
+  DigestAlgorithmIdentifiers ::=
+      SET OF DigestAlgorithmIdentifier
+
+  SignerInfos ::= SET OF SignerInfo.
+
+  @param[in, out]  P            The reference to the current position pointer.
+  @param[in]       Start        The start of the buffer, for bounds-checking.
+  @param[in]       Pkcs7        MbedtlsPkcs7
+
+  @retval number      The number of bytes written to p on success.
+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDer (
+  UINT8         **P,
+  UINT8         *Start,
+  MbedtlsPkcs7  *Pkcs7
+  )
+{
+  INT32              ret;
+  INT32              Len;
+  mbedtls_md_type_t  DigestAlg[1];
+
+  DigestAlg[0] = MBEDTLS_MD_SHA256;
+  Len          = 0;
+
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (P, Start, &(Pkcs7->SignedData.SignerInfos)));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (P, Start, &(Pkcs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (P, Start, NULL, 0));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (P, Start, DigestAlg, 1));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (P, Start, Pkcs7->SignedData.Version));
+
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));
+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+  return Len;
+}
+
+/**
+  Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
+  Syntax Standard, version 1.5". This interface is only intended to be used for
+  application to perform PKCS#7 functionality validation.
+
+  If this interface is not supported, then return FALSE.
+
+  @param[in]  PrivateKey       Pointer to the PEM-formatted private key data for
+                               data signing.
+  @param[in]  PrivateKeySize   Size of the PEM private key data in bytes.
+  @param[in]  KeyPassword      NULL-terminated passphrase used for encrypted PEM
+                               key data.
+  @param[in]  InData           Pointer to the content to be signed.
+  @param[in]  InDataSize       Size of InData in bytes.
+  @param[in]  SignCert         Pointer to signer's DER-encoded certificate to sign with.
+  @param[in]  OtherCerts       Pointer to an optional additional set of certificates to
+                               include in the PKCS#7 signedData (e.g. any intermediate
+                               CAs in the chain).
+  @param[out] SignedData       Pointer to output PKCS#7 signedData. It's caller's
+                               responsibility to free the buffer with FreePool().
+  @param[out] SignedDataSize   Size of SignedData in bytes.
+
+  @retval     TRUE             PKCS#7 data signing succeeded.
+  @retval     FALSE            PKCS#7 data signing failed.
+  @retval     FALSE            This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7Sign (
+  IN CONST UINT8  *PrivateKey,
+  IN UINTN        PrivateKeySize,
+  IN CONST UINT8  *KeyPassword,
+  IN UINT8        *InData,
+  IN UINTN        InDataSize,
+  IN UINT8        *SignCert,
+  IN UINT8        *OtherCerts OPTIONAL,
+  OUT UINT8       **SignedData,
+  OUT UINTN       *SignedDataSize
+  )
+{
+  BOOLEAN             Status;
+  INT32               Ret;
+  mbedtls_pk_context  Pkey;
+  UINT8               HashValue[SHA256_DIGEST_SIZE];
+  UINT8               Signature[MAX_SIGNATURE_SIZE];
+  UINTN               SignatureLen;
+  UINT8               *NewPrivateKey;
+  mbedtls_x509_crt    *Crt;
+
+  MbedtlsPkcs7            Pkcs7;
+  MbedtlsPkcs7SignerInfo  SignerInfo;
+  UINT8                   *Buffer;
+  INTN                    BufferSize;
+  UINT8                   *P;
+  INT32                   Len;
+
+  BufferSize = 4096;
+
+  SignatureLen = MAX_SIGNATURE_SIZE;
+  Crt          = (mbedtls_x509_crt *)SignCert;
+
+  NewPrivateKey = NULL;
+  if (PrivateKey[PrivateKeySize - 1] != 0) {
+    NewPrivateKey = AllocateZeroPool (PrivateKeySize + 1);
+    if (NewPrivateKey == NULL) {
+      return FALSE;
+    }
+
+    CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
+    NewPrivateKey[PrivateKeySize] = 0;
+    PrivateKeySize++;
+  } else {
+    NewPrivateKey = AllocateZeroPool (PrivateKeySize);
+    if (NewPrivateKey == NULL) {
+      return FALSE;
+    }
+
+    CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
+  }
+
+  mbedtls_pk_init (&Pkey);
+  Ret = mbedtls_pk_parse_key (
+          &Pkey,
+          NewPrivateKey,
+          PrivateKeySize,
+          KeyPassword,
+          KeyPassword == NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPassword),
+          NULL,
+          NULL
+          );
+  if (Ret != 0) {
+    Status = FALSE;
+    goto Cleanup;
+  }
+
+  /// Calculate InData Digest
+  ZeroMem (HashValue, SHA256_DIGEST_SIZE);
+  Status = Sha256HashAll (InData, InDataSize, HashValue);
+  if (!Status) {
+    goto Cleanup;
+  }
+
+  /// Pk Sign
+  ZeroMem (Signature, MAX_SIGNATURE_SIZE);
+  Ret = mbedtls_pk_sign (
+          &Pkey,
+          MBEDTLS_MD_SHA256,
+          HashValue,
+          SHA256_DIGEST_SIZE,
+          Signature,
+          MAX_SIGNATURE_SIZE,
+          &SignatureLen,
+          MbedtlsRand,
+          NULL
+          );
+  if (Ret != 0) {
+    Status = FALSE;
+    goto Cleanup;
+  }
+
+  ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7));
+  Pkcs7.SignedData.Version = 1;
+
+  Crt->next                     = (mbedtls_x509_crt *)OtherCerts;
+  Pkcs7.SignedData.Certificates = *Crt;
+
+  SignerInfo.Next              = NULL;
+  SignerInfo.Sig.p             = Signature;
+  SignerInfo.Sig.len           = SignatureLen;
+  SignerInfo.Version           = 1;
+  SignerInfo.AlgIdentifier.p   = MbedtlsOidDigestAlgSha256;
+  SignerInfo.AlgIdentifier.len = sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1;
+  if (mbedtls_pk_get_type (&Pkey) == MBEDTLS_PK_RSA) {
+    SignerInfo.SigAlgIdentifier.p   = MbedtlsOidPkcs1Rsa;
+    SignerInfo.SigAlgIdentifier.len = sizeof (MBEDTLS_OID_PKCS1_RSA) - 1;
+  } else {
+    mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgIdentifier.len);
+  }
+
+  SignerInfo.Serial            = ((mbedtls_x509_crt *)SignCert)->serial;
+  SignerInfo.IssuerRaw         = ((mbedtls_x509_crt *)SignCert)->issuer_raw;
+  Pkcs7.SignedData.SignerInfos = SignerInfo;
+
+  Buffer = AllocateZeroPool (BufferSize);
+  if (Buffer == NULL) {
+    Status = FALSE;
+    goto Cleanup;
+  }
+
+  P   = Buffer + BufferSize;
+  Len = MbedTlsPkcs7WriteDer (&P, Buffer, &Pkcs7);
+
+  /// Enlarge buffer if buffer is too small
+  while (Len < 0 && Len == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
+    BufferSize = BufferSize * 2;
+    P          = Buffer + BufferSize;
+    FreePool (Buffer);
+    Buffer = AllocateZeroPool (BufferSize);
+    if (Buffer == NULL) {
+      Status = FALSE;
+      goto Cleanup;
+    }
+
+    P   = Buffer + BufferSize;
+    Len = MbedTlsPkcs7WriteDer (&P, Buffer, &Pkcs7);
+  }
+
+  if (Len <= 0) {
+    Status = FALSE;
+    goto Cleanup;
+  }
+
+  *SignedData     = AllocateZeroPool (Len);
+  *SignedDataSize = Len;
+  CopyMem (*SignedData, P, Len);
+  Status = TRUE;
+
+Cleanup:
+  if (&Pkey != NULL) {
+    mbedtls_pk_free (&Pkey);
+  }
+
+  if (NewPrivateKey != NULL) {
+    FreePool (NewPrivateKey);
+  }
+
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+  }
+
+  return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
new file mode 100644
index 0000000000..6b62ee2618
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
@@ -0,0 +1,113 @@
+/** @file
+  Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+
+/**
+  Extracts the attached content from a PKCS#7 signed data if existed. The input signed
+  data could be wrapped in a ContentInfo structure.
+
+  If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow,
+  then return FALSE. If the P7Data is not correctly formatted, then return FALSE.
+
+  Caution: This function may receive untrusted input. So this function will do
+           basic check for PKCS#7 data structure.
+
+  @param[in]   P7Data       Pointer to the PKCS#7 signed data to process.
+  @param[in]   P7Length     Length of the PKCS#7 signed data in bytes.
+  @param[out]  Content      Pointer to the extracted content from the PKCS#7 signedData.
+                            It's caller's responsibility to free the buffer with FreePool().
+  @param[out]  ContentSize  The size of the extracted content in bytes.
+
+  @retval     TRUE          The P7Data was correctly formatted for processing.
+  @retval     FALSE         The P7Data was not correctly formatted for processing.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetAttachedContent (
+  IN CONST UINT8  *P7Data,
+  IN UINTN        P7Length,
+  OUT VOID        **Content,
+  OUT UINTN       *ContentSize
+  )
+{
+  BOOLEAN             Status;
+  UINT8               *SignedData;
+  UINTN               SignedDataSize;
+  BOOLEAN             Wrapped;
+  INTN                Ret;
+  mbedtls_pkcs7       Pkcs7;
+  mbedtls_pkcs7_data  *MbedtlsContent;
+
+  mbedtls_pkcs7_init (&Pkcs7);
+
+  //
+  // Check input parameter.
+  //
+  if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) {
+    return FALSE;
+  }
+
+  *Content   = NULL;
+  SignedData = NULL;
+
+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
+  if (!Status || (SignedDataSize > INT_MAX)) {
+    goto _Exit;
+  }
+
+  Status = FALSE;
+
+  Ret = mbedtls_pkcs7_parse_der (&Pkcs7, SignedData, (INT32)SignedDataSize);
+
+  //
+  // The type of Pkcs7 must be signedData
+  //
+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
+    goto _Exit;
+  }
+
+  //
+  // Check for detached or attached content
+  //
+  MbedtlsContent = &(Pkcs7.signed_data.content);
+
+  if (MbedtlsContent == NULL) {
+    //
+    // No Content supplied for PKCS7 detached signedData
+    //
+    *Content     = NULL;
+    *ContentSize = 0;
+  } else {
+    //
+    // Retrieve the attached content in PKCS7 signedData
+    //
+    if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) {
+      *ContentSize = MbedtlsContent->data.len;
+      *Content     = AllocateZeroPool (*ContentSize);
+      if (*Content == NULL) {
+        *ContentSize = 0;
+        goto _Exit;
+      }
+
+      CopyMem (*Content, MbedtlsContent->data.p, *ContentSize);
+    }
+  }
+
+  Status = TRUE;
+
+_Exit:
+  //
+  // Release Resources
+  //
+  mbedtls_pkcs7_free (&Pkcs7);
+
+  return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
new file mode 100644
index 0000000000..f5ca4c528a
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
@@ -0,0 +1,1315 @@
+/** @file
+  PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper
+  Implementation over mbedtls.
+
+  RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
+  FIPS 186-4 - Digital Signature Standard (DSS)
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptPkcs7Internal.h"
+#include <mbedtls/pkcs7.h>
+
+/* Profile for backward compatibility. Allows RSA 1024, unlike the default
+   profile. */
+STATIC mbedtls_x509_crt_profile  gCompatProfile =
+{
+  /* Hashes from SHA-256 and above. Note that this selection
+   * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
+
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) |
+ #endif
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),
+  0xFFFFFFF,       /* Any PK alg    */
+
+  /* Curves at or above 128-bit security level. Note that this selection
+   * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |
+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |
+  0,
+  1024,
+};
+
+/**
+ Init MbedtlsPkcs7.
+
+  @param[in]  Pkcs7     MbedtlsPkcs7.
+**/
+STATIC
+VOID
+MbedTlsPkcs7Init (
+  MbedtlsPkcs7  *Pkcs7
+  )
+{
+  ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7));
+}
+
+/**
+  Get Pkcs7 Next Content Len.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Len          MbedtlsPkcs7 Content Len.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetNextContentLen (
+  UINT8  **P,
+  UINT8  *End,
+  UINTN  *Len
+  )
+{
+  INT32  Ret;
+
+  Ret = mbedtls_asn1_get_tag (P, End, Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+  return Ret;
+}
+
+/**
+  Get Pkcs7 Version..
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Ver          MbedtlsPkcs7 Version.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetVersion (
+  UINT8  **P,
+  UINT8  *End,
+  INT32  *Ver
+  )
+{
+  INT32  Ret;
+
+  Ret = mbedtls_asn1_get_int (P, End, Ver);
+  return Ret;
+}
+
+/**
+   ContentInfo ::= SEQUENCE {
+        contentType ContentType,
+        content
+                [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Pkcs7        MbedtlsPkcs7.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetContentInfoType (
+  UINT8             **P,
+  UINT8             *End,
+  mbedtls_asn1_buf  *Pkcs7
+  )
+{
+  UINTN  Len;
+  int    Ret;
+
+  Len = 0;
+  Ret = mbedtls_asn1_get_tag (
+          P,
+          End,
+          &Len,
+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+          );
+
+  if (Ret == 0) {
+    Ret = mbedtls_asn1_get_tag (P, End, &Len, MBEDTLS_ASN1_OID);
+  }
+
+  if (Ret == 0) {
+    Pkcs7->tag = MBEDTLS_ASN1_OID;
+    Pkcs7->len = Len;
+    Pkcs7->p   = *P;
+  }
+
+  return Ret;
+}
+
+/**
+  DigestAlgorithmIdentifier ::= AlgorithmIdentifier.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Alg          MbedtlsPkcs7 AlgorithmIdentifier.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetDigestAlgorithm (
+  UINT8             **P,
+  UINT8             *End,
+  mbedtls_x509_buf  *Alg
+  )
+{
+  INT32  Ret;
+
+  Ret = mbedtls_asn1_get_alg_null (P, End, Alg);
+  return Ret;
+}
+
+/**
+  DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Alg          MbedtlsPkcs7 AlgorithmIdentifier.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetDigestAlgorithmSet (
+  UINT8             **P,
+  UINT8             *End,
+  mbedtls_x509_buf  *Alg
+  )
+{
+  UINTN  Len;
+  INT32  Ret;
+
+  Len = 0;
+  Ret = mbedtls_asn1_get_tag (
+          P,
+          End,
+          &Len,
+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET
+          );
+
+  if (Ret == 0) {
+    End = *P + Len;
+    // assume only one digest algorithm
+    Ret = mbedtls_asn1_get_alg_null (P, End, Alg);
+  }
+
+  return Ret;
+}
+
+/**
+   certificates :: SET OF ExtendedCertificateOrCertificate,
+   ExtendedCertificateOrCertificate ::= CHOICE {
+        certificate Certificate -- x509,
+        extendedCertificate[0] IMPLICIT ExtendedCertificate }.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  Plen         The buffer len.
+  @param[out] Certs        mbedtls_x509_crt cert.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetCertificates (
+  UINT8             **P,
+  INTN              Plen,
+  mbedtls_x509_crt  *Certs
+  )
+{
+  INT32  Ret;
+
+  Ret = mbedtls_x509_crt_parse (Certs, *P, Plen);
+  return Ret;
+}
+
+/**
+   EncryptedDigest ::= OCTET STRING.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] Signature    Signature.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetSignature (
+  UINT8             **P,
+  UINT8             *End,
+  mbedtls_asn1_buf  *Signature
+  )
+{
+  INT32  Ret;
+  UINTN  Len;
+
+  Len = 0;
+  Ret = mbedtls_asn1_get_tag (P, End, &Len, MBEDTLS_ASN1_OCTET_STRING);
+  if (Ret == 0) {
+    Signature->tag = MBEDTLS_ASN1_OCTET_STRING;
+    Signature->len = Len;
+    Signature->p   = *P;
+  }
+
+  return Ret;
+}
+
+/**
+   SignerInfo ::= SEQUENCE {
+        version Version;
+        issuerAndSerialNumber   IssuerAndSerialNumber,
+        digestAlgorithm DigestAlgorithmIdentifier,
+        authenticatedAttributes
+                [0] IMPLICIT Attributes OPTIONAL,
+        digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+        encryptedDigest EncryptedDigest,
+        unauthenticatedAttributes
+                [1] IMPLICIT Attributes OPTIONAL.
+
+  @param[in]  P            The start of the buffer.
+  @param[in]  End          The end of the buffer.
+  @param[out] SignersSet   MbedtlsPkcs7SignerInfo.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetSignersInfoSet (
+  UINT8                   **P,
+  UINT8                   *End,
+  MbedtlsPkcs7SignerInfo  *SignersSet
+  )
+{
+  UINT8  *EndSet;
+  INT32  Ret;
+  UINTN  Len;
+  UINT8  *TempP;
+
+  Len = 0;
+
+  Ret = mbedtls_asn1_get_tag (
+          P,
+          End,
+          &Len,
+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET
+          );
+
+  if (Ret == 0) {
+    EndSet = *P + Len;
+
+    Ret = mbedtls_asn1_get_tag (
+            P,
+            EndSet,
+            &Len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+            );
+  }
+
+  if (Ret == 0) {
+    Ret = mbedtls_asn1_get_int (P, EndSet, &SignersSet->Version);
+  }
+
+  if (Ret == 0) {
+    Ret = mbedtls_asn1_get_tag (
+            P,
+            EndSet,
+            &Len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+            );
+  }
+
+  if (Ret == 0) {
+    SignersSet->IssuerRaw.p = *P;
+    Ret                     = mbedtls_asn1_get_tag (
+                                P,
+                                EndSet,
+                                &Len,
+                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+                                );
+  }
+
+  if (Ret == 0) {
+    Ret = mbedtls_x509_get_name (P, *P + Len, &SignersSet->Issuer);
+  }
+
+  if (Ret == 0) {
+    SignersSet->IssuerRaw.len = *P - SignersSet->IssuerRaw.p;
+
+    Ret = mbedtls_x509_get_serial (P, EndSet, &SignersSet->Serial);
+  }
+
+  if (Ret == 0) {
+    Ret = MbedTlsPkcs7GetDigestAlgorithm (P, EndSet, &SignersSet->AlgIdentifier);
+  }
+
+  // OPTIONAL AuthenticatedAttributes
+  if (Ret == 0) {
+    TempP = *P;
+    if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+      SignersSet->AuthAttr.len = Len + (TempP - *P);
+      SignersSet->AuthAttr.p   = *P;
+      *P                       = TempP + Len;
+    } else {
+      SignersSet->AuthAttr.p = NULL;
+    }
+  }
+
+  if (Ret == 0) {
+    Ret = MbedTlsPkcs7GetDigestAlgorithm (P, EndSet, &SignersSet->SigAlgIdentifier);
+  }
+
+  if (Ret == 0) {
+    Ret = Pkcs7GetSignature (P, End, &SignersSet->Sig);
+  }
+
+  if (Ret == 0) {
+    SignersSet->Next = NULL;
+  }
+
+  return Ret;
+}
+
+/**
+   SignedData ::= SEQUENCE {
+        version Version,
+        digestAlgorithms DigestAlgorithmIdentifiers,
+        contentInfo ContentInfo,
+        certificates
+                [0] IMPLICIT ExtendedCertificatesAndCertificates
+                    OPTIONAL,
+        crls
+                [0] IMPLICIT CertificateRevocationLists OPTIONAL,
+        signerInfos SignerInfos }.
+
+  @param[in]  Buffer       The start of the buffer.
+  @param[in]  BufferLen    The len the buffer.
+  @param[out] SignedData   MbedtlsPkcs7SignedData.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetSignedData (
+  UINT8                   *Buffer,
+  INTN                    BufferLen,
+  MbedtlsPkcs7SignedData  *SignedData
+  )
+{
+  UINT8             *P;
+  UINT8             *End;
+  UINTN             Len;
+  INT32             Ret;
+  UINT8             *CertP;
+  UINTN             CertLen;
+  UINT8             *OldCertP;
+  UINTN             TotalCertLen;
+  mbedtls_x509_crt  *MoreCert;
+  UINT8             CertNum;
+  mbedtls_x509_crt  *LastCert;
+
+  Len      = 0;
+  P        = Buffer;
+  End      = Buffer + BufferLen;
+  MoreCert = NULL;
+
+  Ret = mbedtls_asn1_get_tag (
+          &P,
+          End,
+          &Len,
+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+          );
+
+  if (Ret == 0) {
+    // version
+    Ret = MbedTlsPkcs7GetVersion (&P, End, &SignedData->Version);
+  }
+
+  if ((Ret == 0) && (SignedData->Version != 1)) {
+    Ret = -1;
+  }
+
+  if (Ret == 0) {
+    // digest algorithm
+    Ret = MbedTlsPkcs7GetDigestAlgorithmSet (
+            &P,
+            End,
+            &SignedData->DigestAlgorithms
+            );
+  }
+
+  if (Ret == 0) {
+    if (
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA1) - 1) &&
+         (CompareMem (
+            SignedData->DigestAlgorithms.p,
+            MBEDTLS_OID_DIGEST_ALG_SHA1,
+            SignedData->DigestAlgorithms.len
+            ) == 0)) ||
+ #endif
+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1) &&
+         (CompareMem (
+            SignedData->DigestAlgorithms.p,
+            MBEDTLS_OID_DIGEST_ALG_SHA256,
+            SignedData->DigestAlgorithms.len
+            ) == 0)) ||
+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA384) - 1) &&
+         (CompareMem (
+            SignedData->DigestAlgorithms.p,
+            MBEDTLS_OID_DIGEST_ALG_SHA384,
+            SignedData->DigestAlgorithms.len
+            ) == 0)) ||
+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA512) - 1) &&
+         (CompareMem (
+            SignedData->DigestAlgorithms.p,
+            MBEDTLS_OID_DIGEST_ALG_SHA512,
+            SignedData->DigestAlgorithms.len
+            ) == 0)))
+    {
+      Ret = 0;
+    } else {
+      Ret = -1;
+    }
+  }
+
+  if (Ret == 0) {
+    Ret = Pkcs7GetContentInfoType (&P, End, &SignedData->ContentInfo.Oid);
+  }
+
+  if (Ret == 0) {
+    // move to next
+    P     = P + SignedData->ContentInfo.Oid.len;
+    Ret   = MbedTlsPkcs7GetNextContentLen (&P, End, &Len);
+    CertP = P + Len;
+
+    // move to actual cert, if there are more [0]
+    if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) == 0) {
+      Len = CertLen;
+      P   = CertP;
+    }
+  }
+
+  // certificates: may have many certs
+  CertP = P;
+
+  TotalCertLen = 0;
+
+  MoreCert = &SignedData->Certificates;
+  CertNum  = 0;
+
+  while (TotalCertLen < Len) {
+    OldCertP = CertP;
+
+    Ret = mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (Ret != 0) {
+      goto End;
+    }
+
+    // cert total len
+    CertLen = CertLen + (CertP - OldCertP);
+
+    // move to next cert
+    CertP = OldCertP + CertLen;
+
+    // change TotalCertLen
+    TotalCertLen += CertLen;
+
+    mbedtls_x509_crt_init (MoreCert);
+    Ret = MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert);
+    if (Ret != 0) {
+      goto End;
+    }
+
+    CertNum++;
+    MoreCert->next = AllocateZeroPool (sizeof (mbedtls_x509_crt));
+    MoreCert       = MoreCert->next;
+  }
+
+  if (TotalCertLen != Len) {
+    Ret = -1;
+    goto End;
+  }
+
+  LastCert = &(SignedData->Certificates);
+
+  while (CertNum--) {
+    if (CertNum == 0) {
+      LastCert->next = NULL;
+      break;
+    } else {
+      LastCert = LastCert->next;
+    }
+  }
+
+  // signers info
+  if (Ret == 0) {
+    P   = P + Len;
+    Ret = MbedTlsPkcs7GetSignersInfoSet (&P, End, &SignedData->SignerInfos);
+  }
+
+End:
+  if (MoreCert != NULL) {
+    FreePool (MoreCert);
+    MoreCert = NULL;
+  }
+
+  return Ret;
+}
+
+/**
+  Parse MbedtlsPkcs7 to Der format.
+  @param[in]  Buffer       The start of the buffer.
+  @param[in]  BufferLen    The len the buffer.
+  @param[out] Pkcs7        MbedtlsPkcs7.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedtlsPkcs7ParseDer (
+  CONST UINT8   *Buffer,
+  INTN          BufferLen,
+  MbedtlsPkcs7  *Pkcs7
+  )
+{
+  UINT8  *P;
+  UINT8  *End;
+  UINTN  Len;
+  INT32  Ret;
+
+  if (Pkcs7 == NULL) {
+    return -1;
+  }
+
+  Len = 0;
+  P   = (UINT8 *)Buffer;
+  End = P + BufferLen;
+
+  Ret = Pkcs7GetContentInfoType (&P, End, &Pkcs7->ContentTypeOid);
+  if (Ret != 0) {
+    goto out;
+  }
+
+  if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0)) {
+    // Invalid PKCS7 data type;
+    Ret = -1;
+    goto out;
+  }
+
+  if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, Pkcs7->ContentTypeOid.len) != 0) {
+    // Invalid PKCS7 data type;
+    Ret = -1;
+    goto out;
+  }
+
+  // Content type is SignedData
+  P = P + Pkcs7->ContentTypeOid.len;
+
+  Ret = MbedTlsPkcs7GetNextContentLen (&P, End, &Len);
+  if (Ret != 0) {
+    goto out;
+  }
+
+  Ret = Pkcs7GetSignedData (P, Len, &Pkcs7->SignedData);
+  if (Ret != 0) {
+    goto out;
+  }
+
+out:
+  return Ret;
+}
+
+/**
+  MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo.
+  @param[in]  SignerInfo   MbedtlsPkcs7 SignerInfo.
+  @param[in]  Cert         cert.
+  @param[in]  Data         Pointer for data.
+  @param[in]  DataLen      The len the buffer.
+
+  @retval 0                Success.
+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedtlsPkcs7SignedDataVerifySigners (
+  MbedtlsPkcs7SignerInfo  *SignerInfo,
+  mbedtls_x509_crt        *Cert,
+  CONST UINT8             *Data,
+  INTN                    DataLen
+  )
+{
+  INT32                    Ret;
+  UINT8                    Hash[MBEDTLS_MD_MAX_SIZE];
+  mbedtls_pk_context       Pk;
+  CONST mbedtls_md_info_t  *MdInfo;
+  INTN                     HashLen;
+  UINT8                    TempAuthAttr;
+
+  Pk = Cert->pk;
+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+
+  // all the hash algo
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1);
+  HashLen = mbedtls_md_get_size (MdInfo);
+  mbedtls_md (MdInfo, Data, DataLen, Hash);
+  if (SignerInfo->AuthAttr.p != NULL) {
+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);
+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+    // Restore content
+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+  }
+
+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+
+  if (Ret == 0) {
+    return Ret;
+  }
+
+ #endif
+
+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256);
+  HashLen = mbedtls_md_get_size (MdInfo);
+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+  mbedtls_md (MdInfo, Data, DataLen, Hash);
+  if (SignerInfo->AuthAttr.p != NULL) {
+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);
+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+    // Restore content
+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+  }
+
+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+  if (Ret == 0) {
+    return Ret;
+  }
+
+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA384);
+  HashLen = mbedtls_md_get_size (MdInfo);
+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+  mbedtls_md (MdInfo, Data, DataLen, Hash);
+  if (SignerInfo->AuthAttr.p != NULL) {
+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);
+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+    // Restore content
+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+  }
+
+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+  if (Ret == 0) {
+    return Ret;
+  }
+
+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA512);
+  HashLen = mbedtls_md_get_size (MdInfo);
+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+  mbedtls_md (MdInfo, Data, DataLen, Hash);
+  if (SignerInfo->AuthAttr.p != NULL) {
+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);
+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+    // Restore content
+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+  }
+
+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+  if (Ret == 0) {
+    return Ret;
+  }
+
+  return Ret;
+}
+
+/**
+  Find signer cert in MbedtlsPkcs7SignerInfo.
+
+  @param[in]  SignerInfo   MbedtlsPkcs7 SignerInfo.
+  @param[in]  Certs        MbedtlsPkcs7 SignerInfo certs.
+
+  @retval cert             Signer Cert.
+**/
+STATIC
+mbedtls_x509_crt *
+MbedTlsPkcs7FindSignerCert (
+  MbedtlsPkcs7SignerInfo  *SignerInfo,
+  mbedtls_x509_crt        *Certs
+  )
+{
+  mbedtls_x509_crt  *Cert;
+
+  Cert = Certs;
+  while (Cert != NULL) {
+    if ((Cert->issuer_raw.len == SignerInfo->IssuerRaw.len) &&
+        (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->issuer_raw.len) == 0) &&
+        (Cert->serial.len == SignerInfo->Serial.len) &&
+        (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.len) == 0))
+    {
+      break;
+    }
+
+    Cert = Cert->next;
+  }
+
+  return Cert;
+}
+
+/**
+  verify cert.
+
+  @param[in]  Ca    CA cert.
+  @param[in]  CaCrl CRL.
+  @param[in]  End   Cert which need be verified.
+
+  @retval TRUE      Verify successfully.
+  @retval FALSE     Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7VerifyCert (
+  mbedtls_x509_crt  *Ca,
+  mbedtls_x509_crl  *CaCrl,
+  mbedtls_x509_crt  *End
+  )
+{
+  INT32                     Ret;
+  UINT32                    VFlag;
+  mbedtls_x509_crt_profile  Profile;
+
+  VFlag = 0;
+  CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));
+
+  Ret = mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, NULL, &VFlag, NULL, NULL);
+
+  return Ret == 0;
+}
+
+/**
+  verify cert chain.
+
+  @param[in]  Pkcs7 MbedtlsPkcs7.
+  @param[in]  Ca    CA cert.
+  @param[in]  End   Cert which need be verified.
+
+  @retval TRUE      Verify successfully.
+  @retval FALSE     Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7VerifyCertChain (
+  MbedtlsPkcs7      *Pkcs7,
+  mbedtls_x509_crt  *Ca,
+  mbedtls_x509_crt  *End
+  )
+{
+  mbedtls_x509_crt  *AllCert;
+  mbedtls_x509_crt  *InterCert;
+
+  AllCert   = &(Pkcs7->SignedData.Certificates);
+  InterCert = NULL;
+
+  while (AllCert != NULL) {
+    if ((AllCert->next == End) && (MbedTlsPkcs7VerifyCert (AllCert, NULL, End))) {
+      InterCert = AllCert;
+      break;
+    }
+
+    AllCert = AllCert->next;
+  }
+
+  if (InterCert == NULL) {
+    return FALSE;
+  }
+
+  if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) {
+    return TRUE;
+  } else {
+    return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert);
+  }
+}
+
+/**
+  MbedTlsPkcs7 Verify SignedData.
+
+  @param[in]  Pkcs7        MbedtlsPkcs7.
+  @param[in]  TrustCert    CA cert.
+  @param[in]  Data         Pointer for data.
+  @param[in]  DataLen      The len the buffer.
+
+  @retval TRUE      Verify successfully.
+  @retval FALSE     Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7SignedDataVerify (
+  MbedtlsPkcs7      *Pkcs7,
+  mbedtls_x509_crt  *TrustCert,
+  CONST UINT8       *Data,
+  INTN              DataLen
+  )
+{
+  MbedtlsPkcs7SignerInfo  *SignerInfo;
+  mbedtls_x509_crt        *Cert;
+  mbedtls_x509_crt        *AllCert;
+  BOOLEAN                 Result;
+
+  SignerInfo = &(Pkcs7->SignedData.SignerInfos);
+  Result     = TRUE;
+
+  //
+  // Traverse signers and verify each signers
+  //
+  while (SignerInfo != NULL) {
+    Result = FALSE;
+    // 1. Find signers cert
+    Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.Certificates));
+    if (Cert != NULL) {
+      // 2. Check signer cert is trusted by trustCert
+      if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Cert)) {
+        // root cert verify pass
+        Result = TRUE;
+      } else {
+        if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) {
+          Result = TRUE;
+        } else {
+          Result = FALSE;
+        }
+      }
+
+      if (Result == TRUE) {
+        // 3. Check signed data
+        AllCert = &(Pkcs7->SignedData.Certificates);
+        while (AllCert != NULL) {
+          if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Data, DataLen) == 0) {
+            return TRUE;
+          }
+
+          AllCert = AllCert->next;
+        }
+
+        Result = FALSE;
+      }
+    }
+
+    // move to next
+    SignerInfo = SignerInfo->Next;
+  }
+
+  return Result;
+}
+
+/**
+  Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+  a new structure to wrap P7Data.
+
+  Caution: This function may receive untrusted input.
+  UEFI Authenticated Variable is external input, so this function will do basic
+  check for PKCS#7 data structure.
+
+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.
+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.
+  @param[out] WrapFlag     If TRUE P7Data is a ContentInfo structure, otherwise
+                           return FALSE.
+  @param[out] WrapData     If return status of this function is TRUE:
+                           1) when WrapFlag is TRUE, pointer to P7Data.
+                           2) when WrapFlag is FALSE, pointer to a new ContentInfo
+                           structure. It's caller's responsibility to free this
+                           buffer.
+  @param[out] WrapDataSize Length of ContentInfo structure in bytes.
+
+  @retval     TRUE         The operation is finished successfully.
+  @retval     FALSE        The operation is failed due to lack of resources.
+
+**/
+BOOLEAN
+WrapPkcs7Data (
+  IN CONST UINT8  *P7Data,
+  IN UINTN        P7Length,
+  OUT BOOLEAN     *WrapFlag,
+  OUT UINT8       **WrapData,
+  OUT UINTN       *WrapDataSize
+  )
+{
+  BOOLEAN  Wrapped;
+  UINT8    *SignedData;
+
+  //
+  // Check whether input P7Data is a wrapped ContentInfo structure or not.
+  //
+  Wrapped = FALSE;
+  if ((P7Data[4] == 0x06) && (P7Data[5] == 0x09)) {
+    if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1) == 0) {
+      if ((P7Data[15] == 0xA0) && (P7Data[16] == 0x82)) {
+        Wrapped = TRUE;
+      }
+    }
+  }
+
+  if (Wrapped) {
+    *WrapData     = (UINT8 *)P7Data;
+    *WrapDataSize = P7Length;
+  } else {
+    //
+    // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.
+    //
+    *WrapDataSize = P7Length + 19;
+    *WrapData     = AllocateZeroPool (*WrapDataSize);
+    if (*WrapData == NULL) {
+      *WrapFlag = Wrapped;
+      return FALSE;
+    }
+
+    SignedData = *WrapData;
+
+    //
+    // Part1: 0x30, 0x82.
+    //
+    SignedData[0] = 0x30;
+    SignedData[1] = 0x82;
+
+    //
+    // Part2: Length1 = P7Length + 19 - 4, in big endian.
+    //
+    SignedData[2] = (UINT8)(((UINT16)(*WrapDataSize - 4)) >> 8);
+    SignedData[3] = (UINT8)(((UINT16)(*WrapDataSize - 4)) & 0xff);
+
+    //
+    // Part3: 0x06, 0x09.
+    //
+    SignedData[4] = 0x06;
+    SignedData[5] = 0x09;
+
+    //
+    // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.
+    //
+    CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1);
+
+    //
+    // Part5: 0xA0, 0x82.
+    //
+    SignedData[15] = 0xA0;
+    SignedData[16] = 0x82;
+
+    //
+    // Part6: Length2 = P7Length, in big endian.
+    //
+    SignedData[17] = (UINT8)(((UINT16)P7Length) >> 8);
+    SignedData[18] = (UINT8)(((UINT16)P7Length) & 0xff);
+
+    //
+    // Part7: P7Data.
+    //
+    CopyMem (SignedData + 19, P7Data, P7Length);
+  }
+
+  *WrapFlag = Wrapped;
+  return TRUE;
+}
+
+/**
+  Verifies the validity of a PKCS#7 signed data as described in "PKCS #7:
+  Cryptographic Message Syntax Standard". The input signed data could be wrapped
+  in a ContentInfo structure.
+
+  If P7Data, TrustedCert or InData is NULL, then return FALSE.
+  If P7Length, CertLength or DataLength overflow, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.
+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.
+  @param[in]  TrustedCert  Pointer to a trusted/root certificate encoded in DER, which
+                           is used for certificate chain verification.
+  @param[in]  CertLength   Length of the trusted certificate in bytes.
+  @param[in]  InData       Pointer to the content to be verified.
+  @param[in]  DataLength   Length of InData in bytes.
+
+  @retval  TRUE  The specified PKCS#7 signed data is valid.
+  @retval  FALSE Invalid PKCS#7 signed data.
+  @retval  FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7Verify (
+  IN CONST UINT8  *P7Data,
+  IN UINTN        P7Length,
+  IN CONST UINT8  *TrustedCert,
+  IN UINTN        CertLength,
+  IN CONST UINT8  *InData,
+  IN UINTN        DataLength
+  )
+{
+  BOOLEAN           Status;
+  UINT8             *WrapData;
+  UINTN             WrapDataSize;
+  BOOLEAN           Wrapped;
+  MbedtlsPkcs7      Pkcs7;
+  INT32             Ret;
+  mbedtls_x509_crt  Crt;
+
+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);
+
+  if (Status) {
+    Ret    = 0;
+    Status = FALSE;
+  } else {
+    Ret = -1;
+  }
+
+  MbedTlsPkcs7Init (&Pkcs7);
+  mbedtls_x509_crt_init (&Crt);
+
+  if (Ret == 0) {
+    Ret = MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7);
+  }
+
+  if (Ret == 0) {
+    Ret = mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength);
+  }
+
+  if (Ret == 0) {
+    Status = MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)DataLength);
+  }
+
+  if (&Crt != NULL) {
+    mbedtls_x509_crt_free (&Crt);
+  }
+
+  return Status;
+}
+
+/**
+  Wrap function to use free() to free allocated memory for certificates.
+
+  @param[in]  Certs        Pointer to the certificates to be freed.
+
+**/
+VOID
+EFIAPI
+Pkcs7FreeSigners (
+  IN UINT8  *Certs
+  )
+{
+  if (Certs == NULL) {
+    return;
+  }
+
+  FreePool (Certs);
+}
+
+/**
+  Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:
+  Cryptographic Message Syntax Standard". The input signed data could be wrapped
+  in a ContentInfo structure.
+
+  If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then
+  return FALSE. If P7Length overflow, then return FALSE.
+
+  Caution: This function may receive untrusted input.
+  UEFI Authenticated Variable is external input, so this function will do basic
+  check for PKCS#7 data structure.
+
+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.
+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.
+  @param[out] CertStack    Pointer to Signer's certificates retrieved from P7Data.
+                           It's caller's responsibility to free the buffer with
+                           Pkcs7FreeSigners().
+                           This data structure is EFI_CERT_STACK type.
+  @param[out] StackLength  Length of signer's certificates in bytes.
+  @param[out] TrustedCert  Pointer to a trusted certificate from Signer's certificates.
+                           It's caller's responsibility to free the buffer with
+                           Pkcs7FreeSigners().
+  @param[out] CertLength   Length of the trusted certificate in bytes.
+
+  @retval  TRUE            The operation is finished successfully.
+  @retval  FALSE           Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetSigners (
+  IN CONST UINT8  *P7Data,
+  IN UINTN        P7Length,
+  OUT UINT8       **CertStack,
+  OUT UINTN       *StackLength,
+  OUT UINT8       **TrustedCert,
+  OUT UINTN       *CertLength
+  )
+{
+  MbedtlsPkcs7SignerInfo  *SignerInfo;
+  mbedtls_x509_crt        *Cert;
+  MbedtlsPkcs7            Pkcs7;
+  BOOLEAN                 Status;
+  UINT8                   *WrapData;
+  UINTN                   WrapDataSize;
+  BOOLEAN                 Wrapped;
+
+  UINTN  CertSize;
+  UINT8  Index;
+  UINT8  *CertBuf;
+  UINT8  *OldBuf;
+  UINTN  BufferSize;
+  UINTN  OldSize;
+
+  if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||
+      (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX))
+  {
+    return FALSE;
+  }
+
+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);
+
+  if (!Status) {
+    return FALSE;
+  }
+
+  Status  = FALSE;
+  CertBuf = NULL;
+  OldBuf  = NULL;
+  Cert    = NULL;
+
+  MbedTlsPkcs7Init (&Pkcs7);
+  if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) != 0) {
+    goto _Exit;
+  }
+
+  SignerInfo = &(Pkcs7.SignedData.SignerInfos);
+
+  //
+  // Traverse each signers
+  //
+  // Convert CertStack to buffer in following format:
+  // UINT8  CertNumber;
+  // UINT32 Cert1Length;
+  // UINT8  Cert1[];
+  // UINT32 Cert2Length;
+  // UINT8  Cert2[];
+  // ...
+  // UINT32 CertnLength;
+  // UINT8  Certn[];
+  //
+  BufferSize = sizeof (UINT8);
+  OldSize    = BufferSize;
+  Index      = 0;
+
+  while (SignerInfo != NULL) {
+    // Find signers cert
+    Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Certificates));
+    if (Cert == NULL) {
+      goto _Exit;
+    }
+
+    CertSize   = Cert->raw.len;
+    OldSize    = BufferSize;
+    OldBuf     = CertBuf;
+    BufferSize = OldSize + CertSize + sizeof (UINT32);
+
+    CertBuf = AllocateZeroPool (BufferSize);
+    if (CertBuf == NULL) {
+      goto _Exit;
+    }
+
+    if (OldBuf != NULL) {
+      CopyMem (CertBuf, OldBuf, OldSize);
+      free (OldBuf);
+      OldBuf = NULL;
+    }
+
+    WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize);
+    CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize);
+
+    Index++;
+
+    // move to next
+    SignerInfo = SignerInfo->Next;
+  }
+
+  if (CertBuf != NULL) {
+    //
+    // Update CertNumber.
+    //
+    CertBuf[0] = Index;
+
+    *CertLength  = BufferSize - OldSize - sizeof (UINT32);
+    *TrustedCert = AllocateZeroPool (*CertLength);
+    if (*TrustedCert == NULL) {
+      goto _Exit;
+    }
+
+    CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);
+    *CertStack   = CertBuf;
+    *StackLength = BufferSize;
+    Status       = TRUE;
+  }
+
+_Exit:
+  //
+  // Release Resources
+  //
+  if (!Status && (CertBuf != NULL)) {
+    FreePool (CertBuf);
+    *CertStack = NULL;
+  }
+
+  if (OldBuf != NULL) {
+    FreePool (OldBuf);
+  }
+
+  return Status;
+}
+
+/**
+  Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:
+  Cryptographic Message Syntax Standard", and outputs two certificate lists chained and
+  unchained to the signer's certificates.
+  The input signed data could be wrapped in a ContentInfo structure.
+
+  @param[in]  P7Data            Pointer to the PKCS#7 message.
+  @param[in]  P7Length          Length of the PKCS#7 message in bytes.
+  @param[out] SignerChainCerts  Pointer to the certificates list chained to signer's
+                                certificate. It's caller's responsibility to free the buffer
+                                with Pkcs7FreeSigners().
+                                This data structure is EFI_CERT_STACK type.
+  @param[out] ChainLength       Length of the chained certificates list buffer in bytes.
+  @param[out] UnchainCerts      Pointer to the unchained certificates lists. It's caller's
+                                responsibility to free the buffer with Pkcs7FreeSigners().
+                                This data structure is EFI_CERT_STACK type.
+  @param[out] UnchainLength     Length of the unchained certificates list buffer in bytes.
+
+  @retval  TRUE         The operation is finished successfully.
+  @retval  FALSE        Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetCertificatesList (
+  IN CONST UINT8  *P7Data,
+  IN UINTN        P7Length,
+  OUT UINT8       **SignerChainCerts,
+  OUT UINTN       *ChainLength,
+  OUT UINT8       **UnchainCerts,
+  OUT UINTN       *UnchainLength
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
new file mode 100644
index 0000000000..23ea676373
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
@@ -0,0 +1,689 @@
+/** @file
+  This module verifies that Enhanced Key Usages (EKU's) are present within
+  a PKCS7 signature blob using MbedTLS.
+
+  Copyright (C) Microsoft Corporation. All Rights Reserved.
+  Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+#include <mbedtls/asn1write.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  EkuOID[] = { 0x55, 0x1D, 0x25 };
+
+/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gBasicConstraintsCase1[] = { 0x30, 0x00 };
+
+/*leaf Cert basic_constraints case2: CA: false */
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 };
+
+/**
+  Find first Extension data match with given OID
+
+  @param[in]      Start             Pointer to the DER-encoded extensions data
+  @param[in]      End               extensions data size in bytes
+  @param[in ]     Oid               OID for match
+  @param[in ]     OidSize           OID size in bytes
+  @param[out]     FindExtensionData output matched extension data.
+  @param[out]     FindExtensionDataLen matched extension data size.
+
+**/
+STATIC
+BOOLEAN
+InternalX509FindExtensionData (
+  UINT8        *Start,
+  UINT8        *End,
+  CONST UINT8  *Oid,
+  UINTN        OidSize,
+  UINT8        **FindExtensionData,
+  UINTN        *FindExtensionDataLen
+  )
+{
+  UINT8    *Ptr;
+  UINT8    *ExtensionPtr;
+  UINTN    ObjLen;
+  INT32    Ret;
+  BOOLEAN  Status;
+  UINTN    FindExtensionLen;
+  UINTN    HeaderLen;
+
+  /*If no Extension entry match Oid*/
+  Status = FALSE;
+  Ptr    = Start;
+
+  Ret = 0;
+
+  while (TRUE) {
+    //
+    // Extension  ::=  SEQUENCE  {
+    //     extnID      OBJECT IDENTIFIER,
+    //     critical    BOOLEAN DEFAULT FALSE,
+    //     extnValue   OCTET STRING  }
+    //
+    ExtensionPtr = Ptr;
+    Ret          = mbedtls_asn1_get_tag (
+                     &Ptr,
+                     End,
+                     &ObjLen,
+                     MBEDTLS_ASN1_CONSTRUCTED |
+                     MBEDTLS_ASN1_SEQUENCE
+                     );
+    if (Ret == 0) {
+      HeaderLen        = (UINTN)(Ptr - ExtensionPtr);
+      FindExtensionLen = ObjLen;
+      /* Get Object Identifier*/
+      Ret = mbedtls_asn1_get_tag (
+              &Ptr,
+              End,
+              &ObjLen,
+              MBEDTLS_ASN1_OID
+              );
+    } else {
+      break;
+    }
+
+    if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) {
+      Ptr += ObjLen;
+
+      Ret = mbedtls_asn1_get_tag (
+              &Ptr,
+              End,
+              &ObjLen,
+              MBEDTLS_ASN1_BOOLEAN
+              );
+      if (Ret == 0) {
+        Ptr += ObjLen;
+      }
+
+      Ret = mbedtls_asn1_get_tag (
+              &Ptr,
+              End,
+              &ObjLen,
+              MBEDTLS_ASN1_OCTET_STRING
+              );
+    } else {
+      Ret = 1;
+    }
+
+    if (Ret == 0) {
+      *FindExtensionData    = Ptr;
+      *FindExtensionDataLen = ObjLen;
+      Status                = TRUE;
+      break;
+    }
+
+    /* move to next*/
+    Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
+    Ret = 0;
+  }
+
+  return Status;
+}
+
+/**
+  Retrieve Extension data from one X.509 certificate.
+
+  @param[in]      Cert             Pointer to the  X509 certificate.
+  @param[in]      Oid              Object identifier buffer
+  @param[in]      OidSize          Object identifier buffer size
+  @param[out]     ExtensionData    Extension bytes.
+  @param[in, out] ExtensionDataSize Extension bytes size.
+
+  @retval RETURN_SUCCESS           The certificate Extension data retrieved successfully.
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+                                  If ExtensionDataSize is NULL.
+                                  If ExtensionData is not NULL and *ExtensionDataSize is 0.
+                                  If Certificate is invalid.
+  @retval RETURN_NOT_FOUND         If no Extension entry match Oid.
+  @retval RETURN_BUFFER_TOO_SMALL  If the ExtensionData is NULL. The required buffer size
+                                  is returned in the ExtensionDataSize parameter.
+  @retval RETURN_UNSUPPORTED       The operation is not supported.
+**/
+STATIC
+BOOLEAN
+GetExtensionData (
+  CONST mbedtls_x509_crt  *Cert,
+  CONST UINT8             *Oid,
+  UINTN                   OidSize,
+  UINT8                   *ExtensionData,
+  UINTN                   *ExtensionDataSize
+  )
+{
+  CONST mbedtls_x509_crt  *Crt;
+  INT32                   Ret;
+  BOOLEAN                 Status;
+  UINT8                   *Ptr;
+  UINT8                   *End;
+  UINTN                   ObjLen;
+
+  Ptr    = NULL;
+  End    = NULL;
+  ObjLen = 0;
+
+  if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) ||
+      (ExtensionDataSize == NULL))
+  {
+    return FALSE;
+  }
+
+  Status = FALSE;
+
+  Crt = Cert;
+
+  Ptr = Crt->v3_ext.p;
+  End = Crt->v3_ext.p + Crt->v3_ext.len;
+  Ret = mbedtls_asn1_get_tag (
+          &Ptr,
+          End,
+          &ObjLen,
+          MBEDTLS_ASN1_CONSTRUCTED |
+          MBEDTLS_ASN1_SEQUENCE
+          );
+
+  if (Ret == 0) {
+    Status = InternalX509FindExtensionData (
+               Ptr,
+               End,
+               Oid,
+               OidSize,
+               &Ptr,
+               &ObjLen
+               );
+  }
+
+  if (Status) {
+    if (*ExtensionDataSize < ObjLen) {
+      *ExtensionDataSize = ObjLen;
+      Status             = FALSE;
+      goto cleanup;
+    }
+
+    if (Oid != NULL) {
+      if (ExtensionData == NULL) {
+        return FALSE;
+      }
+
+      CopyMem (ExtensionData, Ptr, ObjLen);
+    }
+
+    *ExtensionDataSize = ObjLen;
+  } else {
+    *ExtensionDataSize = 0;
+  }
+
+cleanup:
+  return Status;
+}
+
+/**
+  Determines if the specified EKU represented in ASN1 form is present
+  in a given certificate.
+
+  @param[in]  Cert                  The certificate to check.
+  @param[in]  EKU                   The EKU to look for.
+  @param[in]  EkuLen                The size of EKU.
+
+  @retval EFI_SUCCESS               We successfully identified the signing type.
+  @retval EFI_INVALID_PARAMETER     A parameter was invalid.
+  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.
+
+**/
+STATIC
+EFI_STATUS
+IsEkuInCertificate (
+  IN CONST mbedtls_x509_crt  *Cert,
+  IN UINT8                   *EKU,
+  IN UINTN                   EkuLen
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     Ret;
+  UINT8       *Buffer;
+  UINTN       Index;
+  UINTN       Len;
+
+  if ((Cert == NULL) || (EKU == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  Len    = 0;
+  Buffer = NULL;
+  Ret    = GetExtensionData (
+             Cert,
+             (CONST UINT8 *)EkuOID,
+             sizeof (EkuOID),
+             NULL,
+             &Len
+             );
+  if (Len == 0) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  Buffer = AllocateZeroPool (Len);
+  if (Buffer == NULL) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  Ret = GetExtensionData (
+          Cert,
+          (CONST UINT8 *)EkuOID,
+          sizeof (EkuOID),
+          Buffer,
+          &Len
+          );
+
+  if ((Len == 0) || (!Ret)) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  Status = EFI_NOT_FOUND;
+  /*find the spdm hardware identity OID*/
+  for (Index = 0; Index <= Len - EkuLen; Index++) {
+    if (!CompareMem (Buffer + Index, EKU, EkuLen)) {
+      // check sub EKU
+      if (Index == Len - EkuLen) {
+        Status = EFI_SUCCESS;
+        break;
+        // Ensure that the OID is complete
+      } else if (Buffer[Index + EkuLen] == 0x06) {
+        Status = EFI_SUCCESS;
+        break;
+      } else {
+        break;
+      }
+    }
+  }
+
+Exit:
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+  }
+
+  return Status;
+}
+
+/**
+  Get OID from txt.
+
+  @param[in]  RequiredEKUs         Array of null-terminated strings listing OIDs of
+                                   required EKUs that must be present in the signature.
+  @param[in]  RequiredEKUsSize     Number of elements in the RequiredEKUs string array.
+  @param[in,out]  CheckOid         OID.
+  @param[out]     OidLen           The size of OID.
+
+**/
+void
+GetOidFromTxt (
+  IN CONST CHAR8  *RequiredEKUs,
+  IN UINTN        RequiredEKUsSize,
+  IN OUT UINT8    *CheckOid,
+  OUT UINT8       *OidLen
+  )
+{
+  UINT8   *Ptr;
+  UINT16  Index;
+  UINT32  Data;
+  UINT8   OidIndex;
+  UINTN   EKUsSize;
+
+  EKUsSize = RequiredEKUsSize;
+  // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN
+  CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0'));
+
+  EKUsSize = EKUsSize - 4;
+  Ptr      = (UINT8 *)(RequiredEKUs + 4);
+
+  OidIndex = 1;
+
+  while (EKUsSize) {
+    Index = 0;
+    Data  = 0;
+
+    while ((*Ptr != '.') && (*Ptr != '\0')) {
+      Index++;
+      Ptr++;
+      EKUsSize--;
+    }
+
+    while (Index) {
+      Data = 10 * Data + (*(Ptr - Index) - '0');
+      Index--;
+    }
+
+    if (EKUsSize != 0) {
+      Ptr++;
+      EKUsSize--;
+    }
+
+    if (Data < 128) {
+      CheckOid[OidIndex] = (UINT8)Data;
+      OidIndex++;
+    } else {
+      CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF);
+      CheckOid[OidIndex]     = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF);
+      OidIndex               = OidIndex + 2;
+    }
+  }
+
+  *OidLen = OidIndex;
+}
+
+/**
+  Verify the Cert is signer cert
+
+  @param[in]  Start        Pointer to the DER-encoded certificate data Start.
+  @param[in]  End          Pointer to the DER-encoded certificate data End.
+
+  @retval  true            verify pass
+  @retval  false           verify fail
+**/
+STATIC
+BOOLEAN
+IsCertSignerCert (
+  UINT8  *Start,
+  UINT8  *End
+  )
+{
+  BOOLEAN           Status;
+  UINT8             *Buffer;
+  UINTN             Len;
+  mbedtls_x509_crt  Cert;
+  UINTN             ObjLen;
+
+  mbedtls_x509_crt_init (&Cert);
+
+  ObjLen = End - Start;
+
+  if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) {
+    return FALSE;
+  }
+
+  Len    = 0;
+  Buffer = NULL;
+  Status = GetExtensionData (
+             &Cert,
+             (CONST UINT8 *)gOidBasicConstraints,
+             sizeof (gOidBasicConstraints),
+             NULL,
+             &Len
+             );
+  if (Len == 0) {
+    /* basic constraints is not present in Cert */
+    return TRUE;
+  }
+
+  Buffer = AllocateZeroPool (Len);
+  if (Buffer == NULL) {
+    return FALSE;
+  }
+
+  Status = GetExtensionData (
+             &Cert,
+             (CONST UINT8 *)gOidBasicConstraints,
+             sizeof (gOidBasicConstraints),
+             Buffer,
+             &Len
+             );
+
+  if (Len == 0) {
+    /* basic constraints is not present in Cert */
+    Status = TRUE;
+    goto Exit;
+  } else if (!Status) {
+    Status = FALSE;
+    goto Exit;
+  }
+
+  if ((Len == sizeof (gBasicConstraintsCase1)) &&
+      (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1))))
+  {
+    Status = TRUE;
+    goto Exit;
+  }
+
+  if ((Len == sizeof (gBasicConstraintsCase2)) &&
+      (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2))))
+  {
+    Status = TRUE;
+    goto Exit;
+  }
+
+  Status = FALSE;
+
+Exit:
+  mbedtls_x509_crt_free (&Cert);
+
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+  }
+
+  return Status;
+}
+
+/**
+  Determines if the specified EKUs are present in a signing certificate.
+
+  @param[in]  SignerCert            The certificate to check.
+  @param[in]  RequiredEKUs          The EKUs to look for.
+  @param[in]  RequiredEKUsSize      The number of EKUs
+  @param[in]  RequireAllPresent     If TRUE, then all the specified EKUs
+                                    must be present in the certificate.
+
+  @retval EFI_SUCCESS               We successfully identified the signing type.
+  @retval EFI_INVALID_PARAMETER     A parameter was invalid.
+  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.
+**/
+STATIC
+EFI_STATUS
+CheckEKUs (
+  IN CONST mbedtls_x509_crt  *SignerCert,
+  IN CONST CHAR8             *RequiredEKUs[],
+  IN CONST UINT32            RequiredEKUsSize,
+  IN BOOLEAN                 RequireAllPresent
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      NumEkusFound;
+  UINT32      Index;
+  UINT8       *EKU;
+  UINTN       EkuLen;
+  UINT8       CheckOid[20];
+  UINT8       OidLen;
+
+  Status       = EFI_SUCCESS;
+  NumEkusFound = 0;
+
+  if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  for (Index = 0; Index < RequiredEKUsSize; Index++) {
+    //
+    // Finding required EKU in Cert.
+    //
+    GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen);
+
+    EKU    = CheckOid;
+    EkuLen = OidLen;
+
+    Status = IsEkuInCertificate (SignerCert, EKU, EkuLen);
+    if (Status == EFI_SUCCESS) {
+      NumEkusFound++;
+      if (!RequireAllPresent) {
+        //
+        // Found at least one, so we are done.
+        //
+        goto Exit;
+      }
+    } else {
+      //
+      // Fail to find Eku in Cert
+      break;
+    }
+  }
+
+Exit:
+  if (RequireAllPresent &&
+      (NumEkusFound == RequiredEKUsSize))
+  {
+    //
+    // Found all required EKUs in certificate.
+    //
+    Status = EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+/**
+  This function receives a PKCS#7 formatted signature blob,
+  looks for the EKU SEQUENCE blob, and if found then looks
+  for all the required EKUs. This function was created so that
+  the Surface team can cut down on the number of Certificate
+  Authorities (CA's) by checking EKU's on leaf signers for
+  a specific product. This prevents one product's certificate
+  from signing another product's firmware or unlock blobs.
+
+  Note that this function does not validate the certificate chain.
+  That needs to be done before using this function.
+
+  @param[in]  Pkcs7Signature       The PKCS#7 signed information content block. An array
+                                   containing the content block with both the signature,
+                                   the signer's certificate, and any necessary intermediate
+                                   certificates.
+  @param[in]  Pkcs7SignatureSize   Number of bytes in Pkcs7Signature.
+  @param[in]  RequiredEKUs         Array of null-terminated strings listing OIDs of
+                                   required EKUs that must be present in the signature.
+  @param[in]  RequiredEKUsSize     Number of elements in the RequiredEKUs string array.
+  @param[in]  RequireAllPresent    If this is TRUE, then all of the specified EKU's
+                                   must be present in the leaf signer.  If it is
+                                   FALSE, then we will succeed if we find any
+                                   of the specified EKU's.
+
+  @retval EFI_SUCCESS              The required EKUs were found in the signature.
+  @retval EFI_INVALID_PARAMETER    A parameter was invalid.
+  @retval EFI_NOT_FOUND            One or more EKU's were not found in the signature.
+
+**/
+EFI_STATUS
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+  IN CONST UINT8   *Pkcs7Signature,
+  IN CONST UINT32  SignatureSize,
+  IN CONST CHAR8   *RequiredEKUs[],
+  IN CONST UINT32  RequiredEKUsSize,
+  IN BOOLEAN       RequireAllPresent
+  )
+{
+  EFI_STATUS        Status;
+  mbedtls_x509_crt  Cert;
+  UINT8             *Ptr;
+  UINT8             *End;
+  INT32             Len;
+  UINTN             ObjLen;
+  UINT8             *OldEnd;
+
+  //
+  // Check input parameter.
+  //
+  if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) {
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  mbedtls_x509_crt_init (&Cert);
+
+  Ptr = (UINT8 *)(UINTN)Pkcs7Signature;
+  Len = (UINT32)SignatureSize;
+  End = Ptr + Len;
+
+  // Cert
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // tbscert
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // signature algo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // signature
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr   += ObjLen;
+  OldEnd = Ptr;
+  // Cert
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  End = Ptr + ObjLen;
+
+  // leaf Cert
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  while ((Ptr != End) && (Ptr < End)) {
+    if (IsCertSignerCert (OldEnd, Ptr)) {
+      break;
+    }
+
+    OldEnd = Ptr;
+    if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+      return FALSE;
+    }
+
+    Ptr += ObjLen;
+  }
+
+  if (Ptr != End) {
+    return FALSE;
+  } else {
+    Ptr = End - ObjLen;
+  }
+
+  // leaf Cert
+  ObjLen += Ptr - OldEnd;
+  Ptr     = OldEnd;
+
+  if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) {
+    return FALSE;
+  }
+
+  Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);
+  if (Status != EFI_SUCCESS) {
+    goto Exit;
+  }
+
+Exit:
+  //
+  // Release Resources
+  //
+  mbedtls_x509_crt_free (&Cert);
+
+  return Status;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117862): https://edk2.groups.io/g/devel/message/117862
Mute This Topic: https://groups.io/mt/105552835/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 6/9] CryptoPkg: Add Pkcs5 functions based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (4 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 7/9] CryptoPkg: Add more RSA related " Wenxing Hou
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

PBKDF2 Key Derivation Function Wrapper Implementation over MbedTLS.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c | 100 ++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
new file mode 100644
index 0000000000..94f1fcfa3b
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
@@ -0,0 +1,100 @@
+/** @file
+  PBKDF2 Key Derivation Function Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs5.h>
+
+/**
+  Derives a key from a password using a salt and iteration count, based on PKCS#5 v2.0
+  password based encryption key derivation function PBKDF2, as specified in RFC 2898.
+
+  If Password or Salt or OutKey is NULL, then return FALSE.
+  If the hash algorithm could not be determined, then return FALSE.
+
+  @param[in]  PasswordLength  Length of input password in bytes.
+  @param[in]  Password        Pointer to the array for the password.
+  @param[in]  SaltLength      Size of the Salt in bytes.
+  @param[in]  Salt            Pointer to the Salt.
+  @param[in]  IterationCount  Number of iterations to perform. Its value should be
+                              greater than or equal to 1.
+  @param[in]  DigestSize      Size of the message digest to be used (eg. SHA256_DIGEST_SIZE).
+                              NOTE: DigestSize will be used to determine the hash algorithm.
+                                    Only SHA1_DIGEST_SIZE or SHA256_DIGEST_SIZE is supported.
+  @param[in]  KeyLength       Size of the derived key buffer in bytes.
+  @param[out] OutKey          Pointer to the output derived key buffer.
+
+  @retval  TRUE   A key was derived successfully.
+  @retval  FALSE  One of the pointers was NULL or one of the sizes was too large.
+  @retval  FALSE  The hash algorithm could not be determined from the digest size.
+  @retval  FALSE  The key derivation operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs5HashPassword (
+  IN UINTN        PasswordLength,
+  IN CONST CHAR8  *Password,
+  IN UINTN        SaltLength,
+  IN CONST UINT8  *Salt,
+  IN UINTN        IterationCount,
+  IN UINTN        DigestSize,
+  IN UINTN        KeyLength,
+  OUT UINT8       *OutKey
+  )
+{
+  mbedtls_md_type_t  HashAlg;
+
+  //
+  // Parameter Checking.
+  //
+  if ((Password == NULL) || (Salt == NULL) || (OutKey == NULL)) {
+    return FALSE;
+  }
+
+  if ((PasswordLength == 0) || (PasswordLength > INT_MAX) ||
+      (SaltLength == 0) || (SaltLength > INT_MAX) ||
+      (KeyLength == 0) || (KeyLength > INT_MAX) ||
+      (IterationCount < 1) || (IterationCount > INT_MAX))
+  {
+    return FALSE;
+  }
+
+  //
+  // Make sure the digest algorithm is supported.
+  //
+  switch (DigestSize) {
+    case SHA1_DIGEST_SIZE:
+      HashAlg = MBEDTLS_MD_SHA1;
+      break;
+    case SHA256_DIGEST_SIZE:
+      HashAlg = MBEDTLS_MD_SHA256;
+      break;
+    default:
+      return FALSE;
+      break;
+  }
+
+  //
+  // Perform password-based key derivation routines.
+  //
+  if (mbedtls_pkcs5_pbkdf2_hmac_ext (
+        HashAlg,
+        (CONST UINT8 *)Password,
+        (int)PasswordLength,
+        (CONST UINT8 *)Salt,
+        (int)SaltLength,
+        (int)IterationCount,
+        (int)KeyLength,
+        (UINT8 *)OutKey
+        ) != 0)
+  {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117863): https://edk2.groups.io/g/devel/message/117863
Mute This Topic: https://groups.io/mt/105552837/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 7/9] CryptoPkg: Add more RSA related functions based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (5 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 6/9] CryptoPkg: Add Pkcs5 " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 8/9] CryptoPkg: Add AuthenticodeVerify " Wenxing Hou
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Implement more RSA functions such as RsaPkcs1Sign based Mbedlts.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c   | 278 ++++++++++++++
 .../BaseCryptLibMbedTls/Pk/CryptRsaExt.c      | 346 ++++++++++++++++++
 .../BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c  | 137 +++++++
 3 files changed, 761 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
new file mode 100644
index 0000000000..61ccdd78e6
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
@@ -0,0 +1,278 @@
+/** @file
+  This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/x509_crt.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+  Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+  encrypted message in a newly allocated buffer.
+
+  Things that can cause a failure include:
+  - X509 key size does not match any known key size.
+  - Fail to parse X509 certificate.
+  - Fail to allocate an intermediate buffer.
+  - Null pointer provided for a non-optional parameter.
+  - Data size is too large for the provided key size (max size is a function of key size
+    and hash digest size).
+
+  @param[in]  PublicKey           A pointer to the DER-encoded X509 certificate that
+                                  will be used to encrypt the data.
+  @param[in]  PublicKeySize       Size of the X509 cert buffer.
+  @param[in]  InData              Data to be encrypted.
+  @param[in]  InDataSize          Size of the data buffer.
+  @param[in]  PrngSeed            [Optional] If provided, a pointer to a random seed buffer
+                                  to be used when initializing the PRNG. NULL otherwise.
+  @param[in]  PrngSeedSize        [Optional] If provided, size of the random seed buffer.
+                                  0 otherwise.
+  @param[out] EncryptedData       Pointer to an allocated buffer containing the encrypted
+                                  message.
+  @param[out] EncryptedDataSize   Size of the encrypted message buffer.
+
+  @retval     TRUE                Encryption was successful.
+  @retval     FALSE               Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Encrypt (
+  IN CONST UINT8  *PublicKey,
+  IN UINTN        PublicKeySize,
+  IN UINT8        *InData,
+  IN UINTN        InDataSize,
+  IN CONST UINT8  *PrngSeed OPTIONAL,
+  IN UINTN        PrngSeedSize OPTIONAL,
+  OUT UINT8       **EncryptedData,
+  OUT UINTN       *EncryptedDataSize
+  )
+{
+  BOOLEAN              Result;
+  UINT32               Ret;
+  UINT8                *OutData;
+  mbedtls_x509_crt     CertContext;
+  mbedtls_rsa_context  RsaContext;
+
+  //
+  // Check input parameters.
+  //
+  if ((PublicKey == NULL) || (InData == NULL) ||
+      (EncryptedData == NULL) || (EncryptedDataSize == NULL))
+  {
+    return FALSE;
+  }
+
+  //
+  // Check public key size.
+  //
+  if (PublicKeySize > UINT_MAX) {
+    //
+    // Public key size is too large for implementation.
+    //
+    return FALSE;
+  }
+
+  *EncryptedData     = NULL;
+  *EncryptedDataSize = 0;
+  Result             = FALSE;
+  OutData            = NULL;
+
+  mbedtls_x509_crt_init (&CertContext);
+
+  if (mbedtls_x509_crt_parse_der (&CertContext, PublicKey, (UINT32)PublicKeySize) != 0) {
+    goto _Exit;
+  }
+
+  if (mbedtls_pk_get_type (&CertContext.pk) != MBEDTLS_PK_RSA) {
+    goto _Exit;
+  }
+
+  mbedtls_rsa_init (&RsaContext);
+  if (mbedtls_rsa_set_padding (&RsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE) != 0) {
+    goto _Exit;
+  }
+
+  Ret = mbedtls_rsa_copy (&RsaContext, mbedtls_pk_rsa (CertContext.pk));
+  if (Ret != 0) {
+    goto _Exit;
+  }
+
+  *EncryptedDataSize = RsaContext.len;
+
+  //
+  // Allocate a buffer for the output data.
+  //
+  OutData = AllocateZeroPool (*EncryptedDataSize);
+  if (OutData == NULL) {
+    //
+    // Fail to allocate the output buffer.
+    //
+    goto _Exit;
+  }
+
+  Ret = mbedtls_rsa_pkcs1_encrypt (
+          &RsaContext,
+          MbedtlsRand,
+          NULL,
+          InDataSize,
+          InData,
+          OutData
+          );
+  if (Ret != 0) {
+    FreePool (OutData);
+    OutData = NULL;
+    goto _Exit;
+  }
+
+  *EncryptedData = OutData;
+  Result         = TRUE;
+
+_Exit:
+  //
+  // Release Resources
+  //
+  if (&CertContext != NULL) {
+    mbedtls_x509_crt_free (&CertContext);
+  }
+
+  if (&RsaContext != NULL) {
+    mbedtls_rsa_free (&RsaContext);
+  }
+
+  return Result;
+}
+
+/**
+  Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+  encrypted message in a newly allocated buffer.
+
+  Things that can cause a failure include:
+  - X509 key size does not match any known key size.
+  - Fail to allocate an intermediate buffer.
+  - Null pointer provided for a non-optional parameter.
+  - Data size is too large for the provided key size (max size is a function of key size
+    and hash digest size).
+
+  @param[in]  RsaContext          A pointer to an RSA context created by RsaNew() and
+                                  provisioned with a public key using RsaSetKey().
+  @param[in]  InData              Data to be encrypted.
+  @param[in]  InDataSize          Size of the data buffer.
+  @param[in]  PrngSeed            [Optional] If provided, a pointer to a random seed buffer
+                                  to be used when initializing the PRNG. NULL otherwise.
+  @param[in]  PrngSeedSize        [Optional] If provided, size of the random seed buffer.
+                                  0 otherwise.
+  @param[in]  DigestLen           [Optional] If provided, size of the hash used:
+                                  SHA1_DIGEST_SIZE
+                                  SHA256_DIGEST_SIZE
+                                  SHA384_DIGEST_SIZE
+                                  SHA512_DIGEST_SIZE
+                                  0 to use default (SHA1)
+  @param[out] EncryptedData       Pointer to an allocated buffer containing the encrypted
+                                  message.
+  @param[out] EncryptedDataSize   Size of the encrypted message buffer.
+
+  @retval     TRUE                Encryption was successful.
+  @retval     FALSE               Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepEncrypt (
+  IN   VOID         *RsaContext,
+  IN   UINT8        *InData,
+  IN   UINTN        InDataSize,
+  IN   CONST UINT8  *PrngSeed   OPTIONAL,
+  IN   UINTN        PrngSeedSize   OPTIONAL,
+  IN   UINT16       DigestLen   OPTIONAL,
+  OUT  UINT8        **EncryptedData,
+  OUT  UINTN        *EncryptedDataSize
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+  decrypted message in a newly allocated buffer.
+
+  Things that can cause a failure include:
+  - Fail to parse private key.
+  - Fail to allocate an intermediate buffer.
+  - Null pointer provided for a non-optional parameter.
+
+  @param[in]  PrivateKey          A pointer to the DER-encoded private key.
+  @param[in]  PrivateKeySize      Size of the private key buffer.
+  @param[in]  EncryptedData       Data to be decrypted.
+  @param[in]  EncryptedDataSize   Size of the encrypted buffer.
+  @param[out] OutData             Pointer to an allocated buffer containing the encrypted
+                                  message.
+  @param[out] OutDataSize         Size of the encrypted message buffer.
+
+  @retval     TRUE                Encryption was successful.
+  @retval     FALSE               Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Decrypt (
+  IN   CONST UINT8  *PrivateKey,
+  IN   UINTN        PrivateKeySize,
+  IN   UINT8        *EncryptedData,
+  IN   UINTN        EncryptedDataSize,
+  OUT  UINT8        **OutData,
+  OUT  UINTN        *OutDataSize
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
+
+/**
+  Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+  decrypted message in a newly allocated buffer.
+
+  Things that can cause a failure include:
+  - Fail to parse private key.
+  - Fail to allocate an intermediate buffer.
+  - Null pointer provided for a non-optional parameter.
+
+  @param[in]  RsaContext          A pointer to an RSA context created by RsaNew() and
+                                  provisioned with a private key using RsaSetKey().
+  @param[in]  EncryptedData       Data to be decrypted.
+  @param[in]  EncryptedDataSize   Size of the encrypted buffer.
+  @param[in]  DigestLen           [Optional] If provided, size of the hash used:
+                                  SHA1_DIGEST_SIZE
+                                  SHA256_DIGEST_SIZE
+                                  SHA384_DIGEST_SIZE
+                                  SHA512_DIGEST_SIZE
+                                  0 to use default (SHA1)
+  @param[out] OutData             Pointer to an allocated buffer containing the encrypted
+                                  message.
+  @param[out] OutDataSize         Size of the encrypted message buffer.
+
+  @retval     TRUE                Encryption was successful.
+  @retval     FALSE               Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepDecrypt (
+  IN   VOID    *RsaContext,
+  IN   UINT8   *EncryptedData,
+  IN   UINTN   EncryptedDataSize,
+  IN   UINT16  DigestLen   OPTIONAL,
+  OUT  UINT8   **OutData,
+  OUT  UINTN   *OutDataSize
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
new file mode 100644
index 0000000000..9aade48b86
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
@@ -0,0 +1,346 @@
+/** @file
+  RSA Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+  This file implements following APIs which provide more capabilities for RSA:
+  1) RsaGetKey
+  2) RsaGenerateKey
+  3) RsaCheckKey
+  4) RsaPkcs1Sign
+
+  RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+
+/**
+  Gets the tag-designated RSA key component from the established RSA context.
+
+  This function retrieves the tag-designated RSA key component from the
+  established RSA context as a non-negative integer (octet string format
+  represented in RSA PKCS#1).
+  If specified key component has not been set or has been cleared, then returned
+  BnSize is set to 0.
+  If the BigNumber buffer is too small to hold the contents of the key, FALSE
+  is returned and BnSize is set to the required buffer size to obtain the key.
+
+  If RsaContext is NULL, then return FALSE.
+  If BnSize is NULL, then return FALSE.
+  If BnSize is large enough but BigNumber is NULL, then return FALSE.
+
+  @param[in, out]  RsaContext  Pointer to RSA context being set.
+  @param[in]       KeyTag      Tag of RSA key component being set.
+  @param[out]      BigNumber   Pointer to octet integer buffer.
+  @param[in, out]  BnSize      On input, the size of big number buffer in bytes.
+                               On output, the size of data returned in big number buffer in bytes.
+
+  @retval  TRUE   RSA key component was retrieved successfully.
+  @retval  FALSE  Invalid RSA key component tag.
+  @retval  FALSE  BnSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetKey (
+  IN OUT VOID     *RsaContext,
+  IN RSA_KEY_TAG  KeyTag,
+  OUT UINT8       *BigNumber,
+  IN OUT UINTN    *BnSize
+  )
+{
+  mbedtls_rsa_context  *RsaKey;
+  INT32                Ret;
+  mbedtls_mpi          Value;
+  UINTN                Size;
+
+  //
+  // Check input parameters.
+  //
+  if ((RsaContext == NULL) || (*BnSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  //
+  // Init mbedtls_mpi
+  //
+  mbedtls_mpi_init (&Value);
+  Size    = *BnSize;
+  *BnSize = 0;
+
+  RsaKey = (mbedtls_rsa_context *)RsaContext;
+
+  switch (KeyTag) {
+    case RsaKeyN:
+      Ret = mbedtls_rsa_export (RsaKey, &Value, NULL, NULL, NULL, NULL);
+      break;
+    case RsaKeyE:
+      Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, NULL, &Value);
+      break;
+    case RsaKeyD:
+      Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, &Value, NULL);
+      break;
+    case RsaKeyQ:
+      Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, &Value, NULL, NULL);
+      break;
+    case RsaKeyP:
+      Ret = mbedtls_rsa_export (RsaKey, NULL, &Value, NULL, NULL, NULL);
+      break;
+    case RsaKeyDp:
+    case RsaKeyDq:
+    case RsaKeyQInv:
+    default:
+      Ret = -1;
+      break;
+  }
+
+  if (Ret != 0) {
+    goto End;
+  }
+
+  if (mbedtls_mpi_size (&Value) == 0) {
+    Ret = 0;
+    goto End;
+  }
+
+  *BnSize = Size;
+
+  Size = mbedtls_mpi_size (&Value);
+  if (*BnSize < Size) {
+    Ret     = 1;
+    *BnSize = Size;
+    goto End;
+  }
+
+  if (BigNumber == NULL) {
+    Ret     = 0;
+    *BnSize = Size;
+    goto End;
+  }
+
+  if ((BigNumber != NULL) && (Ret == 0)) {
+    Ret     = mbedtls_mpi_write_binary (&Value, BigNumber, Size);
+    *BnSize = Size;
+  }
+
+End:
+  mbedtls_mpi_free (&Value);
+  return Ret == 0;
+}
+
+/**
+  Generates RSA key components.
+
+  This function generates RSA key components. It takes RSA public exponent E and
+  length in bits of RSA modulus N as input, and generates all key components.
+  If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
+
+  Before this function can be invoked, pseudorandom number generator must be correctly
+  initialized by RandomSeed().
+
+  If RsaContext is NULL, then return FALSE.
+
+  @param[in, out]  RsaContext           Pointer to RSA context being set.
+  @param[in]       ModulusLength        Length of RSA modulus N in bits.
+  @param[in]       PublicExponent       Pointer to RSA public exponent.
+  @param[in]       PublicExponentSize   Size of RSA public exponent buffer in bytes.
+
+  @retval  TRUE   RSA key component was generated successfully.
+  @retval  FALSE  Invalid RSA key component tag.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGenerateKey (
+  IN OUT VOID     *RsaContext,
+  IN UINTN        ModulusLength,
+  IN CONST UINT8  *PublicExponent,
+  IN UINTN        PublicExponentSize
+  )
+{
+  INT32                Ret;
+  mbedtls_rsa_context  *Rsa;
+  INT32                E;
+
+  //
+  // Check input parameters.
+  //
+  if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  Rsa = (mbedtls_rsa_context *)RsaContext;
+
+  if (PublicExponent == NULL) {
+    E = 0x10001;
+  } else {
+    if (PublicExponentSize == 0) {
+      return FALSE;
+    }
+
+    switch (PublicExponentSize) {
+      case 1:
+        E = PublicExponent[0];
+        break;
+      case 2:
+        E = PublicExponent[0] << 8 | PublicExponent[1];
+        break;
+      case 3:
+        E = PublicExponent[0] << 16 | PublicExponent[1] << 8 |
+            PublicExponent[2];
+        break;
+      case 4:
+        E = PublicExponent[0] << 24 | PublicExponent[1] << 16 |
+            PublicExponent[2] << 8 | PublicExponent[3];
+        break;
+      default:
+        return FALSE;
+    }
+  }
+
+  Ret = mbedtls_rsa_gen_key (
+          Rsa,
+          MbedtlsRand,
+          NULL,
+          (UINT32)ModulusLength,
+          E
+          );
+
+  return Ret == 0;
+}
+
+/**
+  Validates key components of RSA context.
+  NOTE: This function performs integrity checks on all the RSA key material, so
+        the RSA key structure must contain all the private key data.
+
+  This function validates key components of RSA context in following aspects:
+  - Whether p is a prime
+  - Whether q is a prime
+  - Whether n = p * q
+  - Whether d*e = 1  mod lcm(p-1,q-1)
+
+  If RsaContext is NULL, then return FALSE.
+
+  @param[in]  RsaContext  Pointer to RSA context to check.
+
+  @retval  TRUE   RSA key components are valid.
+  @retval  FALSE  RSA key components are not valid.
+
+**/
+BOOLEAN
+EFIAPI
+RsaCheckKey (
+  IN VOID  *RsaContext
+  )
+{
+  if (RsaContext == NULL) {
+    return FALSE;
+  }
+
+  UINT32  Ret;
+
+  Ret = mbedtls_rsa_complete (RsaContext);
+  if (Ret == 0) {
+    Ret = mbedtls_rsa_check_privkey (RsaContext);
+  }
+
+  return Ret == 0;
+}
+
+/**
+  Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
+
+  This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
+  RSA PKCS#1.
+  If the Signature buffer is too small to hold the contents of signature, FALSE
+  is returned and SigSize is set to the required buffer size to obtain the signature.
+
+  If RsaContext is NULL, then return FALSE.
+  If MessageHash is NULL, then return FALSE.
+  If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digest, then return FALSE.
+  If SigSize is large enough but Signature is NULL, then return FALSE.
+
+  @param[in]       RsaContext   Pointer to RSA context for signature generation.
+  @param[in]       MessageHash  Pointer to octet message hash to be signed.
+  @param[in]       HashSize     Size of the message hash in bytes.
+  @param[out]      Signature    Pointer to buffer to receive RSA PKCS1-v1_5 signature.
+  @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.
+                                On output, the size of data returned in Signature buffer in bytes.
+
+  @retval  TRUE   Signature successfully generated in PKCS1-v1_5.
+  @retval  FALSE  Signature generation failed.
+  @retval  FALSE  SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPkcs1Sign (
+  IN VOID         *RsaContext,
+  IN CONST UINT8  *MessageHash,
+  IN UINTN        HashSize,
+  OUT UINT8       *Signature,
+  IN OUT UINTN    *SigSize
+  )
+{
+  INT32              Ret;
+  mbedtls_md_type_t  md_alg;
+
+  if ((RsaContext == NULL) || (MessageHash == NULL)) {
+    return FALSE;
+  }
+
+  if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+    return FALSE;
+  }
+
+  switch (HashSize) {
+    case MD5_DIGEST_SIZE:
+      break;
+
+    case SHA1_DIGEST_SIZE:
+      md_alg = MBEDTLS_MD_SHA1;
+      break;
+
+    case SHA256_DIGEST_SIZE:
+      md_alg = MBEDTLS_MD_SHA256;
+      break;
+
+    case SHA384_DIGEST_SIZE:
+      md_alg = MBEDTLS_MD_SHA384;
+      break;
+
+    case SHA512_DIGEST_SIZE:
+      md_alg = MBEDTLS_MD_SHA512;
+      break;
+
+    default:
+      return FALSE;
+  }
+
+  if (mbedtls_rsa_get_len (RsaContext) > *SigSize) {
+    *SigSize = mbedtls_rsa_get_len (RsaContext);
+    return FALSE;
+  }
+
+  mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, md_alg);
+
+  Ret = mbedtls_rsa_pkcs1_sign (
+          RsaContext,
+          MbedtlsRand,
+          NULL,
+          md_alg,
+          (UINT32)HashSize,
+          MessageHash,
+          Signature
+          );
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  *SigSize = mbedtls_rsa_get_len (RsaContext);
+  return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
new file mode 100644
index 0000000000..0e2203cdb9
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
@@ -0,0 +1,137 @@
+/** @file
+  RSA PSS Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+  This file implements following APIs which provide basic capabilities for RSA:
+  1) RsaPssSign
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/sha512.h>
+
+/**
+  Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+  This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+  RFC 8017.
+  Mask generation function is the same as the message digest algorithm.
+  If the Signature buffer is too small to hold the contents of signature, FALSE
+  is returned and SigSize is set to the required buffer size to obtain the signature.
+
+  If RsaContext is NULL, then return FALSE.
+  If Message is NULL, then return FALSE.
+  If MsgSize is zero or > INT_MAX, then return FALSE.
+  If DigestLen is NOT 32, 48 or 64, return FALSE.
+  If SaltLen is not equal to DigestLen, then return FALSE.
+  If SigSize is large enough but Signature is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in]      RsaContext   Pointer to RSA context for signature generation.
+  @param[in]      Message      Pointer to octet message to be signed.
+  @param[in]      MsgSize      Size of the message in bytes.
+  @param[in]      DigestLen    Length of the digest in bytes to be used for RSA signature operation.
+  @param[in]      SaltLen      Length of the salt in bytes to be used for PSS encoding.
+  @param[out]     Signature    Pointer to buffer to receive RSA PSS signature.
+  @param[in, out] SigSize      On input, the size of Signature buffer in bytes.
+                               On output, the size of data returned in Signature buffer in bytes.
+
+  @retval  TRUE   Signature successfully generated in RSASSA-PSS.
+  @retval  FALSE  Signature generation failed.
+  @retval  FALSE  SigSize is too small.
+  @retval  FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+  IN VOID         *RsaContext,
+  IN CONST UINT8  *Message,
+  IN UINTN        MsgSize,
+  IN UINT16       DigestLen,
+  IN UINT16       SaltLen,
+  OUT UINT8       *Signature,
+  IN OUT UINTN    *SigSize
+  )
+{
+  INT32              Ret;
+  mbedtls_md_type_t  MdAlg;
+  UINT8              HashValue[SHA512_DIGEST_SIZE];
+
+  if (RsaContext == NULL) {
+    return FALSE;
+  }
+
+  if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+    return FALSE;
+  }
+
+  if ((Message == NULL) || (MsgSize == 0) || (MsgSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  if (SaltLen != DigestLen) {
+    return FALSE;
+  }
+
+  ZeroMem (HashValue, DigestLen);
+
+  switch (DigestLen) {
+    case SHA256_DIGEST_SIZE:
+      MdAlg = MBEDTLS_MD_SHA256;
+      if (mbedtls_sha256 (Message, MsgSize, HashValue, FALSE) != 0) {
+        return FALSE;
+      }
+
+      break;
+
+    case SHA384_DIGEST_SIZE:
+      MdAlg = MBEDTLS_MD_SHA384;
+      if (mbedtls_sha512 (Message, MsgSize, HashValue, TRUE) != 0) {
+        return FALSE;
+      }
+
+      break;
+
+    case SHA512_DIGEST_SIZE:
+      MdAlg = MBEDTLS_MD_SHA512;
+      if (mbedtls_sha512 (Message, MsgSize, HashValue, FALSE) != 0) {
+        return FALSE;
+      }
+
+      break;
+
+    default:
+      return FALSE;
+  }
+
+  if (Signature == NULL) {
+    //
+    // If Signature is NULL, return safe SignatureSize
+    //
+    *SigSize = MBEDTLS_MPI_MAX_SIZE;
+    return FALSE;
+  }
+
+  mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V21, MdAlg);
+
+  Ret = mbedtls_rsa_rsassa_pss_sign (
+          RsaContext,
+          MbedtlsRand,
+          NULL,
+          MdAlg,
+          (UINT32)DigestLen,
+          HashValue,
+          Signature
+          );
+  if (Ret != 0) {
+    return FALSE;
+  }
+
+  *SigSize = ((mbedtls_rsa_context *)RsaContext)->len;
+  return TRUE;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117864): https://edk2.groups.io/g/devel/message/117864
Mute This Topic: https://groups.io/mt/105552838/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 8/9] CryptoPkg: Add AuthenticodeVerify based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (6 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 7/9] CryptoPkg: Add more RSA related " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-16  7:51 ` [edk2-devel] [PATCH 9/9] CryptoPkg: Add ImageTimestampVerify " Wenxing Hou
  2024-04-22  7:53 ` [edk2-devel] [PATCH 0/9] Add more crypt APIs " Li, Yi
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Implement AuthenticodeVerify based on Mbedtls.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../Pk/CryptAuthenticode.c                    | 214 ++++++++++++++++++
 1 file changed, 214 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
new file mode 100644
index 0000000000..9d8301b2c0
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
@@ -0,0 +1,214 @@
+/** @file
+  Authenticode Portable Executable Signature Verification which does not provide
+  real capabilities.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+
+//
+// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8  mSpcIndirectOidValue[] = {
+  0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04
+};
+
+/**
+  Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows
+  Authenticode Portable Executable Signature Format".
+
+  Return FALSE to indicate this interface is not supported.
+
+  @param[in]  AuthData     Pointer to the Authenticode Signature retrieved from signed
+                           PE/COFF image to be verified.
+  @param[in]  DataSize     Size of the Authenticode Signature in bytes.
+  @param[in]  TrustedCert  Pointer to a trusted/root certificate encoded in DER, which
+                           is used for certificate chain verification.
+  @param[in]  CertSize     Size of the trusted certificate in bytes.
+  @param[in]  ImageHash    Pointer to the original image file hash value. The procedure
+                           for calculating the image hash value is described in Authenticode
+                           specification.
+  @param[in]  HashSize     Size of Image hash value in bytes.
+
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+AuthenticodeVerify (
+  IN CONST UINT8  *AuthData,
+  IN UINTN        DataSize,
+  IN CONST UINT8  *TrustedCert,
+  IN UINTN        CertSize,
+  IN CONST UINT8  *ImageHash,
+  IN UINTN        HashSize
+  )
+{
+  BOOLEAN      Status;
+  CONST UINT8  *OrigAuthData;
+  UINT8        *SpcIndirectDataContent;
+  UINT8        Asn1Byte;
+  UINTN        ContentSize;
+  CONST UINT8  *SpcIndirectDataOid;
+  UINT8        *Ptr;
+  UINT8        *End;
+  INT32        Len;
+  UINTN        ObjLen;
+
+  OrigAuthData = AuthData;
+
+  //
+  // Check input parameters.
+  //
+  if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) {
+    return FALSE;
+  }
+
+  if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  if (DataSize <= HashSize) {
+    return FALSE;
+  }
+
+  Ptr = (UINT8 *)(UINTN)AuthData;
+  Len = (UINT32)DataSize;
+  End = Ptr + Len;
+
+  // ContentInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // ContentType
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // content
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  End = Ptr + ObjLen;
+  // signedData
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // version
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // digestAlgo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // encapContentInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  End = Ptr + ObjLen;
+  // eContentType
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Status = FALSE;
+
+  SpcIndirectDataOid = Ptr;
+  if ((ObjLen != sizeof (mSpcIndirectOidValue)) ||
+      (CompareMem (
+         SpcIndirectDataOid,
+         mSpcIndirectOidValue,
+         sizeof (mSpcIndirectOidValue)
+         ) != 0))
+  {
+    //
+    // Un-matched SPC_INDIRECT_DATA_OBJID.
+    //
+    goto _Exit;
+  }
+
+  Ptr += ObjLen;
+  // eContent
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  SpcIndirectDataContent = Ptr;
+
+  //
+  // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.
+  //
+  Asn1Byte = *(SpcIndirectDataContent + 1);
+
+  if ((Asn1Byte & 0x80) == 0) {
+    //
+    // Short Form of Length Encoding (Length < 128)
+    //
+    ContentSize = (UINTN)(Asn1Byte & 0x7F);
+    //
+    // Skip the SEQUENCE Tag;
+    //
+    SpcIndirectDataContent += 2;
+  } else if ((Asn1Byte & 0x81) == 0x81) {
+    //
+    // Long Form of Length Encoding (128 <= Length < 255, Single Octet)
+    //
+    ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
+    //
+    // Skip the SEQUENCE Tag;
+    //
+    SpcIndirectDataContent += 3;
+  } else if ((Asn1Byte & 0x82) == 0x82) {
+    //
+    // Long Form of Length Encoding (Length > 255, Two Octet)
+    //
+    ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
+    ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3));
+    //
+    // Skip the SEQUENCE Tag;
+    //
+    SpcIndirectDataContent += 4;
+  } else {
+    goto _Exit;
+  }
+
+  //
+  // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent
+  // defined in Authenticode
+  // NOTE: Need to double-check HashLength here!
+  //
+  if (ContentSize < HashSize) {
+    return FALSE;
+  }
+
+  if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) {
+    //
+    // Un-matched PE/COFF Hash Value
+    //
+    goto _Exit;
+  }
+
+  //
+  // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature
+  //
+  Status = (BOOLEAN)Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);
+
+_Exit:
+
+  return Status;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117865): https://edk2.groups.io/g/devel/message/117865
Mute This Topic: https://groups.io/mt/105552839/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH 9/9] CryptoPkg: Add ImageTimestampVerify based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (7 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 8/9] CryptoPkg: Add AuthenticodeVerify " Wenxing Hou
@ 2024-04-16  7:51 ` Wenxing Hou
  2024-04-22  7:53 ` [edk2-devel] [PATCH 0/9] Add more crypt APIs " Li, Yi
  9 siblings, 0 replies; 12+ messages in thread
From: Wenxing Hou @ 2024-04-16  7:51 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Yi Li

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

Timestamp Countersignature Verification implementaion based on Mbedtls.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../Library/BaseCryptLibMbedTls/Pk/CryptTs.c  | 381 ++++++++++++++++++
 1 file changed, 381 insertions(+)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
new file mode 100644
index 0000000000..d3fa205f9c
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
@@ -0,0 +1,381 @@
+/** @file
+  RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does
+  not provide real capabilities.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/asn1.h>
+
+//
+// OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1")
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8  mSpcRFC3161OidValue[] = {
+  0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01
+};
+
+/**
+  Convert ASN.1 GeneralizedTime to EFI Time.
+
+  @param[in]  Ptr          Pointer to the ASN.1 GeneralizedTime to be converted.
+  @param[out] EfiTime      Return the corresponding EFI Time.
+
+  @retval  TRUE   The time conversion succeeds.
+  @retval  FALSE  Invalid parameters.
+
+**/
+STATIC
+BOOLEAN
+ConvertAsn1TimeToEfiTime (
+  IN  UINT8     *Ptr,
+  OUT EFI_TIME  *EfiTime
+  )
+{
+  CONST CHAR8  *Str;
+  UINTN        Index;
+
+  if ((Ptr == NULL) || (EfiTime == NULL)) {
+    return FALSE;
+  }
+
+  Str = (CONST CHAR8 *)Ptr;
+  SetMem (EfiTime, sizeof (EFI_TIME), 0);
+
+  Index = 0;
+
+  /* four digit year */
+  EfiTime->Year  = (Str[Index++] - '0') * 1000;
+  EfiTime->Year += (Str[Index++] - '0') * 100;
+  EfiTime->Year += (Str[Index++] - '0') * 10;
+  EfiTime->Year += (Str[Index++] - '0');
+  if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) {
+    return FALSE;
+  }
+
+  EfiTime->Month  = (Str[Index++] - '0') * 10;
+  EfiTime->Month += (Str[Index++] - '0');
+  if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) {
+    return FALSE;
+  }
+
+  EfiTime->Day  = (Str[Index++] - '0') * 10;
+  EfiTime->Day += (Str[Index++] - '0');
+  if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) {
+    return FALSE;
+  }
+
+  EfiTime->Hour  = (Str[Index++] - '0') * 10;
+  EfiTime->Hour += (Str[Index++] - '0');
+  if (EfiTime->Hour > 23) {
+    return FALSE;
+  }
+
+  EfiTime->Minute  = (Str[Index++] - '0') * 10;
+  EfiTime->Minute += (Str[Index++] - '0');
+  if (EfiTime->Minute > 59) {
+    return FALSE;
+  }
+
+  EfiTime->Second  = (Str[Index++] - '0') * 10;
+  EfiTime->Second += (Str[Index++] - '0');
+  if (EfiTime->Second > 59) {
+    return FALSE;
+  }
+
+  /* Note: we did not adjust the time based on time zone information */
+
+  return TRUE;
+}
+
+/**
+  Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode
+  signature.
+
+  Return FALSE to indicate this interface is not supported.
+
+  @param[in]  AuthData     Pointer to the Authenticode Signature retrieved from signed
+                           PE/COFF image to be verified.
+  @param[in]  DataSize     Size of the Authenticode Signature in bytes.
+  @param[in]  TsaCert      Pointer to a trusted/root TSA certificate encoded in DER, which
+                           is used for TSA certificate chain verification.
+  @param[in]  CertSize     Size of the trusted certificate in bytes.
+  @param[out] SigningTime  Return the time of timestamp generation time if the timestamp
+                           signature is valid.
+
+  @retval  FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ImageTimestampVerify (
+  IN  CONST UINT8  *AuthData,
+  IN  UINTN        DataSize,
+  IN  CONST UINT8  *TsaCert,
+  IN  UINTN        CertSize,
+  OUT EFI_TIME     *SigningTime
+  )
+{
+  BOOLEAN  Status;
+  UINT8    *Ptr;
+  UINT8    *End;
+  INT32    Len;
+  UINTN    ObjLen;
+  UINT8    *TempPtr;
+
+  //
+  // Initializations
+  //
+  if (SigningTime != NULL) {
+    SetMem (SigningTime, sizeof (EFI_TIME), 0);
+  }
+
+  //
+  // Input Parameters Checking.
+  //
+  if ((AuthData == NULL) || (TsaCert == NULL)) {
+    return FALSE;
+  }
+
+  if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) {
+    return FALSE;
+  }
+
+  Ptr = (UINT8 *)(UINTN)AuthData;
+  Len = (UINT32)DataSize;
+  End = Ptr + Len;
+
+  // ContentInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // ContentType
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // content
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  End = Ptr + ObjLen;
+  // signedData
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // version
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // digestAlgo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // encapContentInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // cert
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  TempPtr = Ptr;
+  // OPTIONAL CRLs
+  if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+    Ptr = TempPtr + ObjLen;
+  }
+
+  // signerInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  // sub parse
+  // signerInfo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  End = Ptr + ObjLen;
+
+  // version
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // sid
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // digestalgo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // OPTIONAL AuthenticatedAttributes
+  TempPtr = Ptr;
+  if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+    Ptr = TempPtr + ObjLen;
+  }
+
+  // signaturealgo
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // signature
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // OPTIONAL UnauthenticatedAttributes
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, 0xA1) != 0) {
+    return FALSE;
+  }
+
+  // Attribute
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // type
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  if (CompareMem (Ptr, mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // values
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  // values
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // signedData OID
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // [0]
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // integer
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // SET
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // tST OID
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+    return FALSE;
+  }
+
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) {
+    return FALSE;
+  }
+
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  // Integer
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // policy OID
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // sequence
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+  // Integer
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+    return FALSE;
+  }
+
+  Ptr += ObjLen;
+
+  // GeneralizedTime
+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_GENERALIZED_TIME) != 0) {
+    return FALSE;
+  }
+
+  //
+  // Retrieve the signing time from TS_TST_INFO structure.
+  //
+  if (SigningTime != NULL) {
+    SetMem (SigningTime, sizeof (EFI_TIME), 0);
+    Status = ConvertAsn1TimeToEfiTime (Ptr, SigningTime);
+  }
+
+  return Status;
+}
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117866): https://edk2.groups.io/g/devel/message/117866
Mute This Topic: https://groups.io/mt/105552840/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* Re: [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related functions based on Mbedtls
  2024-04-16  7:51 ` [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related " Wenxing Hou
@ 2024-04-22  7:52   ` Li, Yi
  0 siblings, 0 replies; 12+ messages in thread
From: Li, Yi @ 2024-04-22  7:52 UTC (permalink / raw)
  To: Hou, Wenxing, devel@edk2.groups.io; +Cc: Yao, Jiewen

The pools used to store cert chain are not released properly, which will lead to memory leak problems
Please ensure MbedtlsPkcs7SignedData.Certificates are handled correctly when:
  1. error occurred in Pkcs7GetSigner/SignedData
  2. Pkcs7Verify finished.

Regards,
Yi

-----Original Message-----
From: Hou, Wenxing <wenxing.hou@intel.com> 
Sent: Tuesday, April 16, 2024 3:51 PM
To: devel@edk2.groups.io
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>
Subject: [PATCH 5/9] CryptoPkg: Add Pkcs7 related functions based on Mbedtls

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

Because the current Mbedlts pkcs7 library doesn't support
authenticatedAttributes:
Mbed-TLS/mbedtls@bb82ab7
and only support 0 or 1 certificates in Signed data:
tianocore/edk2-staging@9c5b26b

The patch implement Pkcs7 by low Mbedtls Api.
And the implementation has pass unit_tes and integration test.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
---
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |   33 +
 .../Pk/CryptPkcs7Internal.h                   |   20 +-
 .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c   |  615 ++++++++
 .../Pk/CryptPkcs7VerifyBase.c                 |  113 ++
 .../Pk/CryptPkcs7VerifyCommon.c               | 1315 +++++++++++++++++
 .../Pk/CryptPkcs7VerifyEku.c                  |  689 +++++++++
 6 files changed, 2773 insertions(+), 12 deletions(-)
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
index e2c7e42ecb..1b9742c166 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
@@ -38,4 +38,37 @@ MbedtlsRand (
   UINT8  *output,

   UINTN  len

   );

+

+/**

+  Check input P7Data is a wrapped ContentInfo structure or not. If not construct

+  a new structure to wrap P7Data.

+

+  Caution: This function may receive untrusted input.

+  UEFI Authenticated Variable is external input, so this function will do basic

+  check for PKCS#7 data structure.

+

+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.

+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.

+  @param[out] WrapFlag     If TRUE P7Data is a ContentInfo structure, otherwise

+                           return FALSE.

+  @param[out] WrapData     If return status of this function is TRUE:

+                           1) when WrapFlag is TRUE, pointer to P7Data.

+                           2) when WrapFlag is FALSE, pointer to a new ContentInfo

+                           structure. It's caller's responsibility to free this

+                           buffer.

+  @param[out] WrapDataSize Length of ContentInfo structure in bytes.

+

+  @retval     TRUE         The operation is finished successfully.

+  @retval     FALSE        The operation is failed due to lack of resources.

+

+**/

+BOOLEAN

+WrapPkcs7Data (

+  IN  CONST UINT8  *P7Data,

+  IN  UINTN        P7Length,

+  OUT BOOLEAN      *WrapFlag,

+  OUT UINT8        **WrapData,

+  OUT UINTN        *WrapDataSize

+  );

+

 #endif

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
index 207f493cbb..d4bdb0abf7 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
@@ -4,7 +4,7 @@
 

   RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5

 

-Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>

+Copyright (c) 2023-2024, Intel Corporation. All rights reserved.<BR>

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

 

 **/

@@ -31,10 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define MBEDTLS_OID_PKCS7_DIGESTED_DATA              MBEDTLS_OID_PKCS7 "\x05"

 #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA             MBEDTLS_OID_PKCS7 "\x06"

 

-typedef mbedtls_asn1_buf         MBEDTLSPKCS7BUF;

-typedef mbedtls_asn1_named_data  MBEDTLSPKCS7NAME;

-typedef mbedtls_asn1_sequence    MBEDTLSPKCS7SEQUENCE;

-

 ///

 /// PKCS7 SignerInfo type

 /// https://tools.ietf.org/html/rfc2315#section-9.2

@@ -48,8 +44,8 @@ typedef struct MbedtlsPkcs7SignerInfo {
   mbedtls_x509_buf                 SigAlgIdentifier;

   mbedtls_x509_buf                 AuthAttr;

   mbedtls_x509_buf                 Sig;

-  struct MBEDTLSPKCS7SIGNERINFO    *Next;

-} MBEDTLSPKCS7SIGNERINFO;

+  struct MbedtlsPkcs7SignerInfo    *Next;

+} MbedtlsPkcs7SignerInfo;

 

 ///

 /// PKCS7 signed data attached data format

@@ -57,7 +53,7 @@ typedef struct MbedtlsPkcs7SignerInfo {
 typedef struct MbedtlsPkcs7Data {

   mbedtls_asn1_buf    Oid;

   mbedtls_asn1_buf    Data;

-} MBEDTLSPKCS7DATA;

+} MbedtlsPkcs7Data;

 

 ///

 /// Signed Data

@@ -66,18 +62,18 @@ typedef struct MbedtlsPkcs7Data {
 typedef struct MbedtlsPkcs7SignedData {

   INT32                            Version;

   mbedtls_asn1_buf                 DigestAlgorithms;

-  struct MBEDTLSPKCS7DATA          ContentInfo;

+  struct MbedtlsPkcs7Data          ContentInfo;

   mbedtls_x509_crt                 Certificates;

   mbedtls_x509_crl                 Crls;

   struct MbedtlsPkcs7SignerInfo    SignerInfos;

-} MBEDTLSPKCS7SIGNEDDATA;

+} MbedtlsPkcs7SignedData;

 

 ///

 /// PKCS7 struct, only support SignedData

 ///

 typedef struct MbedtlsPkcs7 {

   mbedtls_asn1_buf                 ContentTypeOid;

-  struct MBEDTLSPKCS7SIGNEDDATA    SignedData;

-} MBEDTLSPKCS7;

+  struct MbedtlsPkcs7SignedData    SignedData;

+} MbedtlsPkcs7;

 

 #endif

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
new file mode 100644
index 0000000000..e4d2d7a2a8
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
@@ -0,0 +1,615 @@
+/** @file

+  PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper

+  Implementation over mbedtls.

+

+  RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites

+  FIPS 186-4 - Digital Signature Standard (DSS)

+

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

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

+

+**/

+

+#include "CryptPkcs7Internal.h"

+#include <mbedtls/ecdh.h>

+

+///

+/// Enough to store any signature generated by PKCS7

+///

+#define MAX_SIGNATURE_SIZE  1024

+

+GLOBAL_REMOVE_IF_UNREFERENCED UINT8  MbedtlsOidDigestAlgSha256[] = MBEDTLS_OID_DIGEST_ALG_SHA256;

+GLOBAL_REMOVE_IF_UNREFERENCED UINT8  MbedtlsOidPkcs1Rsa[]        = MBEDTLS_OID_PKCS1_RSA;

+

+/**

+  Write DigestAlgorithmIdentifier.

+

+  @param[in, out]  P           The reference to the current position pointer.

+  @param[in]       Start       The start of the buffer, for bounds-checking.

+  @param[in]       DigestType  Digest Type

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteDigestAlgorithm (

+  UINT8              **P,

+  UINT8              *Start,

+  mbedtls_md_type_t  DigestType

+  )

+{

+  UINT8  *OidPtr;

+  UINTN  OidLen;

+  INT32  Ret;

+

+  Ret = mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, &OidLen);

+  if (Ret == 0) {

+    return mbedtls_asn1_write_oid (P, (CONST UINT8 *)Start, (CONST CHAR8 *)OidPtr, OidLen);

+  }

+

+  return 0;

+}

+

+/**

+  DigestAlgorithmIdentifiers ::=

+  SET OF DigestAlgorithmIdentifier.

+

+  @param[in, out]  P           The reference to the current position pointer.

+  @param[in]       Start       The start of the buffer, for bounds-checking.

+  @param[in]       DigestTypes Digest Type array.

+  @param[in]       Count       The index for Digest Type.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteDigestAlgorithmSet (

+  UINT8              **P,

+  UINT8              *Start,

+  mbedtls_md_type_t  *DigestTypes,

+  INTN               Count

+  )

+{

+  INTN   Idx;

+  INT32  Len;

+  INT32  ret;

+

+  Len = 0;

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (P, Start));

+

+  for (Idx = 0; Idx < Count; Idx++) {

+    MBEDTLS_ASN1_CHK_ADD (

+      Len,

+      MbedTlsPkcs7WriteDigestAlgorithm (P, Start, DigestTypes[Idx])

+      );

+  }

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, (UINTN)Len));

+

+  MBEDTLS_ASN1_CHK_ADD (

+    Len,

+    mbedtls_asn1_write_tag (

+      P,

+      Start,

+      (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)

+      )

+    );

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, (UINTN)Len));

+

+  MBEDTLS_ASN1_CHK_ADD (

+    Len,

+    mbedtls_asn1_write_tag (

+      P,

+      Start,

+      (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)

+      )

+    );

+

+  return Len;

+}

+

+/**

+   ContentInfo ::= SEQUENCE {

+        contentType ContentType,

+        content

+                [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.

+

+  @param[in, out]  P           The reference to the current position pointer.

+  @param[in]       Start       The start of the buffer, for bounds-checking.

+  @param[in]       Content     ContentInfo.

+  @param[in]       ContentLen  Size of ContentInfo.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteContentInfo (

+  UINT8  **P,

+  UINT8  *Start,

+  UINT8  *Content,

+  INTN   ContentLen

+  )

+{

+  INT32  ret;

+  INT32  Len;

+

+  Len = 0;

+  if (Content != NULL) {

+    MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (P, Start, Content, ContentLen));

+  }

+

+  MBEDTLS_ASN1_CHK_ADD (

+    Len,

+    mbedtls_asn1_write_oid (

+      P,

+      Start,

+      MBEDTLS_OID_PKCS7_DATA,

+      sizeof (MBEDTLS_OID_PKCS7_DATA) - 1

+      )

+    );

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));

+

+  return Len;

+}

+

+/**

+   certificates :: SET OF ExtendedCertificateOrCertificate,

+   ExtendedCertificateOrCertificate ::= CHOICE {

+        certificate Certificate -- x509,

+        extendedCertificate[0] IMPLICIT ExtendedCertificate }.

+

+  @param[in, out]  P           The reference to the current position pointer.

+  @param[in]       Start       The start of the buffer, for bounds-checking.

+  @param[in]       Cert        Certificate.

+  @param[in]       OtherCerts  Ohter Certificate.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteCertificates (

+  UINT8             **P,

+  UINT8             *Start,

+  mbedtls_x509_crt  *Cert,

+  mbedtls_x509_crt  *OtherCerts

+  )

+{

+  INT32             ret;

+  INT32             Len;

+  mbedtls_x509_crt  *TmpCert;

+

+  Len = 0;

+

+  /// Write OtherCerts

+  TmpCert = OtherCerts;

+  while (TmpCert != NULL) {

+    MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, TmpCert->raw.p, TmpCert->raw.len));

+    TmpCert = TmpCert->next;

+  }

+

+  /// Write Cert

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, Cert->raw.p, Cert->raw.len));

+

+  /// Write NextContext

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));

+  return Len;

+}

+

+/**

+  write Pkcs7 Int.

+

+  @param[in, out]  P            The reference to the current position pointer.

+  @param[in]       Start        The start of the buffer, for bounds-checking.

+  @param[in]       SerialRaw    SerialRaw.

+  @param[in]       SerialRawLen Size of SerialRaw.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteInt (

+  UINT8  **P,

+  UINT8  *Start,

+  UINT8  *SerialRaw,

+  INTN   SerialRawLen

+  )

+{

+  INT32  ret;

+  UINT8  *Ptr;

+  INT32  Len;

+

+  Len = 0;

+  Ptr = SerialRaw + SerialRawLen;

+  while (Ptr > SerialRaw) {

+    *--(*P) = *--Ptr;

+    Len++;

+  }

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_INTEGER));

+

+  return Len;

+}

+

+/**

+  write Pkcs7 Issuer And SerialNumber.

+

+  @param[in, out]  P            The reference to the current position pointer.

+  @param[in]       Start        The start of the buffer, for bounds-checking.

+  @param[in]       Serial       Serial.

+  @param[in]       SerialLen    Size of Serial.

+  @param[in]       IssuerRaw    IssuerRawLen.

+  @param[in]       IssuerRawLen Size of IssuerRawLen.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteIssuerAndSerialNumber (

+  UINT8  **P,

+  UINT8  *Start,

+  UINT8  *Serial,

+  INTN   SerialLen,

+  UINT8  *IssuerRaw,

+  INTN   IssuerRawLen

+  )

+{

+  INT32  ret;

+  INT32  Len;

+

+  Len = 0;

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (P, Start, Serial, SerialLen));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (P, Start, IssuerRaw, IssuerRawLen));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));

+

+  return Len;

+}

+

+/**

+   SignerInfo ::= SEQUENCE {

+        version Version;

+        issuerAndSerialNumber   IssuerAndSerialNumber,

+        digestAlgorithm DigestAlgorithmIdentifier,

+        authenticatedAttributes

+                [0] IMPLICIT Attributes OPTIONAL,

+        digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,

+        encryptedDigest EncryptedDigest,

+        unauthenticatedAttributes

+                [1] IMPLICIT Attributes OPTIONAL.

+

+  @param[in, out]  P            The reference to the current position pointer.

+  @param[in]       Start        The start of the buffer, for bounds-checking.

+  @param[in]       SignerInfo    SignerInfo.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteSignerInfo (

+  UINT8                   **P,

+  UINT8                   *Start,

+  MbedtlsPkcs7SignerInfo  *SignerInfo

+  )

+{

+  INT32  ret;

+  INT32  Len;

+

+  Len = 0;

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (P, Start, SignerInfo->Sig.p, SignerInfo->Sig.len));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (P, Start, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIdentifier.len, 0));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (P, Start, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier.len, 0));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (P, Start, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p, SignerInfo->IssuerRaw.len));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (P, Start, SignerInfo->Version));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));

+

+  return Len;

+}

+

+/**

+  write Pkcs7 Signers Info Set.

+

+  @param[in, out]  P            The reference to the current position pointer.

+  @param[in]       Start        The start of the buffer, for bounds-checking.

+  @param[in]       SignersSet   SignerInfo Set.

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteSignersInfoSet (

+  UINT8                   **P,

+  UINT8                   *Start,

+  MbedtlsPkcs7SignerInfo  *SignersSet

+  )

+{

+  MbedtlsPkcs7SignerInfo  *SignerInfo;

+  INT32                   ret;

+  INT32                   Len;

+

+  SignerInfo = SignersSet;

+  Len        = 0;

+

+  while (SignerInfo != NULL) {

+    MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (P, Start, SignerInfo));

+    // move to next

+    SignerInfo = SignerInfo->Next;

+  }

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));

+

+  return Len;

+}

+

+/**

+  Signed Data Type

+  SignedData ::= SEQUENCE {

+  version Version,

+  digestAlgorithms DigestAlgorithmIdentifiers,

+  contentInfo ContentInfo,

+  certificates

+      [0] IMPLICIT ExtendedCertificatesAndCertificates

+        OPTIONAL,

+  crls

+    [1] IMPLICIT CertificateRevocationLists OPTIONAL,

+  signerInfos SignerInfos }

+

+  DigestAlgorithmIdentifiers ::=

+      SET OF DigestAlgorithmIdentifier

+

+  SignerInfos ::= SET OF SignerInfo.

+

+  @param[in, out]  P            The reference to the current position pointer.

+  @param[in]       Start        The start of the buffer, for bounds-checking.

+  @param[in]       Pkcs7        MbedtlsPkcs7

+

+  @retval number      The number of bytes written to p on success.

+  @retval negative  A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7WriteDer (

+  UINT8         **P,

+  UINT8         *Start,

+  MbedtlsPkcs7  *Pkcs7

+  )

+{

+  INT32              ret;

+  INT32              Len;

+  mbedtls_md_type_t  DigestAlg[1];

+

+  DigestAlg[0] = MBEDTLS_MD_SHA256;

+  Len          = 0;

+

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (P, Start, &(Pkcs7->SignedData.SignerInfos)));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (P, Start, &(Pkcs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (P, Start, NULL, 0));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (P, Start, DigestAlg, 1));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (P, Start, Pkcs7->SignedData.Version));

+

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (P, Start, Len));

+  MBEDTLS_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (P, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));

+

+  return Len;

+}

+

+/**

+  Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message

+  Syntax Standard, version 1.5". This interface is only intended to be used for

+  application to perform PKCS#7 functionality validation.

+

+  If this interface is not supported, then return FALSE.

+

+  @param[in]  PrivateKey       Pointer to the PEM-formatted private key data for

+                               data signing.

+  @param[in]  PrivateKeySize   Size of the PEM private key data in bytes.

+  @param[in]  KeyPassword      NULL-terminated passphrase used for encrypted PEM

+                               key data.

+  @param[in]  InData           Pointer to the content to be signed.

+  @param[in]  InDataSize       Size of InData in bytes.

+  @param[in]  SignCert         Pointer to signer's DER-encoded certificate to sign with.

+  @param[in]  OtherCerts       Pointer to an optional additional set of certificates to

+                               include in the PKCS#7 signedData (e.g. any intermediate

+                               CAs in the chain).

+  @param[out] SignedData       Pointer to output PKCS#7 signedData. It's caller's

+                               responsibility to free the buffer with FreePool().

+  @param[out] SignedDataSize   Size of SignedData in bytes.

+

+  @retval     TRUE             PKCS#7 data signing succeeded.

+  @retval     FALSE            PKCS#7 data signing failed.

+  @retval     FALSE            This interface is not supported.

+

+**/

+BOOLEAN

+EFIAPI

+Pkcs7Sign (

+  IN CONST UINT8  *PrivateKey,

+  IN UINTN        PrivateKeySize,

+  IN CONST UINT8  *KeyPassword,

+  IN UINT8        *InData,

+  IN UINTN        InDataSize,

+  IN UINT8        *SignCert,

+  IN UINT8        *OtherCerts OPTIONAL,

+  OUT UINT8       **SignedData,

+  OUT UINTN       *SignedDataSize

+  )

+{

+  BOOLEAN             Status;

+  INT32               Ret;

+  mbedtls_pk_context  Pkey;

+  UINT8               HashValue[SHA256_DIGEST_SIZE];

+  UINT8               Signature[MAX_SIGNATURE_SIZE];

+  UINTN               SignatureLen;

+  UINT8               *NewPrivateKey;

+  mbedtls_x509_crt    *Crt;

+

+  MbedtlsPkcs7            Pkcs7;

+  MbedtlsPkcs7SignerInfo  SignerInfo;

+  UINT8                   *Buffer;

+  INTN                    BufferSize;

+  UINT8                   *P;

+  INT32                   Len;

+

+  BufferSize = 4096;

+

+  SignatureLen = MAX_SIGNATURE_SIZE;

+  Crt          = (mbedtls_x509_crt *)SignCert;

+

+  NewPrivateKey = NULL;

+  if (PrivateKey[PrivateKeySize - 1] != 0) {

+    NewPrivateKey = AllocateZeroPool (PrivateKeySize + 1);

+    if (NewPrivateKey == NULL) {

+      return FALSE;

+    }

+

+    CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);

+    NewPrivateKey[PrivateKeySize] = 0;

+    PrivateKeySize++;

+  } else {

+    NewPrivateKey = AllocateZeroPool (PrivateKeySize);

+    if (NewPrivateKey == NULL) {

+      return FALSE;

+    }

+

+    CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);

+  }

+

+  mbedtls_pk_init (&Pkey);

+  Ret = mbedtls_pk_parse_key (

+          &Pkey,

+          NewPrivateKey,

+          PrivateKeySize,

+          KeyPassword,

+          KeyPassword == NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPassword),

+          NULL,

+          NULL

+          );

+  if (Ret != 0) {

+    Status = FALSE;

+    goto Cleanup;

+  }

+

+  /// Calculate InData Digest

+  ZeroMem (HashValue, SHA256_DIGEST_SIZE);

+  Status = Sha256HashAll (InData, InDataSize, HashValue);

+  if (!Status) {

+    goto Cleanup;

+  }

+

+  /// Pk Sign

+  ZeroMem (Signature, MAX_SIGNATURE_SIZE);

+  Ret = mbedtls_pk_sign (

+          &Pkey,

+          MBEDTLS_MD_SHA256,

+          HashValue,

+          SHA256_DIGEST_SIZE,

+          Signature,

+          MAX_SIGNATURE_SIZE,

+          &SignatureLen,

+          MbedtlsRand,

+          NULL

+          );

+  if (Ret != 0) {

+    Status = FALSE;

+    goto Cleanup;

+  }

+

+  ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7));

+  Pkcs7.SignedData.Version = 1;

+

+  Crt->next                     = (mbedtls_x509_crt *)OtherCerts;

+  Pkcs7.SignedData.Certificates = *Crt;

+

+  SignerInfo.Next              = NULL;

+  SignerInfo.Sig.p             = Signature;

+  SignerInfo.Sig.len           = SignatureLen;

+  SignerInfo.Version           = 1;

+  SignerInfo.AlgIdentifier.p   = MbedtlsOidDigestAlgSha256;

+  SignerInfo.AlgIdentifier.len = sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1;

+  if (mbedtls_pk_get_type (&Pkey) == MBEDTLS_PK_RSA) {

+    SignerInfo.SigAlgIdentifier.p   = MbedtlsOidPkcs1Rsa;

+    SignerInfo.SigAlgIdentifier.len = sizeof (MBEDTLS_OID_PKCS1_RSA) - 1;

+  } else {

+    mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgIdentifier.len);

+  }

+

+  SignerInfo.Serial            = ((mbedtls_x509_crt *)SignCert)->serial;

+  SignerInfo.IssuerRaw         = ((mbedtls_x509_crt *)SignCert)->issuer_raw;

+  Pkcs7.SignedData.SignerInfos = SignerInfo;

+

+  Buffer = AllocateZeroPool (BufferSize);

+  if (Buffer == NULL) {

+    Status = FALSE;

+    goto Cleanup;

+  }

+

+  P   = Buffer + BufferSize;

+  Len = MbedTlsPkcs7WriteDer (&P, Buffer, &Pkcs7);

+

+  /// Enlarge buffer if buffer is too small

+  while (Len < 0 && Len == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {

+    BufferSize = BufferSize * 2;

+    P          = Buffer + BufferSize;

+    FreePool (Buffer);

+    Buffer = AllocateZeroPool (BufferSize);

+    if (Buffer == NULL) {

+      Status = FALSE;

+      goto Cleanup;

+    }

+

+    P   = Buffer + BufferSize;

+    Len = MbedTlsPkcs7WriteDer (&P, Buffer, &Pkcs7);

+  }

+

+  if (Len <= 0) {

+    Status = FALSE;

+    goto Cleanup;

+  }

+

+  *SignedData     = AllocateZeroPool (Len);

+  *SignedDataSize = Len;

+  CopyMem (*SignedData, P, Len);

+  Status = TRUE;

+

+Cleanup:

+  if (&Pkey != NULL) {

+    mbedtls_pk_free (&Pkey);

+  }

+

+  if (NewPrivateKey != NULL) {

+    FreePool (NewPrivateKey);

+  }

+

+  if (Buffer != NULL) {

+    FreePool (Buffer);

+  }

+

+  return Status;

+}

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
new file mode 100644
index 0000000000..6b62ee2618
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
@@ -0,0 +1,113 @@
+/** @file

+  Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper.

+

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

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

+

+**/

+

+#include "InternalCryptLib.h"

+#include <mbedtls/pkcs7.h>

+

+/**

+  Extracts the attached content from a PKCS#7 signed data if existed. The input signed

+  data could be wrapped in a ContentInfo structure.

+

+  If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow,

+  then return FALSE. If the P7Data is not correctly formatted, then return FALSE.

+

+  Caution: This function may receive untrusted input. So this function will do

+           basic check for PKCS#7 data structure.

+

+  @param[in]   P7Data       Pointer to the PKCS#7 signed data to process.

+  @param[in]   P7Length     Length of the PKCS#7 signed data in bytes.

+  @param[out]  Content      Pointer to the extracted content from the PKCS#7 signedData.

+                            It's caller's responsibility to free the buffer with FreePool().

+  @param[out]  ContentSize  The size of the extracted content in bytes.

+

+  @retval     TRUE          The P7Data was correctly formatted for processing.

+  @retval     FALSE         The P7Data was not correctly formatted for processing.

+

+**/

+BOOLEAN

+EFIAPI

+Pkcs7GetAttachedContent (

+  IN CONST UINT8  *P7Data,

+  IN UINTN        P7Length,

+  OUT VOID        **Content,

+  OUT UINTN       *ContentSize

+  )

+{

+  BOOLEAN             Status;

+  UINT8               *SignedData;

+  UINTN               SignedDataSize;

+  BOOLEAN             Wrapped;

+  INTN                Ret;

+  mbedtls_pkcs7       Pkcs7;

+  mbedtls_pkcs7_data  *MbedtlsContent;

+

+  mbedtls_pkcs7_init (&Pkcs7);

+

+  //

+  // Check input parameter.

+  //

+  if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) {

+    return FALSE;

+  }

+

+  *Content   = NULL;

+  SignedData = NULL;

+

+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);

+  if (!Status || (SignedDataSize > INT_MAX)) {

+    goto _Exit;

+  }

+

+  Status = FALSE;

+

+  Ret = mbedtls_pkcs7_parse_der (&Pkcs7, SignedData, (INT32)SignedDataSize);

+

+  //

+  // The type of Pkcs7 must be signedData

+  //

+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {

+    goto _Exit;

+  }

+

+  //

+  // Check for detached or attached content

+  //

+  MbedtlsContent = &(Pkcs7.signed_data.content);

+

+  if (MbedtlsContent == NULL) {

+    //

+    // No Content supplied for PKCS7 detached signedData

+    //

+    *Content     = NULL;

+    *ContentSize = 0;

+  } else {

+    //

+    // Retrieve the attached content in PKCS7 signedData

+    //

+    if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) {

+      *ContentSize = MbedtlsContent->data.len;

+      *Content     = AllocateZeroPool (*ContentSize);

+      if (*Content == NULL) {

+        *ContentSize = 0;

+        goto _Exit;

+      }

+

+      CopyMem (*Content, MbedtlsContent->data.p, *ContentSize);

+    }

+  }

+

+  Status = TRUE;

+

+_Exit:

+  //

+  // Release Resources

+  //

+  mbedtls_pkcs7_free (&Pkcs7);

+

+  return Status;

+}

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
new file mode 100644
index 0000000000..f5ca4c528a
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
@@ -0,0 +1,1315 @@
+/** @file

+  PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper

+  Implementation over mbedtls.

+

+  RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites

+  FIPS 186-4 - Digital Signature Standard (DSS)

+

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

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

+

+**/

+

+#include "CryptPkcs7Internal.h"

+#include <mbedtls/pkcs7.h>

+

+/* Profile for backward compatibility. Allows RSA 1024, unlike the default

+   profile. */

+STATIC mbedtls_x509_crt_profile  gCompatProfile =

+{

+  /* Hashes from SHA-256 and above. Note that this selection

+   * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */

+

+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) |

+ #endif

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),

+  0xFFFFFFF,       /* Any PK alg    */

+

+  /* Curves at or above 128-bit security level. Note that this selection

+   * should be aligned with ssl_preset_default_curves in ssl_tls.c. */

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |

+  MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |

+  0,

+  1024,

+};

+

+/**

+ Init MbedtlsPkcs7.

+

+  @param[in]  Pkcs7     MbedtlsPkcs7.

+**/

+STATIC

+VOID

+MbedTlsPkcs7Init (

+  MbedtlsPkcs7  *Pkcs7

+  )

+{

+  ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7));

+}

+

+/**

+  Get Pkcs7 Next Content Len.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Len          MbedtlsPkcs7 Content Len.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetNextContentLen (

+  UINT8  **P,

+  UINT8  *End,

+  UINTN  *Len

+  )

+{

+  INT32  Ret;

+

+  Ret = mbedtls_asn1_get_tag (P, End, Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);

+  return Ret;

+}

+

+/**

+  Get Pkcs7 Version..

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Ver          MbedtlsPkcs7 Version.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetVersion (

+  UINT8  **P,

+  UINT8  *End,

+  INT32  *Ver

+  )

+{

+  INT32  Ret;

+

+  Ret = mbedtls_asn1_get_int (P, End, Ver);

+  return Ret;

+}

+

+/**

+   ContentInfo ::= SEQUENCE {

+        contentType ContentType,

+        content

+                [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Pkcs7        MbedtlsPkcs7.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+Pkcs7GetContentInfoType (

+  UINT8             **P,

+  UINT8             *End,

+  mbedtls_asn1_buf  *Pkcs7

+  )

+{

+  UINTN  Len;

+  int    Ret;

+

+  Len = 0;

+  Ret = mbedtls_asn1_get_tag (

+          P,

+          End,

+          &Len,

+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE

+          );

+

+  if (Ret == 0) {

+    Ret = mbedtls_asn1_get_tag (P, End, &Len, MBEDTLS_ASN1_OID);

+  }

+

+  if (Ret == 0) {

+    Pkcs7->tag = MBEDTLS_ASN1_OID;

+    Pkcs7->len = Len;

+    Pkcs7->p   = *P;

+  }

+

+  return Ret;

+}

+

+/**

+  DigestAlgorithmIdentifier ::= AlgorithmIdentifier.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Alg          MbedtlsPkcs7 AlgorithmIdentifier.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetDigestAlgorithm (

+  UINT8             **P,

+  UINT8             *End,

+  mbedtls_x509_buf  *Alg

+  )

+{

+  INT32  Ret;

+

+  Ret = mbedtls_asn1_get_alg_null (P, End, Alg);

+  return Ret;

+}

+

+/**

+  DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Alg          MbedtlsPkcs7 AlgorithmIdentifier.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetDigestAlgorithmSet (

+  UINT8             **P,

+  UINT8             *End,

+  mbedtls_x509_buf  *Alg

+  )

+{

+  UINTN  Len;

+  INT32  Ret;

+

+  Len = 0;

+  Ret = mbedtls_asn1_get_tag (

+          P,

+          End,

+          &Len,

+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET

+          );

+

+  if (Ret == 0) {

+    End = *P + Len;

+    // assume only one digest algorithm

+    Ret = mbedtls_asn1_get_alg_null (P, End, Alg);

+  }

+

+  return Ret;

+}

+

+/**

+   certificates :: SET OF ExtendedCertificateOrCertificate,

+   ExtendedCertificateOrCertificate ::= CHOICE {

+        certificate Certificate -- x509,

+        extendedCertificate[0] IMPLICIT ExtendedCertificate }.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  Plen         The buffer len.

+  @param[out] Certs        mbedtls_x509_crt cert.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetCertificates (

+  UINT8             **P,

+  INTN              Plen,

+  mbedtls_x509_crt  *Certs

+  )

+{

+  INT32  Ret;

+

+  Ret = mbedtls_x509_crt_parse (Certs, *P, Plen);

+  return Ret;

+}

+

+/**

+   EncryptedDigest ::= OCTET STRING.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] Signature    Signature.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+Pkcs7GetSignature (

+  UINT8             **P,

+  UINT8             *End,

+  mbedtls_asn1_buf  *Signature

+  )

+{

+  INT32  Ret;

+  UINTN  Len;

+

+  Len = 0;

+  Ret = mbedtls_asn1_get_tag (P, End, &Len, MBEDTLS_ASN1_OCTET_STRING);

+  if (Ret == 0) {

+    Signature->tag = MBEDTLS_ASN1_OCTET_STRING;

+    Signature->len = Len;

+    Signature->p   = *P;

+  }

+

+  return Ret;

+}

+

+/**

+   SignerInfo ::= SEQUENCE {

+        version Version;

+        issuerAndSerialNumber   IssuerAndSerialNumber,

+        digestAlgorithm DigestAlgorithmIdentifier,

+        authenticatedAttributes

+                [0] IMPLICIT Attributes OPTIONAL,

+        digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,

+        encryptedDigest EncryptedDigest,

+        unauthenticatedAttributes

+                [1] IMPLICIT Attributes OPTIONAL.

+

+  @param[in]  P            The start of the buffer.

+  @param[in]  End          The end of the buffer.

+  @param[out] SignersSet   MbedtlsPkcs7SignerInfo.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedTlsPkcs7GetSignersInfoSet (

+  UINT8                   **P,

+  UINT8                   *End,

+  MbedtlsPkcs7SignerInfo  *SignersSet

+  )

+{

+  UINT8  *EndSet;

+  INT32  Ret;

+  UINTN  Len;

+  UINT8  *TempP;

+

+  Len = 0;

+

+  Ret = mbedtls_asn1_get_tag (

+          P,

+          End,

+          &Len,

+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET

+          );

+

+  if (Ret == 0) {

+    EndSet = *P + Len;

+

+    Ret = mbedtls_asn1_get_tag (

+            P,

+            EndSet,

+            &Len,

+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE

+            );

+  }

+

+  if (Ret == 0) {

+    Ret = mbedtls_asn1_get_int (P, EndSet, &SignersSet->Version);

+  }

+

+  if (Ret == 0) {

+    Ret = mbedtls_asn1_get_tag (

+            P,

+            EndSet,

+            &Len,

+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE

+            );

+  }

+

+  if (Ret == 0) {

+    SignersSet->IssuerRaw.p = *P;

+    Ret                     = mbedtls_asn1_get_tag (

+                                P,

+                                EndSet,

+                                &Len,

+                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE

+                                );

+  }

+

+  if (Ret == 0) {

+    Ret = mbedtls_x509_get_name (P, *P + Len, &SignersSet->Issuer);

+  }

+

+  if (Ret == 0) {

+    SignersSet->IssuerRaw.len = *P - SignersSet->IssuerRaw.p;

+

+    Ret = mbedtls_x509_get_serial (P, EndSet, &SignersSet->Serial);

+  }

+

+  if (Ret == 0) {

+    Ret = MbedTlsPkcs7GetDigestAlgorithm (P, EndSet, &SignersSet->AlgIdentifier);

+  }

+

+  // OPTIONAL AuthenticatedAttributes

+  if (Ret == 0) {

+    TempP = *P;

+    if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {

+      SignersSet->AuthAttr.len = Len + (TempP - *P);

+      SignersSet->AuthAttr.p   = *P;

+      *P                       = TempP + Len;

+    } else {

+      SignersSet->AuthAttr.p = NULL;

+    }

+  }

+

+  if (Ret == 0) {

+    Ret = MbedTlsPkcs7GetDigestAlgorithm (P, EndSet, &SignersSet->SigAlgIdentifier);

+  }

+

+  if (Ret == 0) {

+    Ret = Pkcs7GetSignature (P, End, &SignersSet->Sig);

+  }

+

+  if (Ret == 0) {

+    SignersSet->Next = NULL;

+  }

+

+  return Ret;

+}

+

+/**

+   SignedData ::= SEQUENCE {

+        version Version,

+        digestAlgorithms DigestAlgorithmIdentifiers,

+        contentInfo ContentInfo,

+        certificates

+                [0] IMPLICIT ExtendedCertificatesAndCertificates

+                    OPTIONAL,

+        crls

+                [0] IMPLICIT CertificateRevocationLists OPTIONAL,

+        signerInfos SignerInfos }.

+

+  @param[in]  Buffer       The start of the buffer.

+  @param[in]  BufferLen    The len the buffer.

+  @param[out] SignedData   MbedtlsPkcs7SignedData.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+Pkcs7GetSignedData (

+  UINT8                   *Buffer,

+  INTN                    BufferLen,

+  MbedtlsPkcs7SignedData  *SignedData

+  )

+{

+  UINT8             *P;

+  UINT8             *End;

+  UINTN             Len;

+  INT32             Ret;

+  UINT8             *CertP;

+  UINTN             CertLen;

+  UINT8             *OldCertP;

+  UINTN             TotalCertLen;

+  mbedtls_x509_crt  *MoreCert;

+  UINT8             CertNum;

+  mbedtls_x509_crt  *LastCert;

+

+  Len      = 0;

+  P        = Buffer;

+  End      = Buffer + BufferLen;

+  MoreCert = NULL;

+

+  Ret = mbedtls_asn1_get_tag (

+          &P,

+          End,

+          &Len,

+          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE

+          );

+

+  if (Ret == 0) {

+    // version

+    Ret = MbedTlsPkcs7GetVersion (&P, End, &SignedData->Version);

+  }

+

+  if ((Ret == 0) && (SignedData->Version != 1)) {

+    Ret = -1;

+  }

+

+  if (Ret == 0) {

+    // digest algorithm

+    Ret = MbedTlsPkcs7GetDigestAlgorithmSet (

+            &P,

+            End,

+            &SignedData->DigestAlgorithms

+            );

+  }

+

+  if (Ret == 0) {

+    if (

+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES

+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA1) - 1) &&

+         (CompareMem (

+            SignedData->DigestAlgorithms.p,

+            MBEDTLS_OID_DIGEST_ALG_SHA1,

+            SignedData->DigestAlgorithms.len

+            ) == 0)) ||

+ #endif

+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1) &&

+         (CompareMem (

+            SignedData->DigestAlgorithms.p,

+            MBEDTLS_OID_DIGEST_ALG_SHA256,

+            SignedData->DigestAlgorithms.len

+            ) == 0)) ||

+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA384) - 1) &&

+         (CompareMem (

+            SignedData->DigestAlgorithms.p,

+            MBEDTLS_OID_DIGEST_ALG_SHA384,

+            SignedData->DigestAlgorithms.len

+            ) == 0)) ||

+        ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA512) - 1) &&

+         (CompareMem (

+            SignedData->DigestAlgorithms.p,

+            MBEDTLS_OID_DIGEST_ALG_SHA512,

+            SignedData->DigestAlgorithms.len

+            ) == 0)))

+    {

+      Ret = 0;

+    } else {

+      Ret = -1;

+    }

+  }

+

+  if (Ret == 0) {

+    Ret = Pkcs7GetContentInfoType (&P, End, &SignedData->ContentInfo.Oid);

+  }

+

+  if (Ret == 0) {

+    // move to next

+    P     = P + SignedData->ContentInfo.Oid.len;

+    Ret   = MbedTlsPkcs7GetNextContentLen (&P, End, &Len);

+    CertP = P + Len;

+

+    // move to actual cert, if there are more [0]

+    if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) == 0) {

+      Len = CertLen;

+      P   = CertP;

+    }

+  }

+

+  // certificates: may have many certs

+  CertP = P;

+

+  TotalCertLen = 0;

+

+  MoreCert = &SignedData->Certificates;

+  CertNum  = 0;

+

+  while (TotalCertLen < Len) {

+    OldCertP = CertP;

+

+    Ret = mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);

+    if (Ret != 0) {

+      goto End;

+    }

+

+    // cert total len

+    CertLen = CertLen + (CertP - OldCertP);

+

+    // move to next cert

+    CertP = OldCertP + CertLen;

+

+    // change TotalCertLen

+    TotalCertLen += CertLen;

+

+    mbedtls_x509_crt_init (MoreCert);

+    Ret = MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert);

+    if (Ret != 0) {

+      goto End;

+    }

+

+    CertNum++;

+    MoreCert->next = AllocateZeroPool (sizeof (mbedtls_x509_crt));

+    MoreCert       = MoreCert->next;

+  }

+

+  if (TotalCertLen != Len) {

+    Ret = -1;

+    goto End;

+  }

+

+  LastCert = &(SignedData->Certificates);

+

+  while (CertNum--) {

+    if (CertNum == 0) {

+      LastCert->next = NULL;

+      break;

+    } else {

+      LastCert = LastCert->next;

+    }

+  }

+

+  // signers info

+  if (Ret == 0) {

+    P   = P + Len;

+    Ret = MbedTlsPkcs7GetSignersInfoSet (&P, End, &SignedData->SignerInfos);

+  }

+

+End:

+  if (MoreCert != NULL) {

+    FreePool (MoreCert);

+    MoreCert = NULL;

+  }

+

+  return Ret;

+}

+

+/**

+  Parse MbedtlsPkcs7 to Der format.

+  @param[in]  Buffer       The start of the buffer.

+  @param[in]  BufferLen    The len the buffer.

+  @param[out] Pkcs7        MbedtlsPkcs7.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedtlsPkcs7ParseDer (

+  CONST UINT8   *Buffer,

+  INTN          BufferLen,

+  MbedtlsPkcs7  *Pkcs7

+  )

+{

+  UINT8  *P;

+  UINT8  *End;

+  UINTN  Len;

+  INT32  Ret;

+

+  if (Pkcs7 == NULL) {

+    return -1;

+  }

+

+  Len = 0;

+  P   = (UINT8 *)Buffer;

+  End = P + BufferLen;

+

+  Ret = Pkcs7GetContentInfoType (&P, End, &Pkcs7->ContentTypeOid);

+  if (Ret != 0) {

+    goto out;

+  }

+

+  if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0)) {

+    // Invalid PKCS7 data type;

+    Ret = -1;

+    goto out;

+  }

+

+  if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, Pkcs7->ContentTypeOid.len) != 0) {

+    // Invalid PKCS7 data type;

+    Ret = -1;

+    goto out;

+  }

+

+  // Content type is SignedData

+  P = P + Pkcs7->ContentTypeOid.len;

+

+  Ret = MbedTlsPkcs7GetNextContentLen (&P, End, &Len);

+  if (Ret != 0) {

+    goto out;

+  }

+

+  Ret = Pkcs7GetSignedData (P, Len, &Pkcs7->SignedData);

+  if (Ret != 0) {

+    goto out;

+  }

+

+out:

+  return Ret;

+}

+

+/**

+  MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo.

+  @param[in]  SignerInfo   MbedtlsPkcs7 SignerInfo.

+  @param[in]  Cert         cert.

+  @param[in]  Data         Pointer for data.

+  @param[in]  DataLen      The len the buffer.

+

+  @retval 0                Success.

+  @retval negative         A negative MBEDTLS_ERR_ASN1_XXX error code on failure.

+**/

+STATIC

+INT32

+MbedtlsPkcs7SignedDataVerifySigners (

+  MbedtlsPkcs7SignerInfo  *SignerInfo,

+  mbedtls_x509_crt        *Cert,

+  CONST UINT8             *Data,

+  INTN                    DataLen

+  )

+{

+  INT32                    Ret;

+  UINT8                    Hash[MBEDTLS_MD_MAX_SIZE];

+  mbedtls_pk_context       Pk;

+  CONST mbedtls_md_info_t  *MdInfo;

+  INTN                     HashLen;

+  UINT8                    TempAuthAttr;

+

+  Pk = Cert->pk;

+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);

+

+  // all the hash algo

+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES

+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1);

+  HashLen = mbedtls_md_get_size (MdInfo);

+  mbedtls_md (MdInfo, Data, DataLen, Hash);

+  if (SignerInfo->AuthAttr.p != NULL) {

+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);

+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;

+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);

+    // Restore content

+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;

+  }

+

+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);

+

+  if (Ret == 0) {

+    return Ret;

+  }

+

+ #endif

+

+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256);

+  HashLen = mbedtls_md_get_size (MdInfo);

+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);

+  mbedtls_md (MdInfo, Data, DataLen, Hash);

+  if (SignerInfo->AuthAttr.p != NULL) {

+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);

+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;

+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);

+    // Restore content

+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;

+  }

+

+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);

+  if (Ret == 0) {

+    return Ret;

+  }

+

+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA384);

+  HashLen = mbedtls_md_get_size (MdInfo);

+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);

+  mbedtls_md (MdInfo, Data, DataLen, Hash);

+  if (SignerInfo->AuthAttr.p != NULL) {

+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);

+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;

+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);

+    // Restore content

+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;

+  }

+

+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);

+  if (Ret == 0) {

+    return Ret;

+  }

+

+  MdInfo  = mbedtls_md_info_from_type (MBEDTLS_MD_SHA512);

+  HashLen = mbedtls_md_get_size (MdInfo);

+  ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);

+  mbedtls_md (MdInfo, Data, DataLen, Hash);

+  if (SignerInfo->AuthAttr.p != NULL) {

+    TempAuthAttr              = *(SignerInfo->AuthAttr.p);

+    *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;

+    mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);

+    // Restore content

+    *(SignerInfo->AuthAttr.p) = TempAuthAttr;

+  }

+

+  Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);

+  if (Ret == 0) {

+    return Ret;

+  }

+

+  return Ret;

+}

+

+/**

+  Find signer cert in MbedtlsPkcs7SignerInfo.

+

+  @param[in]  SignerInfo   MbedtlsPkcs7 SignerInfo.

+  @param[in]  Certs        MbedtlsPkcs7 SignerInfo certs.

+

+  @retval cert             Signer Cert.

+**/

+STATIC

+mbedtls_x509_crt *

+MbedTlsPkcs7FindSignerCert (

+  MbedtlsPkcs7SignerInfo  *SignerInfo,

+  mbedtls_x509_crt        *Certs

+  )

+{

+  mbedtls_x509_crt  *Cert;

+

+  Cert = Certs;

+  while (Cert != NULL) {

+    if ((Cert->issuer_raw.len == SignerInfo->IssuerRaw.len) &&

+        (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->issuer_raw.len) == 0) &&

+        (Cert->serial.len == SignerInfo->Serial.len) &&

+        (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.len) == 0))

+    {

+      break;

+    }

+

+    Cert = Cert->next;

+  }

+

+  return Cert;

+}

+

+/**

+  verify cert.

+

+  @param[in]  Ca    CA cert.

+  @param[in]  CaCrl CRL.

+  @param[in]  End   Cert which need be verified.

+

+  @retval TRUE      Verify successfully.

+  @retval FALSE     Verify failed.

+**/

+STATIC

+BOOLEAN

+MbedTlsPkcs7VerifyCert (

+  mbedtls_x509_crt  *Ca,

+  mbedtls_x509_crl  *CaCrl,

+  mbedtls_x509_crt  *End

+  )

+{

+  INT32                     Ret;

+  UINT32                    VFlag;

+  mbedtls_x509_crt_profile  Profile;

+

+  VFlag = 0;

+  CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));

+

+  Ret = mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, NULL, &VFlag, NULL, NULL);

+

+  return Ret == 0;

+}

+

+/**

+  verify cert chain.

+

+  @param[in]  Pkcs7 MbedtlsPkcs7.

+  @param[in]  Ca    CA cert.

+  @param[in]  End   Cert which need be verified.

+

+  @retval TRUE      Verify successfully.

+  @retval FALSE     Verify failed.

+**/

+STATIC

+BOOLEAN

+MbedTlsPkcs7VerifyCertChain (

+  MbedtlsPkcs7      *Pkcs7,

+  mbedtls_x509_crt  *Ca,

+  mbedtls_x509_crt  *End

+  )

+{

+  mbedtls_x509_crt  *AllCert;

+  mbedtls_x509_crt  *InterCert;

+

+  AllCert   = &(Pkcs7->SignedData.Certificates);

+  InterCert = NULL;

+

+  while (AllCert != NULL) {

+    if ((AllCert->next == End) && (MbedTlsPkcs7VerifyCert (AllCert, NULL, End))) {

+      InterCert = AllCert;

+      break;

+    }

+

+    AllCert = AllCert->next;

+  }

+

+  if (InterCert == NULL) {

+    return FALSE;

+  }

+

+  if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) {

+    return TRUE;

+  } else {

+    return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert);

+  }

+}

+

+/**

+  MbedTlsPkcs7 Verify SignedData.

+

+  @param[in]  Pkcs7        MbedtlsPkcs7.

+  @param[in]  TrustCert    CA cert.

+  @param[in]  Data         Pointer for data.

+  @param[in]  DataLen      The len the buffer.

+

+  @retval TRUE      Verify successfully.

+  @retval FALSE     Verify failed.

+**/

+STATIC

+BOOLEAN

+MbedTlsPkcs7SignedDataVerify (

+  MbedtlsPkcs7      *Pkcs7,

+  mbedtls_x509_crt  *TrustCert,

+  CONST UINT8       *Data,

+  INTN              DataLen

+  )

+{

+  MbedtlsPkcs7SignerInfo  *SignerInfo;

+  mbedtls_x509_crt        *Cert;

+  mbedtls_x509_crt        *AllCert;

+  BOOLEAN                 Result;

+

+  SignerInfo = &(Pkcs7->SignedData.SignerInfos);

+  Result     = TRUE;

+

+  //

+  // Traverse signers and verify each signers

+  //

+  while (SignerInfo != NULL) {

+    Result = FALSE;

+    // 1. Find signers cert

+    Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.Certificates));

+    if (Cert != NULL) {

+      // 2. Check signer cert is trusted by trustCert

+      if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Cert)) {

+        // root cert verify pass

+        Result = TRUE;

+      } else {

+        if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) {

+          Result = TRUE;

+        } else {

+          Result = FALSE;

+        }

+      }

+

+      if (Result == TRUE) {

+        // 3. Check signed data

+        AllCert = &(Pkcs7->SignedData.Certificates);

+        while (AllCert != NULL) {

+          if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Data, DataLen) == 0) {

+            return TRUE;

+          }

+

+          AllCert = AllCert->next;

+        }

+

+        Result = FALSE;

+      }

+    }

+

+    // move to next

+    SignerInfo = SignerInfo->Next;

+  }

+

+  return Result;

+}

+

+/**

+  Check input P7Data is a wrapped ContentInfo structure or not. If not construct

+  a new structure to wrap P7Data.

+

+  Caution: This function may receive untrusted input.

+  UEFI Authenticated Variable is external input, so this function will do basic

+  check for PKCS#7 data structure.

+

+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.

+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.

+  @param[out] WrapFlag     If TRUE P7Data is a ContentInfo structure, otherwise

+                           return FALSE.

+  @param[out] WrapData     If return status of this function is TRUE:

+                           1) when WrapFlag is TRUE, pointer to P7Data.

+                           2) when WrapFlag is FALSE, pointer to a new ContentInfo

+                           structure. It's caller's responsibility to free this

+                           buffer.

+  @param[out] WrapDataSize Length of ContentInfo structure in bytes.

+

+  @retval     TRUE         The operation is finished successfully.

+  @retval     FALSE        The operation is failed due to lack of resources.

+

+**/

+BOOLEAN

+WrapPkcs7Data (

+  IN CONST UINT8  *P7Data,

+  IN UINTN        P7Length,

+  OUT BOOLEAN     *WrapFlag,

+  OUT UINT8       **WrapData,

+  OUT UINTN       *WrapDataSize

+  )

+{

+  BOOLEAN  Wrapped;

+  UINT8    *SignedData;

+

+  //

+  // Check whether input P7Data is a wrapped ContentInfo structure or not.

+  //

+  Wrapped = FALSE;

+  if ((P7Data[4] == 0x06) && (P7Data[5] == 0x09)) {

+    if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1) == 0) {

+      if ((P7Data[15] == 0xA0) && (P7Data[16] == 0x82)) {

+        Wrapped = TRUE;

+      }

+    }

+  }

+

+  if (Wrapped) {

+    *WrapData     = (UINT8 *)P7Data;

+    *WrapDataSize = P7Length;

+  } else {

+    //

+    // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.

+    //

+    *WrapDataSize = P7Length + 19;

+    *WrapData     = AllocateZeroPool (*WrapDataSize);

+    if (*WrapData == NULL) {

+      *WrapFlag = Wrapped;

+      return FALSE;

+    }

+

+    SignedData = *WrapData;

+

+    //

+    // Part1: 0x30, 0x82.

+    //

+    SignedData[0] = 0x30;

+    SignedData[1] = 0x82;

+

+    //

+    // Part2: Length1 = P7Length + 19 - 4, in big endian.

+    //

+    SignedData[2] = (UINT8)(((UINT16)(*WrapDataSize - 4)) >> 8);

+    SignedData[3] = (UINT8)(((UINT16)(*WrapDataSize - 4)) & 0xff);

+

+    //

+    // Part3: 0x06, 0x09.

+    //

+    SignedData[4] = 0x06;

+    SignedData[5] = 0x09;

+

+    //

+    // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.

+    //

+    CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1);

+

+    //

+    // Part5: 0xA0, 0x82.

+    //

+    SignedData[15] = 0xA0;

+    SignedData[16] = 0x82;

+

+    //

+    // Part6: Length2 = P7Length, in big endian.

+    //

+    SignedData[17] = (UINT8)(((UINT16)P7Length) >> 8);

+    SignedData[18] = (UINT8)(((UINT16)P7Length) & 0xff);

+

+    //

+    // Part7: P7Data.

+    //

+    CopyMem (SignedData + 19, P7Data, P7Length);

+  }

+

+  *WrapFlag = Wrapped;

+  return TRUE;

+}

+

+/**

+  Verifies the validity of a PKCS#7 signed data as described in "PKCS #7:

+  Cryptographic Message Syntax Standard". The input signed data could be wrapped

+  in a ContentInfo structure.

+

+  If P7Data, TrustedCert or InData is NULL, then return FALSE.

+  If P7Length, CertLength or DataLength overflow, then return FALSE.

+  If this interface is not supported, then return FALSE.

+

+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.

+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.

+  @param[in]  TrustedCert  Pointer to a trusted/root certificate encoded in DER, which

+                           is used for certificate chain verification.

+  @param[in]  CertLength   Length of the trusted certificate in bytes.

+  @param[in]  InData       Pointer to the content to be verified.

+  @param[in]  DataLength   Length of InData in bytes.

+

+  @retval  TRUE  The specified PKCS#7 signed data is valid.

+  @retval  FALSE Invalid PKCS#7 signed data.

+  @retval  FALSE This interface is not supported.

+

+**/

+BOOLEAN

+EFIAPI

+Pkcs7Verify (

+  IN CONST UINT8  *P7Data,

+  IN UINTN        P7Length,

+  IN CONST UINT8  *TrustedCert,

+  IN UINTN        CertLength,

+  IN CONST UINT8  *InData,

+  IN UINTN        DataLength

+  )

+{

+  BOOLEAN           Status;

+  UINT8             *WrapData;

+  UINTN             WrapDataSize;

+  BOOLEAN           Wrapped;

+  MbedtlsPkcs7      Pkcs7;

+  INT32             Ret;

+  mbedtls_x509_crt  Crt;

+

+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);

+

+  if (Status) {

+    Ret    = 0;

+    Status = FALSE;

+  } else {

+    Ret = -1;

+  }

+

+  MbedTlsPkcs7Init (&Pkcs7);

+  mbedtls_x509_crt_init (&Crt);

+

+  if (Ret == 0) {

+    Ret = MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7);

+  }

+

+  if (Ret == 0) {

+    Ret = mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength);

+  }

+

+  if (Ret == 0) {

+    Status = MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)DataLength);

+  }

+

+  if (&Crt != NULL) {

+    mbedtls_x509_crt_free (&Crt);

+  }

+

+  return Status;

+}

+

+/**

+  Wrap function to use free() to free allocated memory for certificates.

+

+  @param[in]  Certs        Pointer to the certificates to be freed.

+

+**/

+VOID

+EFIAPI

+Pkcs7FreeSigners (

+  IN UINT8  *Certs

+  )

+{

+  if (Certs == NULL) {

+    return;

+  }

+

+  FreePool (Certs);

+}

+

+/**

+  Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:

+  Cryptographic Message Syntax Standard". The input signed data could be wrapped

+  in a ContentInfo structure.

+

+  If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then

+  return FALSE. If P7Length overflow, then return FALSE.

+

+  Caution: This function may receive untrusted input.

+  UEFI Authenticated Variable is external input, so this function will do basic

+  check for PKCS#7 data structure.

+

+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.

+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.

+  @param[out] CertStack    Pointer to Signer's certificates retrieved from P7Data.

+                           It's caller's responsibility to free the buffer with

+                           Pkcs7FreeSigners().

+                           This data structure is EFI_CERT_STACK type.

+  @param[out] StackLength  Length of signer's certificates in bytes.

+  @param[out] TrustedCert  Pointer to a trusted certificate from Signer's certificates.

+                           It's caller's responsibility to free the buffer with

+                           Pkcs7FreeSigners().

+  @param[out] CertLength   Length of the trusted certificate in bytes.

+

+  @retval  TRUE            The operation is finished successfully.

+  @retval  FALSE           Error occurs during the operation.

+

+**/

+BOOLEAN

+EFIAPI

+Pkcs7GetSigners (

+  IN CONST UINT8  *P7Data,

+  IN UINTN        P7Length,

+  OUT UINT8       **CertStack,

+  OUT UINTN       *StackLength,

+  OUT UINT8       **TrustedCert,

+  OUT UINTN       *CertLength

+  )

+{

+  MbedtlsPkcs7SignerInfo  *SignerInfo;

+  mbedtls_x509_crt        *Cert;

+  MbedtlsPkcs7            Pkcs7;

+  BOOLEAN                 Status;

+  UINT8                   *WrapData;

+  UINTN                   WrapDataSize;

+  BOOLEAN                 Wrapped;

+

+  UINTN  CertSize;

+  UINT8  Index;

+  UINT8  *CertBuf;

+  UINT8  *OldBuf;

+  UINTN  BufferSize;

+  UINTN  OldSize;

+

+  if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||

+      (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX))

+  {

+    return FALSE;

+  }

+

+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);

+

+  if (!Status) {

+    return FALSE;

+  }

+

+  Status  = FALSE;

+  CertBuf = NULL;

+  OldBuf  = NULL;

+  Cert    = NULL;

+

+  MbedTlsPkcs7Init (&Pkcs7);

+  if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) != 0) {

+    goto _Exit;

+  }

+

+  SignerInfo = &(Pkcs7.SignedData.SignerInfos);

+

+  //

+  // Traverse each signers

+  //

+  // Convert CertStack to buffer in following format:

+  // UINT8  CertNumber;

+  // UINT32 Cert1Length;

+  // UINT8  Cert1[];

+  // UINT32 Cert2Length;

+  // UINT8  Cert2[];

+  // ...

+  // UINT32 CertnLength;

+  // UINT8  Certn[];

+  //

+  BufferSize = sizeof (UINT8);

+  OldSize    = BufferSize;

+  Index      = 0;

+

+  while (SignerInfo != NULL) {

+    // Find signers cert

+    Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Certificates));

+    if (Cert == NULL) {

+      goto _Exit;

+    }

+

+    CertSize   = Cert->raw.len;

+    OldSize    = BufferSize;

+    OldBuf     = CertBuf;

+    BufferSize = OldSize + CertSize + sizeof (UINT32);

+

+    CertBuf = AllocateZeroPool (BufferSize);

+    if (CertBuf == NULL) {

+      goto _Exit;

+    }

+

+    if (OldBuf != NULL) {

+      CopyMem (CertBuf, OldBuf, OldSize);

+      free (OldBuf);

+      OldBuf = NULL;

+    }

+

+    WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize);

+    CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize);

+

+    Index++;

+

+    // move to next

+    SignerInfo = SignerInfo->Next;

+  }

+

+  if (CertBuf != NULL) {

+    //

+    // Update CertNumber.

+    //

+    CertBuf[0] = Index;

+

+    *CertLength  = BufferSize - OldSize - sizeof (UINT32);

+    *TrustedCert = AllocateZeroPool (*CertLength);

+    if (*TrustedCert == NULL) {

+      goto _Exit;

+    }

+

+    CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);

+    *CertStack   = CertBuf;

+    *StackLength = BufferSize;

+    Status       = TRUE;

+  }

+

+_Exit:

+  //

+  // Release Resources

+  //

+  if (!Status && (CertBuf != NULL)) {

+    FreePool (CertBuf);

+    *CertStack = NULL;

+  }

+

+  if (OldBuf != NULL) {

+    FreePool (OldBuf);

+  }

+

+  return Status;

+}

+

+/**

+  Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:

+  Cryptographic Message Syntax Standard", and outputs two certificate lists chained and

+  unchained to the signer's certificates.

+  The input signed data could be wrapped in a ContentInfo structure.

+

+  @param[in]  P7Data            Pointer to the PKCS#7 message.

+  @param[in]  P7Length          Length of the PKCS#7 message in bytes.

+  @param[out] SignerChainCerts  Pointer to the certificates list chained to signer's

+                                certificate. It's caller's responsibility to free the buffer

+                                with Pkcs7FreeSigners().

+                                This data structure is EFI_CERT_STACK type.

+  @param[out] ChainLength       Length of the chained certificates list buffer in bytes.

+  @param[out] UnchainCerts      Pointer to the unchained certificates lists. It's caller's

+                                responsibility to free the buffer with Pkcs7FreeSigners().

+                                This data structure is EFI_CERT_STACK type.

+  @param[out] UnchainLength     Length of the unchained certificates list buffer in bytes.

+

+  @retval  TRUE         The operation is finished successfully.

+  @retval  FALSE        Error occurs during the operation.

+

+**/

+BOOLEAN

+EFIAPI

+Pkcs7GetCertificatesList (

+  IN CONST UINT8  *P7Data,

+  IN UINTN        P7Length,

+  OUT UINT8       **SignerChainCerts,

+  OUT UINTN       *ChainLength,

+  OUT UINT8       **UnchainCerts,

+  OUT UINTN       *UnchainLength

+  )

+{

+  ASSERT (FALSE);

+  return FALSE;

+}

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
new file mode 100644
index 0000000000..23ea676373
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
@@ -0,0 +1,689 @@
+/** @file

+  This module verifies that Enhanced Key Usages (EKU's) are present within

+  a PKCS7 signature blob using MbedTLS.

+

+  Copyright (C) Microsoft Corporation. All Rights Reserved.

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

+

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

+

+**/

+

+#include <Base.h>

+#include "InternalCryptLib.h"

+#include <mbedtls/pkcs7.h>

+#include <mbedtls/asn1write.h>

+

+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  EkuOID[] = { 0x55, 0x1D, 0x25 };

+

+/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */

+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gBasicConstraintsCase1[] = { 0x30, 0x00 };

+

+/*leaf Cert basic_constraints case2: CA: false */

+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };

+

+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 };

+

+/**

+  Find first Extension data match with given OID

+

+  @param[in]      Start             Pointer to the DER-encoded extensions data

+  @param[in]      End               extensions data size in bytes

+  @param[in ]     Oid               OID for match

+  @param[in ]     OidSize           OID size in bytes

+  @param[out]     FindExtensionData output matched extension data.

+  @param[out]     FindExtensionDataLen matched extension data size.

+

+**/

+STATIC

+BOOLEAN

+InternalX509FindExtensionData (

+  UINT8        *Start,

+  UINT8        *End,

+  CONST UINT8  *Oid,

+  UINTN        OidSize,

+  UINT8        **FindExtensionData,

+  UINTN        *FindExtensionDataLen

+  )

+{

+  UINT8    *Ptr;

+  UINT8    *ExtensionPtr;

+  UINTN    ObjLen;

+  INT32    Ret;

+  BOOLEAN  Status;

+  UINTN    FindExtensionLen;

+  UINTN    HeaderLen;

+

+  /*If no Extension entry match Oid*/

+  Status = FALSE;

+  Ptr    = Start;

+

+  Ret = 0;

+

+  while (TRUE) {

+    //

+    // Extension  ::=  SEQUENCE  {

+    //     extnID      OBJECT IDENTIFIER,

+    //     critical    BOOLEAN DEFAULT FALSE,

+    //     extnValue   OCTET STRING  }

+    //

+    ExtensionPtr = Ptr;

+    Ret          = mbedtls_asn1_get_tag (

+                     &Ptr,

+                     End,

+                     &ObjLen,

+                     MBEDTLS_ASN1_CONSTRUCTED |

+                     MBEDTLS_ASN1_SEQUENCE

+                     );

+    if (Ret == 0) {

+      HeaderLen        = (UINTN)(Ptr - ExtensionPtr);

+      FindExtensionLen = ObjLen;

+      /* Get Object Identifier*/

+      Ret = mbedtls_asn1_get_tag (

+              &Ptr,

+              End,

+              &ObjLen,

+              MBEDTLS_ASN1_OID

+              );

+    } else {

+      break;

+    }

+

+    if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) {

+      Ptr += ObjLen;

+

+      Ret = mbedtls_asn1_get_tag (

+              &Ptr,

+              End,

+              &ObjLen,

+              MBEDTLS_ASN1_BOOLEAN

+              );

+      if (Ret == 0) {

+        Ptr += ObjLen;

+      }

+

+      Ret = mbedtls_asn1_get_tag (

+              &Ptr,

+              End,

+              &ObjLen,

+              MBEDTLS_ASN1_OCTET_STRING

+              );

+    } else {

+      Ret = 1;

+    }

+

+    if (Ret == 0) {

+      *FindExtensionData    = Ptr;

+      *FindExtensionDataLen = ObjLen;

+      Status                = TRUE;

+      break;

+    }

+

+    /* move to next*/

+    Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;

+    Ret = 0;

+  }

+

+  return Status;

+}

+

+/**

+  Retrieve Extension data from one X.509 certificate.

+

+  @param[in]      Cert             Pointer to the  X509 certificate.

+  @param[in]      Oid              Object identifier buffer

+  @param[in]      OidSize          Object identifier buffer size

+  @param[out]     ExtensionData    Extension bytes.

+  @param[in, out] ExtensionDataSize Extension bytes size.

+

+  @retval RETURN_SUCCESS           The certificate Extension data retrieved successfully.

+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.

+                                  If ExtensionDataSize is NULL.

+                                  If ExtensionData is not NULL and *ExtensionDataSize is 0.

+                                  If Certificate is invalid.

+  @retval RETURN_NOT_FOUND         If no Extension entry match Oid.

+  @retval RETURN_BUFFER_TOO_SMALL  If the ExtensionData is NULL. The required buffer size

+                                  is returned in the ExtensionDataSize parameter.

+  @retval RETURN_UNSUPPORTED       The operation is not supported.

+**/

+STATIC

+BOOLEAN

+GetExtensionData (

+  CONST mbedtls_x509_crt  *Cert,

+  CONST UINT8             *Oid,

+  UINTN                   OidSize,

+  UINT8                   *ExtensionData,

+  UINTN                   *ExtensionDataSize

+  )

+{

+  CONST mbedtls_x509_crt  *Crt;

+  INT32                   Ret;

+  BOOLEAN                 Status;

+  UINT8                   *Ptr;

+  UINT8                   *End;

+  UINTN                   ObjLen;

+

+  Ptr    = NULL;

+  End    = NULL;

+  ObjLen = 0;

+

+  if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) ||

+      (ExtensionDataSize == NULL))

+  {

+    return FALSE;

+  }

+

+  Status = FALSE;

+

+  Crt = Cert;

+

+  Ptr = Crt->v3_ext.p;

+  End = Crt->v3_ext.p + Crt->v3_ext.len;

+  Ret = mbedtls_asn1_get_tag (

+          &Ptr,

+          End,

+          &ObjLen,

+          MBEDTLS_ASN1_CONSTRUCTED |

+          MBEDTLS_ASN1_SEQUENCE

+          );

+

+  if (Ret == 0) {

+    Status = InternalX509FindExtensionData (

+               Ptr,

+               End,

+               Oid,

+               OidSize,

+               &Ptr,

+               &ObjLen

+               );

+  }

+

+  if (Status) {

+    if (*ExtensionDataSize < ObjLen) {

+      *ExtensionDataSize = ObjLen;

+      Status             = FALSE;

+      goto cleanup;

+    }

+

+    if (Oid != NULL) {

+      if (ExtensionData == NULL) {

+        return FALSE;

+      }

+

+      CopyMem (ExtensionData, Ptr, ObjLen);

+    }

+

+    *ExtensionDataSize = ObjLen;

+  } else {

+    *ExtensionDataSize = 0;

+  }

+

+cleanup:

+  return Status;

+}

+

+/**

+  Determines if the specified EKU represented in ASN1 form is present

+  in a given certificate.

+

+  @param[in]  Cert                  The certificate to check.

+  @param[in]  EKU                   The EKU to look for.

+  @param[in]  EkuLen                The size of EKU.

+

+  @retval EFI_SUCCESS               We successfully identified the signing type.

+  @retval EFI_INVALID_PARAMETER     A parameter was invalid.

+  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.

+

+**/

+STATIC

+EFI_STATUS

+IsEkuInCertificate (

+  IN CONST mbedtls_x509_crt  *Cert,

+  IN UINT8                   *EKU,

+  IN UINTN                   EkuLen

+  )

+{

+  EFI_STATUS  Status;

+  BOOLEAN     Ret;

+  UINT8       *Buffer;

+  UINTN       Index;

+  UINTN       Len;

+

+  if ((Cert == NULL) || (EKU == NULL)) {

+    Status = EFI_INVALID_PARAMETER;

+    goto Exit;

+  }

+

+  Len    = 0;

+  Buffer = NULL;

+  Ret    = GetExtensionData (

+             Cert,

+             (CONST UINT8 *)EkuOID,

+             sizeof (EkuOID),

+             NULL,

+             &Len

+             );

+  if (Len == 0) {

+    Status = EFI_NOT_FOUND;

+    goto Exit;

+  }

+

+  Buffer = AllocateZeroPool (Len);

+  if (Buffer == NULL) {

+    Status = EFI_NOT_FOUND;

+    goto Exit;

+  }

+

+  Ret = GetExtensionData (

+          Cert,

+          (CONST UINT8 *)EkuOID,

+          sizeof (EkuOID),

+          Buffer,

+          &Len

+          );

+

+  if ((Len == 0) || (!Ret)) {

+    Status = EFI_NOT_FOUND;

+    goto Exit;

+  }

+

+  Status = EFI_NOT_FOUND;

+  /*find the spdm hardware identity OID*/

+  for (Index = 0; Index <= Len - EkuLen; Index++) {

+    if (!CompareMem (Buffer + Index, EKU, EkuLen)) {

+      // check sub EKU

+      if (Index == Len - EkuLen) {

+        Status = EFI_SUCCESS;

+        break;

+        // Ensure that the OID is complete

+      } else if (Buffer[Index + EkuLen] == 0x06) {

+        Status = EFI_SUCCESS;

+        break;

+      } else {

+        break;

+      }

+    }

+  }

+

+Exit:

+  if (Buffer != NULL) {

+    FreePool (Buffer);

+  }

+

+  return Status;

+}

+

+/**

+  Get OID from txt.

+

+  @param[in]  RequiredEKUs         Array of null-terminated strings listing OIDs of

+                                   required EKUs that must be present in the signature.

+  @param[in]  RequiredEKUsSize     Number of elements in the RequiredEKUs string array.

+  @param[in,out]  CheckOid         OID.

+  @param[out]     OidLen           The size of OID.

+

+**/

+void

+GetOidFromTxt (

+  IN CONST CHAR8  *RequiredEKUs,

+  IN UINTN        RequiredEKUsSize,

+  IN OUT UINT8    *CheckOid,

+  OUT UINT8       *OidLen

+  )

+{

+  UINT8   *Ptr;

+  UINT16  Index;

+  UINT32  Data;

+  UINT8   OidIndex;

+  UINTN   EKUsSize;

+

+  EKUsSize = RequiredEKUsSize;

+  // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN

+  CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0'));

+

+  EKUsSize = EKUsSize - 4;

+  Ptr      = (UINT8 *)(RequiredEKUs + 4);

+

+  OidIndex = 1;

+

+  while (EKUsSize) {

+    Index = 0;

+    Data  = 0;

+

+    while ((*Ptr != '.') && (*Ptr != '\0')) {

+      Index++;

+      Ptr++;

+      EKUsSize--;

+    }

+

+    while (Index) {

+      Data = 10 * Data + (*(Ptr - Index) - '0');

+      Index--;

+    }

+

+    if (EKUsSize != 0) {

+      Ptr++;

+      EKUsSize--;

+    }

+

+    if (Data < 128) {

+      CheckOid[OidIndex] = (UINT8)Data;

+      OidIndex++;

+    } else {

+      CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF);

+      CheckOid[OidIndex]     = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF);

+      OidIndex               = OidIndex + 2;

+    }

+  }

+

+  *OidLen = OidIndex;

+}

+

+/**

+  Verify the Cert is signer cert

+

+  @param[in]  Start        Pointer to the DER-encoded certificate data Start.

+  @param[in]  End          Pointer to the DER-encoded certificate data End.

+

+  @retval  true            verify pass

+  @retval  false           verify fail

+**/

+STATIC

+BOOLEAN

+IsCertSignerCert (

+  UINT8  *Start,

+  UINT8  *End

+  )

+{

+  BOOLEAN           Status;

+  UINT8             *Buffer;

+  UINTN             Len;

+  mbedtls_x509_crt  Cert;

+  UINTN             ObjLen;

+

+  mbedtls_x509_crt_init (&Cert);

+

+  ObjLen = End - Start;

+

+  if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) {

+    return FALSE;

+  }

+

+  Len    = 0;

+  Buffer = NULL;

+  Status = GetExtensionData (

+             &Cert,

+             (CONST UINT8 *)gOidBasicConstraints,

+             sizeof (gOidBasicConstraints),

+             NULL,

+             &Len

+             );

+  if (Len == 0) {

+    /* basic constraints is not present in Cert */

+    return TRUE;

+  }

+

+  Buffer = AllocateZeroPool (Len);

+  if (Buffer == NULL) {

+    return FALSE;

+  }

+

+  Status = GetExtensionData (

+             &Cert,

+             (CONST UINT8 *)gOidBasicConstraints,

+             sizeof (gOidBasicConstraints),

+             Buffer,

+             &Len

+             );

+

+  if (Len == 0) {

+    /* basic constraints is not present in Cert */

+    Status = TRUE;

+    goto Exit;

+  } else if (!Status) {

+    Status = FALSE;

+    goto Exit;

+  }

+

+  if ((Len == sizeof (gBasicConstraintsCase1)) &&

+      (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1))))

+  {

+    Status = TRUE;

+    goto Exit;

+  }

+

+  if ((Len == sizeof (gBasicConstraintsCase2)) &&

+      (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2))))

+  {

+    Status = TRUE;

+    goto Exit;

+  }

+

+  Status = FALSE;

+

+Exit:

+  mbedtls_x509_crt_free (&Cert);

+

+  if (Buffer != NULL) {

+    FreePool (Buffer);

+  }

+

+  return Status;

+}

+

+/**

+  Determines if the specified EKUs are present in a signing certificate.

+

+  @param[in]  SignerCert            The certificate to check.

+  @param[in]  RequiredEKUs          The EKUs to look for.

+  @param[in]  RequiredEKUsSize      The number of EKUs

+  @param[in]  RequireAllPresent     If TRUE, then all the specified EKUs

+                                    must be present in the certificate.

+

+  @retval EFI_SUCCESS               We successfully identified the signing type.

+  @retval EFI_INVALID_PARAMETER     A parameter was invalid.

+  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.

+**/

+STATIC

+EFI_STATUS

+CheckEKUs (

+  IN CONST mbedtls_x509_crt  *SignerCert,

+  IN CONST CHAR8             *RequiredEKUs[],

+  IN CONST UINT32            RequiredEKUsSize,

+  IN BOOLEAN                 RequireAllPresent

+  )

+{

+  EFI_STATUS  Status;

+  UINT32      NumEkusFound;

+  UINT32      Index;

+  UINT8       *EKU;

+  UINTN       EkuLen;

+  UINT8       CheckOid[20];

+  UINT8       OidLen;

+

+  Status       = EFI_SUCCESS;

+  NumEkusFound = 0;

+

+  if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) {

+    Status = EFI_INVALID_PARAMETER;

+    goto Exit;

+  }

+

+  for (Index = 0; Index < RequiredEKUsSize; Index++) {

+    //

+    // Finding required EKU in Cert.

+    //

+    GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen);

+

+    EKU    = CheckOid;

+    EkuLen = OidLen;

+

+    Status = IsEkuInCertificate (SignerCert, EKU, EkuLen);

+    if (Status == EFI_SUCCESS) {

+      NumEkusFound++;

+      if (!RequireAllPresent) {

+        //

+        // Found at least one, so we are done.

+        //

+        goto Exit;

+      }

+    } else {

+      //

+      // Fail to find Eku in Cert

+      break;

+    }

+  }

+

+Exit:

+  if (RequireAllPresent &&

+      (NumEkusFound == RequiredEKUsSize))

+  {

+    //

+    // Found all required EKUs in certificate.

+    //

+    Status = EFI_SUCCESS;

+  }

+

+  return Status;

+}

+

+/**

+  This function receives a PKCS#7 formatted signature blob,

+  looks for the EKU SEQUENCE blob, and if found then looks

+  for all the required EKUs. This function was created so that

+  the Surface team can cut down on the number of Certificate

+  Authorities (CA's) by checking EKU's on leaf signers for

+  a specific product. This prevents one product's certificate

+  from signing another product's firmware or unlock blobs.

+

+  Note that this function does not validate the certificate chain.

+  That needs to be done before using this function.

+

+  @param[in]  Pkcs7Signature       The PKCS#7 signed information content block. An array

+                                   containing the content block with both the signature,

+                                   the signer's certificate, and any necessary intermediate

+                                   certificates.

+  @param[in]  Pkcs7SignatureSize   Number of bytes in Pkcs7Signature.

+  @param[in]  RequiredEKUs         Array of null-terminated strings listing OIDs of

+                                   required EKUs that must be present in the signature.

+  @param[in]  RequiredEKUsSize     Number of elements in the RequiredEKUs string array.

+  @param[in]  RequireAllPresent    If this is TRUE, then all of the specified EKU's

+                                   must be present in the leaf signer.  If it is

+                                   FALSE, then we will succeed if we find any

+                                   of the specified EKU's.

+

+  @retval EFI_SUCCESS              The required EKUs were found in the signature.

+  @retval EFI_INVALID_PARAMETER    A parameter was invalid.

+  @retval EFI_NOT_FOUND            One or more EKU's were not found in the signature.

+

+**/

+EFI_STATUS

+EFIAPI

+VerifyEKUsInPkcs7Signature (

+  IN CONST UINT8   *Pkcs7Signature,

+  IN CONST UINT32  SignatureSize,

+  IN CONST CHAR8   *RequiredEKUs[],

+  IN CONST UINT32  RequiredEKUsSize,

+  IN BOOLEAN       RequireAllPresent

+  )

+{

+  EFI_STATUS        Status;

+  mbedtls_x509_crt  Cert;

+  UINT8             *Ptr;

+  UINT8             *End;

+  INT32             Len;

+  UINTN             ObjLen;

+  UINT8             *OldEnd;

+

+  //

+  // Check input parameter.

+  //

+  if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) {

+    Status = EFI_INVALID_PARAMETER;

+    return Status;

+  }

+

+  mbedtls_x509_crt_init (&Cert);

+

+  Ptr = (UINT8 *)(UINTN)Pkcs7Signature;

+  Len = (UINT32)SignatureSize;

+  End = Ptr + Len;

+

+  // Cert

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {

+    return FALSE;

+  }

+

+  // tbscert

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {

+    return FALSE;

+  }

+

+  Ptr += ObjLen;

+  // signature algo

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {

+    return FALSE;

+  }

+

+  Ptr += ObjLen;

+  // signature

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {

+    return FALSE;

+  }

+

+  Ptr   += ObjLen;

+  OldEnd = Ptr;

+  // Cert

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {

+    return FALSE;

+  }

+

+  End = Ptr + ObjLen;

+

+  // leaf Cert

+  if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {

+    return FALSE;

+  }

+

+  Ptr += ObjLen;

+

+  while ((Ptr != End) && (Ptr < End)) {

+    if (IsCertSignerCert (OldEnd, Ptr)) {

+      break;

+    }

+

+    OldEnd = Ptr;

+    if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {

+      return FALSE;

+    }

+

+    Ptr += ObjLen;

+  }

+

+  if (Ptr != End) {

+    return FALSE;

+  } else {

+    Ptr = End - ObjLen;

+  }

+

+  // leaf Cert

+  ObjLen += Ptr - OldEnd;

+  Ptr     = OldEnd;

+

+  if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) {

+    return FALSE;

+  }

+

+  Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);

+  if (Status != EFI_SUCCESS) {

+    goto Exit;

+  }

+

+Exit:

+  //

+  // Release Resources

+  //

+  mbedtls_x509_crt_free (&Cert);

+

+  return Status;

+}

-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118072): https://edk2.groups.io/g/devel/message/118072
Mute This Topic: https://groups.io/mt/105552835/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* Re: [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls
  2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
                   ` (8 preceding siblings ...)
  2024-04-16  7:51 ` [edk2-devel] [PATCH 9/9] CryptoPkg: Add ImageTimestampVerify " Wenxing Hou
@ 2024-04-22  7:53 ` Li, Yi
  9 siblings, 0 replies; 12+ messages in thread
From: Li, Yi @ 2024-04-22  7:53 UTC (permalink / raw)
  To: Hou, Wenxing, devel@edk2.groups.io; +Cc: Yao, Jiewen

I found some magic number and format issues, please check comments in your PR.

Regards,
Yi

-----Original Message-----
From: Hou, Wenxing <wenxing.hou@intel.com> 
Sent: Tuesday, April 16, 2024 3:51 PM
To: devel@edk2.groups.io
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Li, Yi1 <yi1.li@intel.com>
Subject: [PATCH 0/9] Add more crypt APIs based on Mbedtls

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

Add AeadAesGcm/Pem(only RSA)/X509(only RSA)/More RSA/PKCS5 /pKCS7/Authenticode/Timestamp implementation based on Mbedtls.

The patch has passed the EDKII CI check:
https://github.com/tianocore/edk2/pull/5552

And the patch has passed unit_test in EDKII and integration test for platform.
And the patch hass passed the fuzz test:
https://github.com/tianocore/edk2-staging/commit/4f19398053c92e4f7791d468a184530b6ab89128

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>

Wenxing Hou (9):
  CryptoPkg: Add AeadAesGcm based on Mbedtls
  CryptoPkg: Add rand function for BaseCryptLibMbedTls
  CryptoPkg: Add Pem APIs based on Mbedtls
  CryptoPkg: Add X509 functions based on Mbedtls
  CryptoPkg: Add Pkcs7 related functions based on Mbedtls
  CryptoPkg: Add Pkcs5 functions based on Mbedtls
  CryptoPkg: Add more RSA related functions based on Mbedtls
  CryptoPkg: Add AuthenticodeVerify based on Mbedtls
  CryptoPkg: Add ImageTimestampVerify based on Mbedtls

 CryptoPkg/CryptoPkg.ci.yaml                   |    1 +
 .../Cipher/CryptAeadAesGcm.c                  |  227 ++
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |   49 +
 .../BaseCryptLibMbedTls/Pem/CryptPem.c        |  138 ++
 .../Pk/CryptAuthenticode.c                    |  214 ++
 .../BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c   |  278 +++
 .../BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c |  100 +
 .../Pk/CryptPkcs7Internal.h                   |   20 +-
 .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c   |  615 ++++++
 .../Pk/CryptPkcs7VerifyBase.c                 |  113 +
 .../Pk/CryptPkcs7VerifyCommon.c               | 1315 +++++++++++
 .../Pk/CryptPkcs7VerifyEku.c                  |  689 ++++++
 .../BaseCryptLibMbedTls/Pk/CryptRsaExt.c      |  346 +++
 .../BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c  |  137 ++  .../Library/BaseCryptLibMbedTls/Pk/CryptTs.c  |  381 ++++
 .../BaseCryptLibMbedTls/Pk/CryptX509.c        | 1924 +++++++++++++++++
 .../BaseCryptLibMbedTls/Rand/CryptRand.c      |  105 +
 .../BaseCryptLibMbedTls/Rand/CryptRandTsc.c   |  105 +
 18 files changed, 6745 insertions(+), 12 deletions(-)  create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
 create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c

--
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118073): https://edk2.groups.io/g/devel/message/118073
Mute This Topic: https://groups.io/mt/105552830/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

end of thread, other threads:[~2024-04-22  7:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-16  7:51 [edk2-devel] [PATCH 0/9] Add more crypt APIs based on Mbedtls Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 1/9] CryptoPkg: Add AeadAesGcm " Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 2/9] CryptoPkg: Add rand function for BaseCryptLibMbedTls Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 3/9] CryptoPkg: Add Pem APIs based on Mbedtls Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 4/9] CryptoPkg: Add X509 functions " Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 5/9] CryptoPkg: Add Pkcs7 related " Wenxing Hou
2024-04-22  7:52   ` Li, Yi
2024-04-16  7:51 ` [edk2-devel] [PATCH 6/9] CryptoPkg: Add Pkcs5 " Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 7/9] CryptoPkg: Add more RSA related " Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 8/9] CryptoPkg: Add AuthenticodeVerify " Wenxing Hou
2024-04-16  7:51 ` [edk2-devel] [PATCH 9/9] CryptoPkg: Add ImageTimestampVerify " Wenxing Hou
2024-04-22  7:53 ` [edk2-devel] [PATCH 0/9] Add more crypt APIs " Li, Yi

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