public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH RESEND v1 0/9] Add DrbgLib
@ 2022-06-29 19:18 PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 1/9] MdePkg/DrbgLib: Drbg library interface definition PierreGondois
                   ` (11 more replies)
  0 siblings, 12 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)

Add support for a Deterministic Random Bits Generator (Drbg). The
specifications used are the following:

- [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
	  for Random Number Generation Using Deterministic Random Bit Generators.
	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
- [2] NIST Special Publication 800-90B, Recommendation for the Entropy
	  Sources Used for Random Bit Generation.
	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
- [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
	  Random Bit Generator (RBG) Constructions.
	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
- [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
	  Recommendation for Key Management:Part 1 - General.

The test vectors available in the CTR_DRBG_AES256 sections of
https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/CTR_DRBG_noDF.pdf
were used for validation.

This patch-set can seen at:
https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1

This patch has the following dependency:
- [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG interface
  https://edk2.groups.io/g/devel/message/90845
- [PATCH v1 0/7] Add AesLib and ArmAesLib 
  https://edk2.groups.io/g/devel/message/90878

Pierre Gondois (9):
  MdePkg/DrbgLib: Drbg library interface definition
  MdePkg/DrbgLib: Add NULL instance of Drbg Library
  MdePkg/DrbgLib: Add BitStream implementation
  MdePkg/DrbgLib: Add Get_entropy_input() implementation
  MdePkg/DrbgLib: Add common wrappers
  MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
  MdePkg/DrbgLib: Add Drbg mechanism functions and module
  ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
  SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm

 ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
 MdePkg/Include/Library/DrbgLib.h              |  172 +++
 MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
 MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
 MdePkg/Library/DrbgLib/Common.c               |  249 ++++
 MdePkg/Library/DrbgLib/Common.h               |   74 ++
 MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
 MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
 MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
 MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
 MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
 MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
 MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
 MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
 MdePkg/MdePkg.dec                             |    4 +
 MdePkg/MdePkg.dsc                             |    2 +
 .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
 .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
 SecurityPkg/SecurityPkg.dsc                   |    2 +
 20 files changed, 4342 insertions(+), 1 deletion(-)
 create mode 100644 MdePkg/Include/Library/DrbgLib.h
 create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
 create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
 create mode 100644 MdePkg/Library/DrbgLib/Common.c
 create mode 100644 MdePkg/Library/DrbgLib/Common.h
 create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
 create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
 create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
 create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
 create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
 create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf

-- 
2.25.1


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

* [PATCH RESEND v1 1/9] MdePkg/DrbgLib: Drbg library interface definition
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 2/9] MdePkg/DrbgLib: Add NULL instance of Drbg Library PierreGondois
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

The NIST Special Publication 800-90A, 800-90B and 800-90C
details how to implement a Deterministic Random Bits Generator (DRBG).
Add a library interface definition for interacting with a Drbg.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 MdePkg/Include/Library/DrbgLib.h | 172 +++++++++++++++++++++++++++++++
 MdePkg/MdePkg.dec                |   4 +
 2 files changed, 176 insertions(+)
 create mode 100644 MdePkg/Include/Library/DrbgLib.h

diff --git a/MdePkg/Include/Library/DrbgLib.h b/MdePkg/Include/Library/DrbgLib.h
new file mode 100644
index 000000000000..aad46dbec228
--- /dev/null
+++ b/MdePkg/Include/Library/DrbgLib.h
@@ -0,0 +1,172 @@
+/** @file
+  DRBG library.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#ifndef DRBG_LIB_H_
+#define DRBG_LIB_H_
+
+/** Drbg Mechanisms.
+*/
+typedef enum {
+  DrbgMechansimHash = 0,        ///< Hash (not supported yet)
+  DrbgMechansimHmac,            ///< HMAC (not supported yet)
+  DrbgMechansimCtr,             ///< CTR
+  DrbgMechansimMax              ///< Maximum value.
+} DRBG_MECHANISM;
+
+/** Drbg Entropy sources.
+*/
+typedef enum {
+  /// Cf. [3] s10.3.3.1
+  /// Construction When a Conditioning Function is not Used
+  DrbgEntropyNoCondFn = 0,
+  /// Cf. [3] s10.3.3.2 (no supported yet)
+  /// Construction When a Vetted Conditioning Function is Used
+  /// and Full Entropy is Not Required)
+  DrbgEntropyNoFullEntropy,
+  /// Cf. [3] s10.3.3.3 (no supported yet)
+  /// Construction When a Vetted Conditioning Function is Used
+  /// to Obtain Full Entropy Bitstrings
+  DrbgEntropyFullEntropy,
+  /// Maximum value.
+  DrbgEntropyMax
+} DRBG_ENTROPY_SRC;
+
+/** Reseed a DRBG instance.
+
+  Implementation of Reseed_function.
+  Cf. [1] s9.2 'Reseeding a DRBG Instantiation'
+
+  @param  [in] PredResRequest   Indicates whether prediction resistance
+                                is to be provided during the request.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInput         An optional additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in, out] Handle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgReseedFn (
+  IN        BOOLEAN  PredResRequest,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN  OUT   VOID     *Handle
+  );
+
+/** Create a Drbg instance.
+
+  Implementation of Instantiate_function.
+  Cf. [1] s9.1 Instantiating a DRBG
+
+  @param  [in] DrbgMechanism    DRBG mechanism chosen.
+  @param  [in] DrbgEntropySrc   Entropy source chosen.
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                The security strenght granted can be different.
+  @param  [in] PredRes          Prediction resistance flag.
+                                If relevant, instantiate a DRBG that supports
+                                prediction resistance.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStr          Personnalization string.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStrLen       Personnalization string length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [out] HandlePtr   Pointer containting the created Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgInstantiateFn (
+  IN        DRBG_MECHANISM    DrbgMechanism,
+  IN        DRBG_ENTROPY_SRC  DrbgEntropySrc,
+  IN        UINTN             ReqSecStrength,
+  IN        BOOLEAN           PredRes,
+  IN  CONST CHAR8             *PersStr,
+  IN        UINTN             PersStrLen,
+  OUT       VOID              **HandlePtr
+  );
+
+/** Generate a random number.
+
+  Implementation of Generate_function.
+  Cf. [1] s9.3.1 The Generate Function
+
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] PredResReq       Request prediction resistance.
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] AddInput         Additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in] ReqNbBits        Number of random bits requested.
+  @param  [in, out] OutBuffer   If success, contains the random bits.
+                                The buffer must be at least ReqNbBits bits
+                                long.
+  @param  [in, out] Handle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgGenerateFn (
+  IN        UINTN    ReqSecStrength,
+  IN        BOOLEAN  PredResReq,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN        UINTN    ReqNbBits,
+  IN  OUT   UINT8    *OutBuffer,
+  IN  OUT   VOID     *Handle
+  );
+
+/** Remove a DRBG instance.
+
+  Implementation of Uninstantiate_function.
+  Cf. [1] s9.4 Removing a DRBG Instantiation
+
+  @param  [in, out] Handle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+DrbgUninstantiateFn (
+  IN  OUT VOID  *Handle
+  );
+
+#endif // DRBG_LIB_H_
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 078ae9323ba6..e96f875f1e91 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -284,6 +284,10 @@ [LibraryClasses]
   #
   AesLib|Include/Library/AesLib.h
 
+  ##  @libraryclass  A library to have a Deterministic Random Bits Generator (DRBG).
+  #
+  DrbgLib|Include/Library/DrbgLib.h
+
 [LibraryClasses.IA32, LibraryClasses.X64, LibraryClasses.AARCH64]
   ##  @libraryclass  Provides services to generate random number.
   #
-- 
2.25.1


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

* [PATCH RESEND v1 2/9] MdePkg/DrbgLib: Add NULL instance of Drbg Library
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 1/9] MdePkg/DrbgLib: Drbg library interface definition PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 3/9] MdePkg/DrbgLib: Add BitStream implementation PierreGondois
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

Add a Null instance of the DrbgLib satisfy potential
build dependencies issues.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
 MdePkg/Library/DrbgLibNull/DrbgLib.c       | 165 +++++++++++++++++++++
 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf |  21 +++
 MdePkg/MdePkg.dsc                          |   1 +
 3 files changed, 187 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
 create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf

diff --git a/MdePkg/Library/DrbgLibNull/DrbgLib.c b/MdePkg/Library/DrbgLibNull/DrbgLib.c
new file mode 100644
index 000000000000..e366843b03f0
--- /dev/null
+++ b/MdePkg/Library/DrbgLibNull/DrbgLib.c
@@ -0,0 +1,165 @@
+/** @file
+  Drbg library.
+  Cf. [1] s9 DRBG Mechanism Functions
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+  - [5] Unified Extensible Firmware Interface (UEFI) Specification,
+        Version 2.8 Errata B, May 2020
+        (https://www.uefi.org/specifications)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DrbgLib.h>
+
+/** Reseed a DRBG instance.
+
+  Implementation of Reseed_function.
+  Cf. [1] s9.2 'Reseeding a DRBG Instantiation'
+
+  @param  [in] PredResRequest   Indicates whether prediction resistance
+                                is to be provided during the request.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInput         An optional additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in, out] Handle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgReseedFn (
+  IN        BOOLEAN  PredResRequest,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN  OUT   VOID     *Handle
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
+/** Create a Drbg instance.
+
+  Implementation of Instantiate_function.
+  Cf. [1] s9.1 Instantiating a DRBG
+
+  @param  [in] DrbgMechanism    DRBG mechanism chosen.
+  @param  [in] DrbgEntropySrc   Entropy source chosen.
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                The security strenght granted can be different.
+  @param  [in] PredRes          Prediction resistance flag.
+                                If relevant, instantiate a DRBG that supports
+                                prediction resistance.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStr          Personnalization string.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStrLen       Personnalization string length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [out] HandlePtr   Pointer containting the created Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgInstantiateFn (
+  IN        DRBG_MECHANISM    DrbgMechanism,
+  IN        DRBG_ENTROPY_SRC  DrbgEntropySrc,
+  IN        UINTN             ReqSecStrength,
+  IN        BOOLEAN           PredRes,
+  IN  CONST CHAR8             *PersStr,
+  IN        UINTN             PersStrLen,
+  OUT       VOID              **HandlePtr
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
+/** Generate a random number.
+
+  Implementation of Generate_function.
+  Cf. [1] s9.3.1 The Generate Function
+
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] PredResReq       Request prediction resistance.
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] AddInput         Additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in] ReqNbBits        Number of random bits requested.
+  @param  [in, out] OutBuffer   If success, contains the random bits.
+                                The buffer must be at least ReqNbBits bits
+                                long.
+  @param  [in, out] Handle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgGenerateFn (
+  IN        UINTN    ReqSecStrength,
+  IN        BOOLEAN  PredResReq,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN        UINTN    ReqNbBits,
+  IN  OUT   UINT8    *OutBuffer,
+  IN  OUT   VOID     *Handle
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
+/** Remove a DRBG instance.
+
+  Implementation of Uninstantiate_function.
+  Cf. [1] s9.4 Removing a DRBG Instantiation
+
+  @param  [in, out] Handle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+DrbgUninstantiateFn (
+  IN  OUT VOID  *Handle
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
diff --git a/MdePkg/Library/DrbgLibNull/DrbgLibNull.inf b/MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
new file mode 100644
index 000000000000..6e17af4390fc
--- /dev/null
+++ b/MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
@@ -0,0 +1,21 @@
+## @file
+#  Drbg Null library
+#
+#  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001B
+  BASE_NAME      = DrbgLib
+  FILE_GUID      = B8A688E5-C31A-4CF8-9A76-B31211D292DE
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = DrbgLib
+
+[Sources]
+  DrbgLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index 726350c215e5..4820cecd0db8 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -69,6 +69,7 @@ [Components]
   MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
   MdePkg/Library/BaseTrngLibNull/BaseTrngLibNull.inf
   MdePkg/Library/AesLibNull/AesLibNull.inf
+  MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
 
   MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
   MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
-- 
2.25.1


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

* [PATCH RESEND v1 3/9] MdePkg/DrbgLib: Add BitStream implementation
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 1/9] MdePkg/DrbgLib: Drbg library interface definition PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 2/9] MdePkg/DrbgLib: Add NULL instance of Drbg Library PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 4/9] MdePkg/DrbgLib: Add Get_entropy_input() implementation PierreGondois
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

The Ctr Drbg does bitstream operations (additions, right/left
shifting, ...). To have a clearer implementation of the NIST
specifications, add a BitStream representation.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 MdePkg/Library/DrbgLib/BitStream.c | 1114 ++++++++++++++++++++++++++++
 MdePkg/Library/DrbgLib/BitStream.h |  366 +++++++++
 2 files changed, 1480 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
 create mode 100644 MdePkg/Library/DrbgLib/BitStream.h

diff --git a/MdePkg/Library/DrbgLib/BitStream.c b/MdePkg/Library/DrbgLib/BitStream.c
new file mode 100644
index 000000000000..1ae114fef803
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/BitStream.c
@@ -0,0 +1,1114 @@
+/** @file
+  BitStream utility.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+
+#include "BitStream.h"
+
+/** Check whether a BitStream is NULL (null length).
+
+  @param [in] Stream  The BitStream.
+
+  @retval TRUE if the BitStream is NULL (null length).
+  @retval FALSE otherwise.
+**/
+BOOLEAN
+EFIAPI
+IsBitStreamEmpty (
+  IN  BIT_STREAM  *Stream
+  )
+{
+  return ((Stream == NULL)       ||
+          (Stream->BitLen == 0)  ||
+          (Stream->Data == NULL));
+}
+
+/** Convert bits to bytes (rounds down).
+
+  @param [in] Bits    Bits.
+
+  @return Bytes.
+**/
+UINTN
+EFIAPI
+BitsToLowerBytes (
+  IN  UINTN  Bits
+  )
+{
+  return Bits >> 3;
+}
+
+/** Convert bits to bytes (rounds up).
+
+  @param [in] Bits    Bits.
+
+  @return Bytes.
+**/
+UINTN
+EFIAPI
+BitsToUpperBytes (
+  IN  UINTN  Bits
+  )
+{
+  return ((Bits + 0x7) >> 3);
+}
+
+/** Get the BitStream length (in bits).
+
+  @param [in] Stream    The BitStream.
+
+  @return Length of the BitStream (in bits).
+**/
+UINTN
+EFIAPI
+BitStreamBitLen (
+  IN  BIT_STREAM  *Stream
+  )
+{
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return 0;
+  }
+
+  return Stream->BitLen;
+}
+
+/** Get the BitStream length (in bytes).
+
+  @param [in] Stream    The BitStream.
+
+  @return Length of the BitStream (in bytes).
+**/
+UINTN
+EFIAPI
+BitStreamByteLen (
+  IN  BIT_STREAM  *Stream
+  )
+{
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return 0;
+  }
+
+  return Stream->ByteLen;
+}
+
+/** Get the BitStream data buffer.
+
+  @param [in] Stream    The BitStream.
+
+  @return Data buffer of the BitStream (can be NULL).
+**/
+UINT8 *
+EFIAPI
+BitStreamData (
+  IN  BIT_STREAM  *Stream
+  )
+{
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return 0;
+  }
+
+  return Stream->Data;
+}
+
+/** Clear the unsused bits of a Stream.
+
+  For instance, if a stream is 5 bits long, then:
+  - bits[7:5] must be cleared.
+  - bits[4:0] must be preserved.
+
+  @param [in, out]  Stream    The BitStream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BitStreamClearUnusedBits (
+  IN  OUT BIT_STREAM  *Stream
+  )
+{
+  UINT8  UsedBits;
+
+  if (IsBitStreamEmpty (Stream)) {
+    ASSERT (!IsBitStreamEmpty (Stream));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Clear the unsused bits of the Stream.
+  // BitStream are big-endian, so MSByte is at index 0.
+  UsedBits = Stream->BitLen & 0x7;
+  if (UsedBits != 0) {
+    Stream->Data[0] &= (0XFF >> (8 - UsedBits));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Allocate a buffer of BitLen (bits) for BitStream.
+
+  @param [in]   BitLen    Length of the buffer to allocate (in bits).
+  @param [out]  Stream    The BitStream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BitStreamShallowAlloc (
+  IN  UINTN       BitLen,
+  OUT BIT_STREAM  *Stream
+  )
+{
+  UINTN  ByteLen;
+
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (Stream, sizeof (BIT_STREAM));
+
+  if (BitLen == 0) {
+    return EFI_SUCCESS;
+  }
+
+  ByteLen      = BitsToUpperBytes (BitLen);
+  Stream->Data = (UINT8 *)AllocateZeroPool (ByteLen);
+  if (Stream->Data == NULL) {
+    ASSERT (Stream->Data != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Stream->BitLen  = BitLen;
+  Stream->ByteLen = ByteLen;
+
+  return EFI_SUCCESS;
+}
+
+/** Allocate a BitStream of BitLen (bits).
+
+  @param [in]   BitLen    Length of the BitStream (in bits).
+  @param [out]  Stream    The BitStream to allocate.
+                          Must be NULL initialized.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamAlloc (
+  IN  UINTN       BitLen,
+  OUT BIT_STREAM  **Stream
+  )
+{
+  EFI_STATUS  Status;
+  BIT_STREAM  *LocStream;
+
+  // Non NULL initialized pointers are considered invalid.
+  if ((Stream == NULL)  ||
+      (*Stream != NULL))
+  {
+    ASSERT (Stream != NULL);
+    ASSERT (*Stream == NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  LocStream = AllocateZeroPool (sizeof (BIT_STREAM));
+  if (LocStream == NULL) {
+    ASSERT (LocStream != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BitStreamShallowAlloc (BitLen, LocStream);
+  if (EFI_ERROR (Status)) {
+    FreePool (LocStream);
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  *Stream = LocStream;
+
+  return EFI_SUCCESS;
+}
+
+/** Free the buffer of the BitStream.
+
+  This is a shallow free, so the BitStream structure itself if not freed.
+
+  @param [in, out]  Stream  BitStream to free the buffer of.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BitStreamShallowFree (
+  IN  OUT BIT_STREAM  *Stream
+  )
+{
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Stream->Data != NULL) {
+    FreePool (Stream->Data);
+  }
+
+  ZeroMem (Stream, sizeof (BIT_STREAM));
+
+  return EFI_SUCCESS;
+}
+
+/** Free a BitStream.
+
+  @param [in, out]  Stream    BitStream to free.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamFree (
+  IN  OUT BIT_STREAM  **Stream
+  )
+{
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BitStreamShallowFree (*Stream);
+  FreePool (*Stream);
+  *Stream = NULL;
+
+  return EFI_SUCCESS;
+}
+
+/** Initialize a BitStream with a buffer.
+
+  The input Buffer is copied to a BitStream buffer.
+
+  @param [in]   Buffer    Buffer to init the Data of the BitStream with.
+                          The Buffer must be big-endian (MSByte at index 0).
+  @param [in]   BitLen    Length of the Buffer (in bits).
+  @param [out]  Stream    BitStream to initialize.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamInit (
+  IN  CONST UINT8       *Buffer,
+  IN        UINTN       BitLen,
+  OUT       BIT_STREAM  **Stream
+  )
+{
+  EFI_STATUS  Status;
+
+  // Non NULL initialized pointers are considered invalid.
+  if ((Stream == NULL)    ||
+      (*Stream != NULL)   ||
+      ((Buffer == NULL) ^ (BitLen == 0)))
+  {
+    ASSERT (Stream != NULL);
+    ASSERT (*Stream == NULL);
+    ASSERT (!((Buffer == NULL) ^ (BitLen == 0)));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = BitStreamAlloc (BitLen, Stream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // BitStream are big-endian, i.e. MSByte is at index 0,
+  // so just copy the input Buffer.
+  CopyMem ((*Stream)->Data, Buffer, (*Stream)->ByteLen);
+
+  return EFI_SUCCESS;
+}
+
+/** Fill a Buffer with a Stream Data.
+
+  The Buffer will be big-endian.
+
+  @param [in]   Stream  Stream to take the Data from.
+  @param [out]  Buffer  Buffer where to write the Data.
+                        Must be at least BitStreamByteLen (Stream)
+                        bytes long.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamToBuffer (
+  IN  BIT_STREAM  *Stream,
+  OUT UINT8       *Buffer
+  )
+{
+  if (IsBitStreamEmpty (Stream)  ||
+      (Buffer == NULL))
+  {
+    ASSERT (!IsBitStreamEmpty (Stream));
+    ASSERT (Buffer != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (Buffer, Stream->Data, Stream->ByteLen);
+
+  return EFI_SUCCESS;
+}
+
+/** Shallow clone a BitStream.
+
+  @param [out]  StreamDest    Shallow cloned BiStream.
+  @param [in]   StreamSrc     Source BitStream to shallow clone.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BitStreamShallowClone (
+  OUT BIT_STREAM  *StreamDest,
+  IN  BIT_STREAM  *StreamSrc
+  )
+{
+  if ((StreamDest == NULL)  ||
+      (StreamSrc == NULL))
+  {
+    ASSERT (StreamDest != NULL);
+    ASSERT (StreamSrc != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (StreamDest, StreamSrc, sizeof (BIT_STREAM));
+  return EFI_SUCCESS;
+}
+
+/** Clone a BitStream.
+
+  @param [out]  StreamDest    Cloned BiStream.
+  @param [in]   StreamSrc     Source BitStream to clone.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamClone (
+  OUT BIT_STREAM  **StreamDest,
+  IN  BIT_STREAM  *StreamSrc
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((StreamDest == NULL)  ||
+      (StreamSrc == NULL))
+  {
+    ASSERT (StreamDest != NULL);
+    ASSERT (StreamSrc != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = BitStreamInit (StreamSrc->Data, StreamSrc->BitLen, StreamDest);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // Fall through.
+  }
+
+  return Status;
+}
+
+/** Replace an initialized BitStream with another.
+
+  This function frees StreamRepl's Data if success.
+
+  @param [in, out]  StreamRepl    Stream whose content is replaced.
+  @param [in]       StreamData    Stream containing the Data to use.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamReplace (
+  IN  OUT BIT_STREAM  *StreamRepl,
+  IN      BIT_STREAM  *StreamData
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((StreamRepl == NULL)  ||
+      (StreamData == NULL))
+  {
+    ASSERT (StreamRepl != NULL);
+    ASSERT (StreamData != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = BitStreamShallowFree (StreamRepl);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  Status = BitStreamShallowClone (StreamRepl, StreamData);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // StreamRepl's content was freed. Can't do much now.
+    // Fall through.
+  }
+
+  return Status;
+}
+
+/** Write a buffer to a BitStream.
+
+  @param [in]       Buffer          Buffer to write to the BitStream.
+                                    Buffer is big-endian.
+  @param [in]       StartBitIndex   Bit index to start writing from.
+  @param [in]       BitCount        Count of bits to write.
+  @param [in, out]  Stream          BitStream to write to.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamWrite (
+  IN      UINT8       *Buffer,
+  IN      UINTN       StartBitIndex,
+  IN      UINTN       BitCount,
+  IN  OUT BIT_STREAM  *Stream
+  )
+{
+  UINTN  EndByteIndex;
+  UINTN  EndBitIndex;
+  UINT8  StartBitRemainder;
+  UINT8  EndBitRemainder;
+  UINT8  *Data;
+  UINT8  ShiftR;
+  UINT8  ShiftL;
+  UINT8  BitMask;
+  UINTN  ByteCount;
+
+  if (((Buffer != NULL) ^ (BitCount != 0))    ||
+      IsBitStreamEmpty (Stream)                ||
+      (StartBitIndex > (MAX_UINTN - BitCount))  ||
+      ((StartBitIndex + BitCount) > Stream->BitLen))
+  {
+    ASSERT (!((Buffer != NULL) ^ (BitCount != 0)));
+    ASSERT (!IsBitStreamEmpty (Stream));
+    ASSERT (StartBitIndex <= (MAX_UINTN - BitCount));
+    ASSERT ((StartBitIndex + BitCount) <= Stream->BitLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ByteCount = BitsToUpperBytes (BitCount);
+
+  if (BitCount == 0) {
+    // Nothing to do.
+    return EFI_SUCCESS;
+  }
+
+  EndByteIndex = Stream->ByteLen - 1 -
+                 BitsToLowerBytes (StartBitIndex + BitCount - 1);
+  EndBitIndex = StartBitIndex + BitCount;
+  Data        = &Stream->Data[EndByteIndex];
+
+  StartBitRemainder = StartBitIndex & 0x7;
+  EndBitRemainder   = EndBitIndex & 0x7;
+
+  ShiftL = StartBitRemainder;
+  ShiftR = 8 - ShiftL;
+
+  // BitCount might not be a multiple of 8. These MsBits can also
+  // be spread on 2 bytes (in StreamIn).
+  if ((StartBitRemainder < EndBitRemainder) || (EndBitRemainder == 0)) {
+    BitMask = 0xFF << StartBitRemainder;
+    if (EndBitRemainder != 0) {
+      BitMask ^= 0xFF << EndBitRemainder;
+    }
+
+    *Data = (*Data & ~BitMask) | ((*Buffer++ << ShiftL) & BitMask);
+
+    ByteCount--;
+    BitCount -= (BitCount & 0x7);
+
+    if (StartBitRemainder == 0) {
+      Data++;
+    }
+  } else if (StartBitRemainder > EndBitRemainder) {
+    BitMask = ~(0xFF << EndBitRemainder);
+    *Data   = (*Data & ~BitMask) | ((*Buffer >> ShiftR) & BitMask);
+    Data++;
+
+    BitMask = 0xFF << StartBitRemainder;
+    *Data   = (*Data & ~BitMask) | ((*Buffer++ << ShiftL) & BitMask);
+
+    ByteCount--;
+    BitCount -= (ShiftR + 8 - EndBitRemainder);
+  }
+
+  // else (StartBitRemainder == EndBitRemainder), nothing to do
+
+  // From here, (BitCount % 8) == 0 so we copy whole bytes from the Buffer.
+  // It doesn't mean we are byte-aligned, so check if the alignment of
+  // StartBitIndex.
+  if (ShiftL == 0) {
+    // StartBitIndex is byte aligned,
+    if (ByteCount) {
+      CopyMem (Data, Buffer, ByteCount);
+    }
+  } else {
+    // StartBitIndex is not byte aligned.
+    BitMask = 0xFF << (StartBitIndex & 0x7);
+    while (ByteCount--) {
+      *Data = (*Data & BitMask) | ((*Buffer >> ShiftR) & ~BitMask);
+      Data++;
+      *Data = (*Data & ~BitMask) | ((*Buffer++ << ShiftL) & BitMask);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** XoR two BitStreams.
+
+  We must have len(StremA) = len(StreamB)
+
+  @param [in]  StreamA   BitStream A.
+  @param [in]  StreamB   BitStream B.
+  @param [out] StreamOut Output BitStream.
+                         Can be *StreamA or *StreamB to replace their
+                         content with the new stream.
+                         Otherwise, it is initialized and contains the
+                         resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamXor (
+  IN  BIT_STREAM  *StreamA,
+  IN  BIT_STREAM  *StreamB,
+  OUT BIT_STREAM  **StreamOut
+  )
+{
+  EFI_STATUS  Status;
+  BIT_STREAM  *LocStream;
+  UINTN       ByteLen;
+  UINTN       *DataLocN;
+  UINT8       *DataLoc8;
+  UINTN       *DataAN;
+  UINT8       *DataA8;
+  UINTN       *DataBN;
+  UINT8       *DataB8;
+  UINTN       ByteLenN;
+  UINTN       ByteLen8;
+  UINTN       Offset;
+
+  if ((StreamA == NULL)     ||
+      (StreamB == NULL)     ||
+      (StreamOut == NULL)   ||
+      (StreamA->BitLen != StreamB->BitLen))
+  {
+    ASSERT (StreamA != NULL);
+    ASSERT (StreamB != NULL);
+    ASSERT (StreamOut != NULL);
+    ASSERT (StreamA->BitLen == StreamB->BitLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (StreamB->BitLen == 0) {
+    // Nothing to do.
+    return EFI_SUCCESS;
+  }
+
+  if (*StreamOut == StreamA) {
+    LocStream = StreamA;
+  } else if (*StreamOut == StreamB) {
+    LocStream = StreamB;
+  } else {
+    LocStream = NULL;
+
+    Status = BitStreamAlloc (StreamA->BitLen, &LocStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+  }
+
+  ByteLen = StreamA->ByteLen;
+
+  DataLocN = (UINTN *)LocStream->Data;
+  DataAN   = (UINTN *)StreamA->Data;
+  DataBN   = (UINTN *)StreamB->Data;
+  // Speed up the process by taking chunks of UINTN instead of UINT8.
+  // ((sizeof (UINTN) >> 2) + 1) is 3 or 2 depending on the size of UINTN.
+  ByteLenN = ByteLen >> (((sizeof (UINTN) >> 2) + 1));
+  ByteLen8 = ByteLen & ((sizeof (UINTN) - 1));
+  while (ByteLenN-- > 0) {
+    DataLocN[ByteLenN] = DataAN[ByteLenN] ^ DataBN[ByteLenN];
+  }
+
+  // XOR remaining UINT8 chunks.
+  if (ByteLen8 != 0) {
+    Offset   = ByteLen - ByteLen8;
+    DataLoc8 = (UINT8 *)DataLocN + Offset;
+    DataA8   = (UINT8 *)DataAN + Offset;
+    DataB8   = (UINT8 *)DataBN + Offset;
+    while (ByteLen8-- > 0) {
+      DataLoc8[ByteLen8] = DataA8[ByteLen8] ^ DataB8[ByteLen8];
+    }
+  }
+
+  *StreamOut = LocStream;
+  return EFI_SUCCESS;
+}
+
+/** Concatenate two BitStreams.
+
+  @param [in]  StreamHigh  BitStream containing the MSBytes.
+  @param [in]  StreamLow   BitStream containing the LSBytes.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamHigh or *StreamLow to replace their
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamConcat (
+  IN  BIT_STREAM  *StreamHigh,
+  IN  BIT_STREAM  *StreamLow,
+  OUT BIT_STREAM  **StreamOut
+  )
+{
+  EFI_STATUS  Status;
+  BIT_STREAM  LocStream;
+  UINTN       TotalBitLen;
+
+  if ((StreamHigh == NULL)  ||
+      (StreamLow == NULL)   ||
+      (StreamOut == NULL))
+  {
+    ASSERT (StreamHigh != NULL);
+    ASSERT (StreamLow != NULL);
+    ASSERT (StreamOut != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TotalBitLen = StreamHigh->BitLen + StreamLow->BitLen;
+
+  Status = BitStreamShallowAlloc (TotalBitLen, &LocStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // Write StreamLow data.
+  Status = BitStreamWrite (
+             StreamLow->Data,
+             0,
+             StreamLow->BitLen,
+             &LocStream
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ErrorHandler;
+  }
+
+  // Write StreamHigh data.
+  Status = BitStreamWrite (
+             StreamHigh->Data,
+             StreamLow->BitLen,
+             StreamHigh->BitLen,
+             &LocStream
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ErrorHandler;
+  }
+
+  if (*StreamOut == StreamHigh) {
+    Status = BitStreamReplace (StreamHigh, &LocStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+  } else if (*StreamOut == StreamLow) {
+    Status = BitStreamReplace (StreamLow, &LocStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+  } else {
+    Status = BitStreamClone (StreamOut, &LocStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+  }
+
+  return Status;
+
+ErrorHandler:
+  BitStreamShallowFree (&LocStream);
+  return Status;
+}
+
+/** Select bits in a BitStream.
+
+  @param [in]   StreamIn        Input BitStream.
+  @param [in]   StartBitIndex   Bit index to start the copy from.
+  @param [in]   BitCount        Count of bits to copy.
+  @param [out]  StreamOut       Output BitStream.
+                                Can be *StreamIn to replace its
+                                content with the new concatenated stream.
+                                Otherwise, it is initialized and contains the
+                                resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamSelect (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       StartBitIndex,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  )
+{
+  EFI_STATUS  Status;
+  BIT_STREAM  StreamDest;
+  UINTN       ByteCount;
+  UINTN       EndByteIndex;
+  UINTN       EndBitCountRemainder;
+  UINT8       *DataDest;
+  UINT8       *DataIn;
+  UINT8       ShiftR;
+  UINT8       ShiftL;
+
+  if ((StreamIn == NULL)                              ||
+      (StartBitIndex > (MAX_UINTN - BitCount))        ||
+      ((StartBitIndex + BitCount) > StreamIn->BitLen) ||
+      (StreamOut == NULL))
+  {
+    ASSERT (StreamIn != NULL);
+    ASSERT (StartBitIndex <= (MAX_UINTN - BitCount));
+    ASSERT ((StartBitIndex + BitCount) <= StreamIn->BitLen);
+    ASSERT (StreamOut != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BitCount == 0) {
+    if (*StreamOut == StreamIn) {
+      Status = BitStreamShallowAlloc (0, &StreamDest);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        return Status;
+      }
+
+      Status = BitStreamReplace (StreamIn, &StreamDest);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        BitStreamShallowFree (&StreamDest);
+        // Fall through.
+      }
+    } else {
+      Status = BitStreamAlloc (0, StreamOut);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        // Fall through.
+      }
+    }
+
+    return Status;
+  }
+
+  ByteCount = BitsToUpperBytes (BitCount);
+
+  // Alloc StreamDest.
+  Status = BitStreamShallowAlloc (BitCount, &StreamDest);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  DataDest = StreamDest.Data;
+
+  EndByteIndex = StreamIn->ByteLen - 1 -
+                 BitsToLowerBytes (StartBitIndex + BitCount - 1);
+  DataIn = &StreamIn->Data[EndByteIndex];
+
+  ShiftR = StartBitIndex & 0x7;
+  if (ShiftR == 0) {
+    // StartBitIndex is byte aligned.
+    CopyMem (DataDest, DataIn, ByteCount);
+    // Unused bits are cleared later.
+  } else {
+    // StartBitIndex is not byte aligned.
+    ShiftL = 8 - ShiftR;
+
+    // BitCount might not be a multiple of 8. These MsBits can also
+    // be spread on 2 bytes (in StreamIn).
+    EndBitCountRemainder = BitCount & 0x7;
+    if ((ShiftR <= EndBitCountRemainder) || (EndBitCountRemainder == 0)) {
+      *DataDest |= (*DataIn++ << ShiftL);
+    }
+
+    *DataDest++ |= (*DataIn >> ShiftR);
+    ByteCount   -= 1;
+
+    // Then copy 8 bits chunks.
+    while (ByteCount--) {
+      *DataDest   |= (*DataIn++ << ShiftL);
+      *DataDest++ |= (*DataIn >> ShiftR);
+    }
+  }
+
+  Status = BitStreamClearUnusedBits (&StreamDest);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ErrorHandler;
+  }
+
+  if (*StreamOut == StreamIn) {
+    Status = BitStreamReplace (StreamIn, &StreamDest);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+  } else {
+    Status = BitStreamClone (StreamOut, &StreamDest);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      // Fall through.
+    }
+  }
+
+  return Status;
+
+ErrorHandler:
+  BitStreamShallowFree (&StreamDest);
+  return Status;
+}
+
+/** Get leftmost (i.e. MSBytes) BitLen bits of a BitStream.
+
+  @param [in]  StreamIn    Input BitStream.
+  @param [in]  BitCount    Count of leftmost bits to copy.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamIn to replace its
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamLeftmost (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  )
+{
+  if ((StreamIn == NULL)    ||
+      (BitCount > StreamIn->BitLen))
+  {
+    ASSERT (StreamIn != NULL);
+    ASSERT (BitCount <= StreamIn->BitLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return BitStreamSelect (
+           StreamIn,
+           StreamIn->BitLen - BitCount,
+           BitCount,
+           StreamOut
+           );
+}
+
+/** Get rightmost (i.e. LSBytes) BitLen bits of a BitStream.
+
+  @param [in]  StreamIn    Input BitStream.
+  @param [in]  BitCount    Count of righttmost bits to copy.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamIn to replace its
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamRightmost (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  )
+{
+  return BitStreamSelect (StreamIn, 0, BitCount, StreamOut);
+}
+
+/** Add a value modulo 2^n to a BitStream.
+
+  @param [in]       Val       Value to add.
+  @param [in]       Modulo    Modulo of the addition (2^Modulo).
+  @param [in, out]  Stream    BitStream where the addition happens.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamAddModulo (
+  IN      UINTN       Val,
+  IN      UINTN       Modulo,
+  IN  OUT BIT_STREAM  *Stream
+  )
+{
+  UINTN  Index;
+  UINTN  ByteLen;
+  UINT8  Carry;
+  UINT8  Trunc8Val;
+  UINT8  *Data;
+
+  if (IsBitStreamEmpty (Stream)   ||
+      (Stream->BitLen != Modulo))
+  {
+    // Additions with BitLen != Modulo are not handled for now.
+    ASSERT (!IsBitStreamEmpty (Stream));
+    ASSERT (Stream->BitLen == Modulo);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Index   = 0;
+  ByteLen = Stream->ByteLen;
+  while ((Val != 0) && (Index < ByteLen)) {
+    Data = &Stream->Data[ByteLen - Index - 1];
+
+    // Only check for 8-bits overflow. If we exit the loop with Carry == 1,
+    // then this was an actual addition modulo X.
+    // [1-7]-bits overflows are cleared with BitStreamClearUnusedBits().
+    Trunc8Val = (UINT8)Val;
+    Carry     = (*Data > MAX_UINT8 - Trunc8Val) ? 1 : 0;
+    *Data    += Trunc8Val;
+
+    Val >>= 8;
+    Val  += Carry;
+
+    Index++;
+  }
+
+  return BitStreamClearUnusedBits (Stream);
+}
+
+/** Print a BitStream.
+
+  @param [in]   Stream    Stream to print.
+**/
+VOID
+EFIAPI
+BitStreamPrint (
+  IN  BIT_STREAM  *Stream
+  )
+{
+  UINTN  ByteLen;
+  UINTN  Index;
+  UINT8  HeadBits;
+  UINT8  Data;
+  UINT8  Bit;
+
+  if (Stream == NULL) {
+    ASSERT (Stream != NULL);
+    return;
+  }
+
+  HeadBits = Stream->BitLen & 0x7;
+  ByteLen  = Stream->ByteLen;
+  Print (L"BitStream(%lu): {\n", Stream->BitLen);
+  Print (L"  [Index]     < 7 6 5 4 3 2 1 0 >\n");
+
+  if (Stream->BitLen == 0) {
+    return;
+  }
+
+  // Print most significant byte.
+  Data = Stream->Data[0];
+
+  Print (L"  [%02lu] (0x%02x) <", ByteLen - 1, Data);
+  for (Index = 7; Index >= 0; Index--) {
+    if ((Index >= HeadBits) && (HeadBits != 0)) {
+      Bit = 'x';
+    } else {
+      Bit = '0' + ((Data & (1 << Index)) >> Index);
+    }
+
+    Print (L" %c", Bit);
+  }
+
+  Print (L" >\n");
+
+  // Print other bytes.
+  for (Index = 1; Index < ByteLen; Index++) {
+    Data = Stream->Data[Index];
+    Print (
+      L"  [%02ld] (0x%02x) < %d %d %d %d %d %d %d %d >\n",
+      ByteLen - Index - 1,
+      Data,
+      Data >> 7,
+      (Data & 0x40) >> 6,
+      (Data & 0x20) >> 5,
+      (Data & 0x10) >> 4,
+      (Data & 0x8) >> 3,
+      (Data & 0x4) >> 2,
+      (Data & 0x2) >> 1,
+      (Data & 0x1)
+      );
+  }
+
+  Print (L"}\n");
+}
diff --git a/MdePkg/Library/DrbgLib/BitStream.h b/MdePkg/Library/DrbgLib/BitStream.h
new file mode 100644
index 000000000000..6f0c7732b2a5
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/BitStream.h
@@ -0,0 +1,366 @@
+/** @file
+  BitStream utility.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef BIT_STREAM_H_
+#define BIT_STREAM_H_
+
+/** BitStream.
+
+  Struct holding a buffer of data and allowing to do operations
+  on them (concatenation, selecting rightmost bits, addition, ...).
+  BitStream are big-endian (MSByte at index 0).
+*/
+typedef struct BitStream {
+  /// Length of BitStream in bits.
+  UINTN    BitLen;
+  /// Length of BitStream in bytes.
+  UINTN    ByteLen;
+  /// Buffer holding the data.
+  UINT8    *Data;
+} BIT_STREAM;
+
+/** Check whether a BitStream is NULL (null length).
+
+  @param [in] Stream  The BitStream.
+
+  @retval TRUE if the BitStream is NULL (null length).
+  @retval FALSE otherwise.
+**/
+BOOLEAN
+EFIAPI
+IsBitStreamEmpty (
+  IN  BIT_STREAM  *Stream
+  );
+
+/** Convert bits to bytes (rounds down).
+
+  @param [in] Bits    Bits.
+
+  @return Bytes.
+**/
+UINTN
+EFIAPI
+BitsToLowerBytes (
+  IN  UINTN  Bits
+  );
+
+/** Convert bits to bytes (rounds up).
+
+  @param [in] Bits    Bits.
+
+  @return Bytes.
+**/
+UINTN
+EFIAPI
+BitsToUpperBytes (
+  IN  UINTN  Bits
+  );
+
+/** Get the BitStream length (in bits).
+
+  @param [in] Stream    The BitStream.
+
+  @return Length of the BitStream (in bits).
+**/
+UINTN
+EFIAPI
+BitStreamBitLen (
+  IN  BIT_STREAM  *Stream
+  );
+
+/** Get the BitStream length (in bytes).
+
+  @param [in] Stream    The BitStream.
+
+  @return Length of the BitStream (in bytes).
+**/
+UINTN
+EFIAPI
+BitStreamByteLen (
+  IN  BIT_STREAM  *Stream
+  );
+
+/** Get the BitStream data buffer.
+
+  @param [in] Stream    The BitStream.
+
+  @return Data buffer of the BitStream (can be NULL).
+**/
+UINT8 *
+EFIAPI
+BitStreamData (
+  IN  BIT_STREAM  *Stream
+  );
+
+/** Allocate a BitStream of BitLen (bits).
+
+  @param [in]   BitLen    Length of the BitStream (in bits).
+  @param [out]  Stream    The BitStream to allocate.
+                          Must be NULL initialized.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamAlloc (
+  IN  UINTN       BitLen,
+  OUT BIT_STREAM  **Stream
+  );
+
+/** Free a BitStream.
+
+  @param [in, out]  Stream    BitStream to free.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamFree (
+  IN  OUT BIT_STREAM  **Stream
+  );
+
+/** Initialize a BitStream with a buffer.
+
+  The input Buffer is copied to a BitStream buffer.
+
+  @param [in]   Buffer    Buffer to init the Data of the BitStream with.
+                          The Buffer must be big-endian (MSByte at index 0).
+  @param [in]   BitLen    Length of the Buffer (in bits).
+  @param [out]  Stream    BitStream to initialize.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamInit (
+  IN  CONST UINT8       *Buffer,
+  IN        UINTN       BitLen,
+  OUT       BIT_STREAM  **Stream
+  );
+
+/** Fill a Buffer with a Stream Data.
+
+  The Buffer will be big-endian.
+
+  @param [in]   Stream  Stream to take the Data from.
+  @param [out]  Buffer  Buffer where to write the Data.
+                        Must be at least BitStreamByteLen (Stream)
+                        bytes long.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamToBuffer (
+  IN  BIT_STREAM  *Stream,
+  OUT UINT8       *Buffer
+  );
+
+/** Clone a BitStream.
+
+  @param [out]  StreamDest    Cloned BiStream.
+  @param [in]   StreamSrc     Source BitStream to clone.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamClone (
+  OUT BIT_STREAM  **StreamDest,
+  IN  BIT_STREAM  *StreamSrc
+  );
+
+/** Replace an initialized BitStream with another.
+
+  This function frees StreamRepl's Data if success.
+
+  @param [out]  StreamRepl    Stream whose content is replaced.
+  @param [in]   StreamData    Stream containing the Data to use.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamReplace (
+  IN  OUT BIT_STREAM  *StreamRepl,
+  IN      BIT_STREAM  *StreamData
+  );
+
+/** Write a buffer to a BitStream.
+
+  @param [in]       Buffer          Buffer to write to the BitStream.
+                                    Buffer is big-endian.
+  @param [in]       StartBitIndex   Bit index to start writing from.
+  @param [in]       BitCount        Count of bits to write.
+  @param [in, out]  Stream          BitStream to write to.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamWrite (
+  IN      UINT8       *Buffer,
+  IN      UINTN       StartBitIndex,
+  IN      UINTN       BitCount,
+  IN  OUT BIT_STREAM  *Stream
+  );
+
+/** XoR two BitStreams.
+
+  We must have len(StremA) = len(StreamB)
+
+  @param [in]  StreamA   BitStream A.
+  @param [in]  StreamB   BitStream B.
+  @param [out] StreamOut Output BitStream.
+                         Can be *StreamA or *StreamB to replace their
+                         content with the new stream.
+                         Otherwise, it is initialized and contains the
+                         resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamXor (
+  IN  BIT_STREAM  *StreamA,
+  IN  BIT_STREAM  *StreamB,
+  OUT BIT_STREAM  **StreamOut
+  );
+
+/** Concatenate two BitStreams.
+
+  @param [in]  StreamHigh  BitStream containing the MSBytes.
+  @param [in]  StreamLow   BitStream containing the LSBytes.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamHigh or *StreamLow to replace their
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamConcat (
+  IN  BIT_STREAM  *StreamHigh,
+  IN  BIT_STREAM  *StreamLow,
+  OUT BIT_STREAM  **StreamOut
+  );
+
+/** Select bits in a BitStream.
+
+  @param [in]   StreamIn        Input BitStream.
+  @param [in]   StartBitIndex   Bit index to start the copy from.
+  @param [in]   BitCount        Count of bits to copy.
+  @param [out]  StreamOut       Output BitStream.
+                                Can be *StreamIn to replace its
+                                content with the new concatenated stream.
+                                Otherwise, it is initialized and contains the
+                                resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamSelect (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       StartBitIndex,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  );
+
+/** Get leftmost (i.e. MSBytes) BitLen bits of a BitStream.
+
+  @param [in]  StreamIn    Input BitStream.
+  @param [in]  BitCount    Count of leftmost bits to copy.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamIn to replace its
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamLeftmost (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  );
+
+/** Get rightmost (i.e. LSBytes) BitLen bits of a BitStream.
+
+  @param [in]  StreamIn    Input BitStream.
+  @param [in]  BitCount    Count of righttmost bits to copy.
+  @param [out] StreamOut   Output BitStream.
+                           Can be *StreamIn to replace its
+                           content with the new concatenated stream.
+                           Otherwise, it is initialized and contains the
+                           resulting stream.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamRightmost (
+  IN  BIT_STREAM  *StreamIn,
+  IN  UINTN       BitCount,
+  OUT BIT_STREAM  **StreamOut
+  );
+
+/** Add a value modulo 2^n to a BitStream.
+
+  @param [in]       Val       Value to add.
+  @param [in]       Modulo    Modulo of the addition (2^Modulo).
+  @param [in, out]  Stream    BitStream where the addition happens.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BitStreamAddModulo (
+  IN      UINTN       Val,
+  IN      UINTN       Modulo,
+  IN  OUT BIT_STREAM  *Stream
+  );
+
+/** Print a BitStream.
+
+  @param [in]   Stream    Stream to print.
+**/
+VOID
+EFIAPI
+BitStreamPrint (
+  IN  BIT_STREAM  *Stream
+  );
+
+#endif // BIT_STREAM_H_
-- 
2.25.1


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

* [PATCH RESEND v1 4/9] MdePkg/DrbgLib: Add Get_entropy_input() implementation
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (2 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 3/9] MdePkg/DrbgLib: Add BitStream implementation PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 5/9] MdePkg/DrbgLib: Add common wrappers PierreGondois
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

NIST Special Publication 800-90C, s10.3.3 'Get_entropy_input
Constructions for Accessing Entropy Sources'
specifies multiple way to implement the Get_entropy_input()
function.

Implement s10.3.3.1 'Construction When a Conditioning Function
is not Used' in a separate file to let room for other potential
implementations.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
 MdePkg/Library/DrbgLib/GetEntropyInput.c | 72 ++++++++++++++++++++++++
 MdePkg/Library/DrbgLib/GetEntropyInput.h | 48 ++++++++++++++++
 2 files changed, 120 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
 create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h

diff --git a/MdePkg/Library/DrbgLib/GetEntropyInput.c b/MdePkg/Library/DrbgLib/GetEntropyInput.c
new file mode 100644
index 000000000000..6257bc9093dd
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/GetEntropyInput.c
@@ -0,0 +1,72 @@
+/** @file
+  GetEntropyInput function implementation.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#include "Common.h"
+
+/** GetEntropyInput implementation (no conditionning function).
+
+  Cf. [3] 10.3.3.1 Construction When a Conditioning Function is not Used
+
+  @param [in]   DrbgHandle        The Drbg hanble.
+  @param [in]   MinEntropy        Minimum entropy.
+  @param [out]  EntropyBitsStream Stream containing the generated entropy.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetEntropyInputNoCondFn (
+  IN  DRBG_HANDLE  DrbgHandle,
+  IN  UINTN        MinEntropy,
+  OUT BIT_STREAM   **EntropyBitsStream
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((DrbgHandle == NULL)          ||
+      (EntropyBitsStream == NULL)   ||
+      (*EntropyBitsStream != NULL))
+  {
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (EntropyBitsStream != NULL);
+    ASSERT (*EntropyBitsStream == NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 1. (status, entropy_bitstring) = Get_Entropy(min_entropy, max_length).
+  // 2. If (status != SUCCESS), then return (status, Null).
+  // 3. Return SUCCESS, entropy_bitstring.
+  Status = GetEntropy (DrbgHandle, MinEntropy, EntropyBitsStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // Fall through.
+  }
+
+  return Status;
+}
diff --git a/MdePkg/Library/DrbgLib/GetEntropyInput.h b/MdePkg/Library/DrbgLib/GetEntropyInput.h
new file mode 100644
index 000000000000..336fbc3826c0
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/GetEntropyInput.h
@@ -0,0 +1,48 @@
+/** @file
+  GetEntropyInput function implementation.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#ifndef GET_ENTROPY_INPUT_H_
+#define GET_ENTROPY_INPUT_H_
+
+/** GetEntropyInput implementation (no conditionning function).
+
+  Cf. [3] 10.3.3.1 Construction When a Conditioning Function is not Used
+
+  @param [in]   DrbgHandle        The Drbg hanble.
+  @param [in]   MinEntropy        Minimum entropy.
+  @param [out]  EntropyBitsStream Stream containing the generated entropy.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetEntropyInputNoCondFn (
+  IN  DRBG_HANDLE  DrbgHandle,
+  IN  UINTN        MinEntropy,
+  OUT BIT_STREAM   **EntropyBitsStream
+  );
+
+#endif // GET_ENTROPY_INPUT_H_
-- 
2.25.1


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

* [PATCH RESEND v1 5/9] MdePkg/DrbgLib: Add common wrappers
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (3 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 4/9] MdePkg/DrbgLib: Add Get_entropy_input() implementation PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 6/9] MdePkg/DrbgLib: Add Ctr Drbg mechanism functions PierreGondois
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

Add common wrappers around the TRNG and AES libraries:
 - GetEntropy() relies an Arm Trng
 - BlockEncrypt relies on Arm implementation of the AES library

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 MdePkg/Library/DrbgLib/Common.c | 249 ++++++++++++++++++++++++++++++++
 MdePkg/Library/DrbgLib/Common.h |  74 ++++++++++
 2 files changed, 323 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLib/Common.c
 create mode 100644 MdePkg/Library/DrbgLib/Common.h

diff --git a/MdePkg/Library/DrbgLib/Common.c b/MdePkg/Library/DrbgLib/Common.c
new file mode 100644
index 000000000000..0aa0459f0b0f
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/Common.c
@@ -0,0 +1,249 @@
+/** @file
+  Implementation of arch specific functions for the Drbg library.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#include <Library/AesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TrngLib.h>
+
+#include "Common.h"
+#include "CtrDrbg.h"
+
+/** GetEntropy implementation using Arm Trng.
+
+  Cf. [3] 10.3.1.2 Condensing After Entropy Collection
+
+  The min and max entropy length are in the DrbgHandle.
+
+  @param [in]   DrbgHandle        The Drbg hanble.
+  @param [in]   ReqEntropy        Requested entropy.
+  @param [out]  EntropyBitsStream Stream containing the generated entropy.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_ABORTED             An error occured.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetEntropy (
+  IN  DRBG_HANDLE  DrbgHandle,
+  IN  UINTN        ReqEntropy,
+  OUT BIT_STREAM   **EntropyBitsStream
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       TrngCollectedEntropy;
+  UINTN       TrngReqBits;
+  UINTN       TrngMaxBits;
+  UINTN       TrngMaxBytes;
+  UINTN       MinLen;
+  UINT8       *QueriedBitsBuff;
+
+  if ((DrbgHandle == NULL)        ||
+      (EntropyBitsStream == NULL) ||
+      (*EntropyBitsStream != NULL))
+  {
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (EntropyBitsStream != NULL);
+    ASSERT (*EntropyBitsStream == NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MinLen          = 0;
+  TrngMaxBits     = GetTrngMaxSupportedEntropyBits ();
+  TrngMaxBytes    = BitsToUpperBytes (TrngMaxBits);
+  QueriedBitsBuff = NULL;
+
+  // 1. If requested_entropy > max_length, return an error indication
+  // and a null value for the entropy_bitstring.
+  //
+  // Note: we also check for MinLen
+  if ((ReqEntropy > DrbgHandle->DrbgVal.MaxLen) ||
+      (ReqEntropy < DrbgHandle->DrbgVal.MinLen))
+  {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 2. collected_entropy = 0.
+  TrngCollectedEntropy = 0;
+
+  // 3. entropy_bitstring = the Null string.
+  Status = BitStreamAlloc (ReqEntropy, EntropyBitsStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  QueriedBitsBuff = (UINT8 *)AllocateZeroPool (TrngMaxBytes);
+  if (QueriedBitsBuff == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    ASSERT_EFI_ERROR (Status);
+    goto ErrorHandler;
+  }
+
+  // 4. While collected_entropy < requested_entropy
+  while (TrngCollectedEntropy < ReqEntropy) {
+    TrngReqBits = MIN ((MinLen - TrngCollectedEntropy), TrngMaxBits);
+
+    // 4.1 Query one or more entropy sources to obtain queried_bits and the
+    // assessed_entropy for those bits.
+    //
+    // Cf. Arm True Random Number Generator Firmware, Interface 1.0,
+    // s2.4.2 Usage, the number of bits requested to the TRNG equals the
+    // number of bits returned. So assessed_entropy == #queried_bits
+    Status = GetTrngEntropy (TrngReqBits, TrngMaxBytes, QueriedBitsBuff);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+
+    // 4.2 entropy_bitstring = entropy_bitstring || queried_bits.
+    //
+    // We are concatenating the other way around. Since this is a TRNG and
+    // the endianness of queried_bits is meaningless, this is the same.
+    Status = BitStreamWrite (
+               QueriedBitsBuff,
+               TrngCollectedEntropy,
+               TrngReqBits,
+               *EntropyBitsStream
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ErrorHandler;
+    }
+
+    // 4.3 collected_entropy = collected_entropy + assessed_entropy.
+    //
+    // Cf above, for Arm TRNG, assessed_entropy == #queried_bits
+    TrngCollectedEntropy += TrngReqBits;
+  } // while
+
+  // 6. If (n > max_length), then
+  // entropy_bitstring = df(entropy_bitstring, max_length).
+  //
+  // Note: This cannot happen.
+  if (DrbgHandle->DrbgVal.MaxLen != 0) {
+    Status = EFI_ABORTED;
+    ASSERT_EFI_ERROR (Status);
+    goto ErrorHandler;
+  }
+
+  FreePool (QueriedBitsBuff);
+
+  // 7. Return (SUCCESS, entropy_bitstring).
+  return Status;
+
+ErrorHandler:
+  if (QueriedBitsBuff) {
+    FreePool (QueriedBitsBuff);
+  }
+
+  BitStreamFree (EntropyBitsStream);
+  return Status;
+}
+
+/** Block encryption (for AES).
+
+  Cf. [1] s10.3.3 'BCC and Block_Encrypt'.
+
+  @param [in]   DrbgHandle      The Drbg hanble.
+  @param [out]  OutBlockStream  Stream containing the encrypted block.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BlockEncrypt (
+  IN  DRBG_HANDLE  DrbgHandle,
+  OUT BIT_STREAM   **OutBlockStream
+  )
+{
+  EFI_STATUS             Status;
+  AES_CTX                AesCtx;
+  CTR_INTERNAL_STATE     *CtrIntState;
+  CTR_VALUE_DEFINITIONS  *CtrVal;
+
+  if ((DrbgHandle == NULL)                  ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL) ||
+      (OutBlockStream == NULL)              ||
+      (*OutBlockStream != NULL))
+  {
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    ASSERT (OutBlockStream != NULL);
+    ASSERT (*OutBlockStream == NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CtrVal      = (CTR_VALUE_DEFINITIONS *)DrbgHandle->DrbgVal.DrbgAlgoVal;
+  CtrIntState = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+  if (IsBitStreamEmpty (CtrIntState->Key)  ||
+      IsBitStreamEmpty (CtrIntState->Val)
+      )
+  {
+    ASSERT (!IsBitStreamEmpty (CtrIntState->Key));
+    ASSERT (!IsBitStreamEmpty (CtrIntState->Val));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AesInitCtx (
+             BitStreamData (CtrIntState->Key),
+             BitStreamBitLen (CtrIntState->Key),
+             &AesCtx
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  Status = BitStreamAlloc (CtrVal->BlockLen, OutBlockStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  Status = AesEncrypt (
+             &AesCtx,
+             BitStreamData (CtrIntState->Val),
+             BitStreamData (*OutBlockStream)
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    BitStreamFree (OutBlockStream);
+    // Fall through.
+  }
+
+  return Status;
+}
diff --git a/MdePkg/Library/DrbgLib/Common.h b/MdePkg/Library/DrbgLib/Common.h
new file mode 100644
index 000000000000..f226528bc5c2
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/Common.h
@@ -0,0 +1,74 @@
+/** @file
+  Implementation of arch specific functions for the Drbg library.
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#ifndef ARCH_IMPLEM_H_
+#define ARCH_IMPLEM_H_
+
+#include "DrbgLibInternal.h"
+
+/** GetEntropy implementation using Arm Trng.
+
+  Cf. [3] 10.3.1.2 Condensing After Entropy Collection
+
+  The min and max entropy length are in the DrbgHandle.
+
+  @param [in]   DrbgHandle        The Drbg hanble.
+  @param [in]   ReqEntropy        Requested entropy.
+  @param [out]  EntropyBitsStream Stream containing the generated entropy.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_ABORTED             An error occured.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetEntropy (
+  IN  DRBG_HANDLE  DrbgHandle,
+  IN  UINTN        ReqEntropy,
+  OUT BIT_STREAM   **EntropyBitsStream
+  );
+
+/** Block encryption (for AES).
+
+  Cf. [1] s10.3.3 'BCC and Block_Encrypt'.
+
+  @param [in]   DrbgHandle      The Drbg hanble.
+  @param [out]  OutBlockStream  Stream containing the encrypted block.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+BlockEncrypt (
+  IN  DRBG_HANDLE  DrbgHandle,
+  OUT BIT_STREAM   **OutBlockStream
+  );
+
+#endif // ARCH_IMPLEM_H_
-- 
2.25.1


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

* [PATCH RESEND v1 6/9] MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (4 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 5/9] MdePkg/DrbgLib: Add common wrappers PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 7/9] MdePkg/DrbgLib: Add Drbg mechanism functions and module PierreGondois
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

>From the NIST Special Publication 800-90A, the implementation
of a Drbg can be split into:
 1. DRBG Mechanism Functions (s9 of the spec), describing the
    operations generic to all the mechanisms.
 2. DRBG Algorithm Specifications (s10 of the spec), describing
    the operations specific to each mechanisms (CTR, HMAC, ...)

This patch implements the 2., i.e. the operations specific to
the Ctr Drbg mechanism.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
 MdePkg/Library/DrbgLib/CtrDrbg.c | 899 +++++++++++++++++++++++++++++++
 MdePkg/Library/DrbgLib/CtrDrbg.h | 100 ++++
 2 files changed, 999 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
 create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h

diff --git a/MdePkg/Library/DrbgLib/CtrDrbg.c b/MdePkg/Library/DrbgLib/CtrDrbg.c
new file mode 100644
index 000000000000..7db4d724086a
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/CtrDrbg.c
@@ -0,0 +1,899 @@
+/** @file
+  Ctr Drbg implementation.
+  (Counter Deterministic Random Bit Generator)
+  Cf. [1] s10.2.1 CTR_DRBG
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+  - [5] Unified Extensible Firmware Interface (UEFI) Specification,
+        Version 2.8 Errata B, May 2020
+        (https://www.uefi.org/specifications)
+  - [6] FIPS 197 November 26, 2001:
+        Specification for the ADVANCED ENCRYPTION STANDARD (AES)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include "Common.h"
+#include "CtrDrbg.h"
+
+/** Get a nonce.
+
+  [1] s10.2.1.3.1 Instantiation When a Derivation Function is Not Used
+
+  When instantiation is performed using this method, full-entropy input
+  is required, and a nonce is not used.
+
+  @param  [in, out] DrbgHandle    The Drbg handle.
+  @param  [out]     NonceStream   Stream containing the Nonce.
+
+  @retval EFI_SUCCESS             Success.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgGetNonce (
+  IN  OUT DRBG_HANDLE  DrbgHandle,
+  OUT     BIT_STREAM   *NonceStream
+  )
+{
+  // Nothing to do.
+  return EFI_SUCCESS;
+}
+
+/** Check the internal state.
+
+  @param  [in] DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgCheckInternalState (
+  IN DRBG_HANDLE  DrbgHandle
+  )
+{
+  CTR_INTERNAL_STATE  *CtrIntState;
+
+  CtrIntState = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+
+  // Just check that key and value BitStreams are still ok.
+  if ((IsBitStreamEmpty (CtrIntState->Val)   ||
+       (IsBitStreamEmpty (CtrIntState->Key))))
+  {
+    ASSERT (!IsBitStreamEmpty (CtrIntState->Val));
+    ASSERT (!IsBitStreamEmpty (CtrIntState->Key));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Update algorithm.
+
+  CTR_DRBG_Update implementation.
+
+  Cf. [1] s10.2.1.2 The Update Function (CTR_DRBG_Update)
+
+  @param [in]       ProvidedData  The data to be used. This must be exactly
+                                  seedlen bits in length.
+  @param [in, out]  DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgUpdate (
+  IN      BIT_STREAM   *ProvidedData,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  )
+{
+  EFI_STATUS             Status;
+  BIT_STREAM             *IncStream;
+  BIT_STREAM             *OutBlkStream;
+  BIT_STREAM             *TempStream;
+  CTR_INTERNAL_STATE     *CtrIntState;
+  CTR_VALUE_DEFINITIONS  *CtrVal;
+
+  if (IsBitStreamEmpty (ProvidedData)  ||
+      (DrbgHandle == NULL)            ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL))
+  {
+    ASSERT (!IsBitStreamEmpty (ProvidedData));
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  IncStream    = NULL;
+  OutBlkStream = NULL;
+  TempStream   = NULL;
+  CtrIntState  = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+  CtrVal       = (CTR_VALUE_DEFINITIONS *)DrbgHandle->DrbgVal.DrbgAlgoVal;
+
+  if (BitStreamBitLen (ProvidedData) != CtrVal->SeedLen) {
+    ASSERT (BitStreamBitLen (ProvidedData) == CtrVal->SeedLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 1. temp = Null.
+  Status = BitStreamAlloc (0, &TempStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //  2. While (len (temp) < seedlen) do
+  while (BitStreamBitLen (TempStream) < CtrVal->SeedLen) {
+    // 2.1 If ctr_len < blocklen
+    if (CtrVal->CtrLen < CtrVal->SeedLen) {
+      // 2.1.1 inc = (rightmost (V, ctr_len) + 1) mod 2 ^ ctr_len.
+      Status = BitStreamRightmost (
+                 CtrIntState->Val,
+                 CtrVal->CtrLen,
+                 &IncStream
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamAddModulo (1, CtrVal->CtrLen, IncStream);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      // 2.1.2 V = leftmost (V, blocklen - ctr_len) || inc.
+      Status = BitStreamLeftmost (
+                 CtrIntState->Val,
+                 CtrVal->BlockLen - CtrVal->CtrLen,
+                 &CtrIntState->Val
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamConcat (
+                 CtrIntState->Val,
+                 IncStream,
+                 &CtrIntState->Val
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamFree (&IncStream);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+    } else {
+      // (2.1) Else V = (V+1) mod 2 ^ blocklen.
+      Status = BitStreamAddModulo (1, CtrVal->BlockLen, CtrIntState->Val);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+    }
+
+    // 2.2 output_block = Block_Encrypt (Key, V).
+    Status = BlockEncrypt (DrbgHandle, &OutBlkStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    // 2.3 temp = temp || output_block.
+    Status = BitStreamConcat (TempStream, OutBlkStream, &TempStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    Status = BitStreamFree (&OutBlkStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  } // while
+
+  // 3. temp = leftmost (temp, seedlen).
+  Status = BitStreamLeftmost (TempStream, CtrVal->SeedLen, &TempStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 4. temp = temp XoR provided_data.
+  Status = BitStreamXor (TempStream, ProvidedData, &TempStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 5. Key = leftmost (temp, keylen).
+  Status = BitStreamFree (&CtrIntState->Key);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  Status = BitStreamLeftmost (TempStream, CtrVal->KeyLen, &CtrIntState->Key);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 6. V = rightmost (temp, blocklen).
+  Status = BitStreamFree (&CtrIntState->Val);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  Status = BitStreamRightmost (
+             TempStream,
+             CtrVal->BlockLen,
+             &CtrIntState->Val
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // Fall through.
+  }
+
+ExitHandler:
+  if (IncStream != NULL) {
+    BitStreamFree (&IncStream);
+  }
+
+  if (OutBlkStream != NULL) {
+    BitStreamFree (&OutBlkStream);
+  }
+
+  if (TempStream != NULL) {
+    BitStreamFree (&TempStream);
+  }
+
+  // 7. Return (Key, V).
+  return Status;
+}
+
+/** Instantiate algorithm.
+
+  CTR_DRBG_Instantiate_algorithm implementation.
+
+  Cf. [1] s10.2.1.3.1 Instantiation When a Derivation Function is Not Used
+
+  @param  [in]  EntropyInput      The string of bits obtained from the
+                                  randomness source.
+  @param  [in]  PersStrBitStream  The personalization string received from the
+                                  consuming application. Note that the length
+                                  of the personalization_string may be zero.
+                                  Note: PersStrBitStream must be initialized,
+                                  even with a NULL BitStream.
+  @param  [out] DrbgHandle        The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgInstantiateAlgo (
+  IN  BIT_STREAM   *EntropyInput,
+  IN  BIT_STREAM   *PersStrBitStream,
+  OUT DRBG_HANDLE  DrbgHandle
+  )
+{
+  EFI_STATUS             Status;
+  BIT_STREAM             *LocalStream;
+  BIT_STREAM             *SeedMaterial;
+  CTR_INTERNAL_STATE     *CtrIntState;
+  CTR_VALUE_DEFINITIONS  *CtrVal;
+  UINTN                  Temp;
+
+  if (IsBitStreamEmpty (EntropyInput)  ||
+      (PersStrBitStream == NULL)      ||
+      (DrbgHandle == NULL) ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL))
+  {
+    ASSERT (!IsBitStreamEmpty (EntropyInput));
+    ASSERT (PersStrBitStream != NULL);
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  LocalStream  = NULL;
+  SeedMaterial = NULL;
+  CtrIntState  = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+  CtrVal       = (CTR_VALUE_DEFINITIONS *)DrbgHandle->DrbgVal.DrbgAlgoVal;
+
+  // 1. temp = len (personalization_string).
+  Temp = BitStreamBitLen (PersStrBitStream);
+
+  // 2. If (temp < seedlen), then
+  // personalization_string = personalization_string || 0 ^ seedlen - temp.
+  if (Temp < CtrVal->SeedLen) {
+    Status = BitStreamAlloc (CtrVal->SeedLen - Temp, &LocalStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+
+    Status = BitStreamConcat (
+               PersStrBitStream,
+               LocalStream,
+               &PersStrBitStream
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  }
+
+  // 3. seed_material = entropy_input XoR personalization_string.
+  Status = BitStreamXor (EntropyInput, PersStrBitStream, &SeedMaterial);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 4. Key = 0 ^ keylen.
+  Status = BitStreamAlloc (CtrVal->KeyLen, &CtrIntState->Key);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 5. V = 0 ^ blocklen.
+  Status = BitStreamAlloc (CtrVal->BlockLen, &CtrIntState->Val);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 6. (Key, V) = CTR_DRBG_Update (seed_material, Key, V).
+  Status = CtrDrbgUpdate (SeedMaterial, DrbgHandle);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 7. reseed_counter = 1.
+  CtrIntState->ReseedCounter = 1;
+
+ExitHandler:
+  if (SeedMaterial != NULL) {
+    BitStreamFree (&SeedMaterial);
+  }
+
+  if (LocalStream != NULL) {
+    BitStreamFree (&LocalStream);
+  }
+
+  // 8. Return (V, Key, reseed_counter).
+  return Status;
+}
+
+/** Reseed algorithm
+
+  CTR_DRBG_Reseed_algorithm implementation.
+
+  Cf. [1] s10.2.1.4.1 Reseeding When a Derivation Function is Not Used
+
+  @param [in]       EntropyInput  The string of bits obtained from the
+                                  randomness source.
+  @param [in]       AddInput      The additional input string received
+                                  from the consuming application. Note
+                                  that the length of the additional_input
+                                  string may be zero.
+  @param [in, out]  DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgReseedAlgo (
+  IN      BIT_STREAM   *EntropyInput,
+  IN      BIT_STREAM   *AddInput,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  )
+{
+  EFI_STATUS             Status;
+  UINTN                  Temp;
+  BIT_STREAM             *LocalStream;
+  BIT_STREAM             *SeedMaterial;
+  CTR_INTERNAL_STATE     *CtrIntState;
+  CTR_VALUE_DEFINITIONS  *CtrVal;
+
+  if (IsBitStreamEmpty (EntropyInput)  ||
+      (AddInput == NULL)              ||
+      (DrbgHandle == NULL) ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL))
+  {
+    ASSERT (!IsBitStreamEmpty (EntropyInput));
+    ASSERT (AddInput != NULL);
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  LocalStream  = NULL;
+  SeedMaterial = NULL;
+  CtrIntState  = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+  CtrVal       = (CTR_VALUE_DEFINITIONS *)DrbgHandle->DrbgVal.DrbgAlgoVal;
+
+  // 1. temp = len (additional_input).
+  Temp = BitStreamBitLen (AddInput);
+
+  // 2. If (temp < seedlen),
+  // then additional_input = additional_input || 0 ^ (seedlen - temp).
+  if (Temp < CtrVal->SeedLen) {
+    Status = BitStreamAlloc (CtrVal->SeedLen - Temp, &LocalStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+
+    Status = BitStreamConcat (
+               AddInput,
+               LocalStream,
+               &AddInput
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  }
+
+  // 3. seed_material = entropy_input XoR additional_input.
+  Status = BitStreamXor (EntropyInput, AddInput, &SeedMaterial);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 4. (Key, V) = CTR_DRBG_Update (seed_material, Key, V).
+  Status = CtrDrbgUpdate (SeedMaterial, DrbgHandle);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 5. reseed_counter = 1.
+  CtrIntState->ReseedCounter = 1;
+
+ExitHandler:
+  if (LocalStream != NULL) {
+    BitStreamFree (&LocalStream);
+  }
+
+  if (SeedMaterial != NULL) {
+    BitStreamFree (&SeedMaterial);
+  }
+
+  // 6. Return (V, Key, reseed_counter).
+  return Status;
+}
+
+/** Generate algorithm.
+
+  CTR_DRBG_Generate_algorithm implementation.
+
+  Cf. s10.2.1.5.1 Generating Pseudorandom Bits When a Derivation Function
+  is Not Used
+
+  To reflect that 'a reseed is required before the requested pseudorandom bits
+  can be generated', the EFI_NOT_READY return code is used.
+
+  @param [in]       AddInput          The additional input string received from
+                                      the consuming application. Note that the
+                                      length of the additional_input string
+                                      may be zero.
+  @param [in]       RequestedNbBits   The number of pseudorandom bits to be
+                                      returned to the generate function.
+  @param [out]      RndBitStream      BitStream containing the random bits.
+  @param [in, out]  DrbgHandle        The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+  @retval EFI_NOT_READY           A reseed is required before the requested
+                                  pseudorandom bits can be generated.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgGenerateAlgo (
+  IN      BIT_STREAM   *AddInput,
+  IN      UINTN        RequestedNbBits,
+  OUT     BIT_STREAM   **RndBitStream,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  )
+{
+  EFI_STATUS             Status;
+  UINTN                  Temp;
+  BIT_STREAM             *IncStream;
+  BIT_STREAM             *LocalStream;
+  BIT_STREAM             *OutBlkStream;
+  BIT_STREAM             *TempStream;
+  CTR_INTERNAL_STATE     *CtrIntState;
+  CTR_VALUE_DEFINITIONS  *CtrVal;
+
+  if ((AddInput == NULL)      ||
+      (RequestedNbBits == 0)  ||
+      (RndBitStream == NULL)  ||
+      (*RndBitStream != NULL) ||
+      (DrbgHandle == NULL) ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL))
+  {
+    ASSERT (AddInput != NULL);
+    ASSERT (RequestedNbBits != 0);
+    ASSERT (RndBitStream != NULL);
+    ASSERT (*RndBitStream == NULL);
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  IncStream    = NULL;
+  LocalStream  = NULL;
+  OutBlkStream = NULL;
+  TempStream   = NULL;
+  CtrIntState  = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+  CtrVal       = (CTR_VALUE_DEFINITIONS *)DrbgHandle->DrbgVal.DrbgAlgoVal;
+
+  // 1. If reseed_counter > reseed_interval,
+  // then return an indication that a reseed is required.
+  if (CtrIntState->ReseedCounter > CtrVal->ReseedInterval) {
+    return EFI_NOT_READY;
+  }
+
+  // 2. If (additional_input != Null), then
+  if (!IsBitStreamEmpty (AddInput)) {
+    // 2.1 temp = len (additional_input).
+    Temp = BitStreamBitLen (AddInput);
+
+    // 2.2 If (temp < seedlen), then
+    // additional_input = additional_input || 0 seedlen - temp .
+    if (Temp < CtrVal->SeedLen) {
+      Status = BitStreamAlloc (CtrVal->SeedLen - Temp, &LocalStream);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        return Status;
+      }
+
+      Status = BitStreamConcat (AddInput, LocalStream, &AddInput);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+    }
+
+    // 2.3 (Key, V) = CTR_DRBG_Update (additional_input, Key, V).
+    Status = CtrDrbgUpdate (AddInput, DrbgHandle);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  } else {
+    // (2.) Else additional_input = 0 ^ seedlen.
+    Status = BitStreamFree (&AddInput); // Freeing &AddInput, this is wrong, AddInput is now a local parameter
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    Status = BitStreamAlloc (CtrVal->SeedLen, &AddInput);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  }
+
+  // 3. temp = Null.
+  Status = BitStreamAlloc (0, &TempStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 4. While (len (temp) < requested_number_of_bits) do:
+  while (BitStreamBitLen (TempStream) < RequestedNbBits) {
+    // 4.1 If ctr_len < blocklen
+    if (CtrVal->CtrLen < CtrVal->BlockLen) {
+      // 4.1.1 inc = (rightmost (V, ctr_len) + 1) mod 2 ^ ctr_len.
+      Status = BitStreamRightmost (
+                 CtrIntState->Val,
+                 CtrVal->CtrLen,
+                 &IncStream
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamAddModulo (1, CtrVal->CtrLen, IncStream);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      // 4.1.2 V = leftmost (V, blocklen-ctr_len) || inc.
+      Status = BitStreamLeftmost (
+                 CtrIntState->Val,
+                 CtrVal->BlockLen - CtrVal->CtrLen,
+                 &CtrIntState->Val
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamConcat (
+                 CtrIntState->Val,
+                 IncStream,
+                 &CtrIntState->Val
+                 );
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      Status = BitStreamFree (&IncStream);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+    } else {
+      // (4.1) Else V = (V+1) mod 2 ^ blocklen.
+      Status = BitStreamAddModulo (1, CtrVal->BlockLen, CtrIntState->Val);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+    }
+
+    // 4.2 output_block = Block_Encrypt (Key, V).
+    Status = BlockEncrypt (DrbgHandle, &OutBlkStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    // 4.3 temp = temp || output_block.
+    Status = BitStreamConcat (TempStream, OutBlkStream, &TempStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    Status = BitStreamFree (&OutBlkStream);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+  } // while
+
+  // 5. returned_bits = leftmost (temp, requested_number_of_bits).
+  Status = BitStreamLeftmost (TempStream, RequestedNbBits, RndBitStream);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 6. (Key, V) = CTR_DRBG_Update (additional_input, Key, V).
+  Status = CtrDrbgUpdate (AddInput, DrbgHandle);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 7. reseed_counter = reseed_counter + 1.
+  CtrIntState->ReseedCounter += 1;
+
+ExitHandler:
+  if (IncStream != NULL) {
+    BitStreamFree (&IncStream);
+  }
+
+  if (LocalStream != NULL) {
+    BitStreamFree (&LocalStream);
+  }
+
+  if (OutBlkStream != NULL) {
+    BitStreamFree (&OutBlkStream);
+  }
+
+  if (TempStream != NULL) {
+    BitStreamFree (&TempStream);
+  }
+
+  // 8. Return (SUCCESS, returned_bits, Key, V, reseed_counter).
+  return Status;
+}
+
+/** Uninstantiate a DRBG instance.
+
+  [1] s9.4 Removing a DRBG Instantiation
+
+  @param  [in, out] DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CtrDrbgUninstantiateFn (
+  IN  OUT DRBG_HANDLE  DrbgHandle
+  )
+{
+  EFI_STATUS          Status;
+  EFI_STATUS          ReturnStatus;
+  CTR_INTERNAL_STATE  *CtrIntState;
+
+  if ((DrbgHandle == NULL) ||
+      (DrbgHandle->IntState.DrbgAlgoIntState == NULL) ||
+      (DrbgHandle->DrbgVal.DrbgAlgoVal == NULL))
+  {
+    ASSERT (DrbgHandle != NULL);
+    ASSERT (DrbgHandle->IntState.DrbgAlgoIntState != NULL);
+    ASSERT (DrbgHandle->DrbgVal.DrbgAlgoVal != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ReturnStatus = EFI_SUCCESS;
+  CtrIntState  = (CTR_INTERNAL_STATE *)DrbgHandle->IntState.DrbgAlgoIntState;
+
+  // 1. If state_handle indicates an invalid state, then return (ERROR_FLAG).
+  // 2. Erase the contents of the internal state indicated by state_handle.
+
+  Status = BitStreamFree (&CtrIntState->Key);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    ReturnStatus = Status;
+  }
+
+  Status = BitStreamFree (&CtrIntState->Val);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    ReturnStatus = Status;
+  }
+
+  FreePool (DrbgHandle);
+
+  // 3. Return (SUCCESS).
+  return ReturnStatus;
+}
+
+/** Drbg mechanism specific instantiation steps.
+
+  @param  [in, out] DrbgHandle     The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+CtrInitHandle (
+  IN  OUT DRBG_HANDLE  DrbgHandle
+  )
+{
+  DRBG_VALUE_DEFINITIONS  *DrbgVal;
+  CTR_INTERNAL_STATE      *CtrIntState;
+  CTR_VALUE_DEFINITIONS   *CtrVal;
+
+  if (DrbgHandle == NULL) {
+    ASSERT (DrbgHandle != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (
+    &DrbgHandle->Algo,
+    &gEfiRngAlgorithmSp80090Ctr256Guid,
+    sizeof (EFI_RNG_ALGORITHM)
+    );
+
+  // Allocate CtrIntState. Fields are init to 0.
+  CtrIntState = AllocateZeroPool (sizeof (CTR_INTERNAL_STATE));
+  if (CtrIntState == NULL) {
+    ASSERT (CtrIntState != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DrbgHandle->IntState.DrbgAlgoIntState = CtrIntState;
+
+  // Allocate CtrVal. Fields are init to 0.
+  CtrVal = AllocateZeroPool (sizeof (CTR_VALUE_DEFINITIONS));
+  if (CtrVal == NULL) {
+    ASSERT (CtrVal != NULL);
+    FreePool (CtrIntState);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DrbgHandle->DrbgVal.DrbgAlgoVal = CtrVal;
+
+  // CTR DRBG definitions, cf [1] Table 3 'Definitions for the CTR_DRBG'.
+  // No derivation function is used.
+  // Only 256 bits AES is allowed (Cf. [5] 'Section 37.5 Random Number
+  // Generator Protocol')
+
+  // Drbg generic values.
+  DrbgVal                         = &DrbgHandle->DrbgVal;
+  DrbgVal->HighestSuppSecStrength = 256;
+  DrbgVal->MinLen                 = CTR_DRBG_AES_256_SEEDLEN;
+  DrbgVal->MaxLen                 = CTR_DRBG_AES_256_SEEDLEN;
+  DrbgVal->MaxPersStrLen          = CTR_DRBG_AES_256_SEEDLEN;
+  DrbgVal->MaxAddInputLen         = CTR_DRBG_AES_256_SEEDLEN;
+  DrbgVal->MaxNbBitsPerRequest    = 1 << 19;
+
+  // Ctr specific values.
+  CtrVal->BlockLen = CTR_DRBG_AES_BLOCKLEN;
+  // 4 <= ctr_len <= blocklen. Choose blocklen to be faster.
+  CtrVal->CtrLen             = CTR_DRBG_AES_BLOCKLEN;
+  CtrVal->KeyLen             = CTR_DRBG_AES_256_KEYLEN;
+  CtrVal->MinRequiredEntropy = SecStrength256bits;
+  CtrVal->SeedLen            = CTR_DRBG_AES_256_SEEDLEN;
+  CtrVal->ReseedInterval     = (UINT64)1 << 48;
+
+  // CtrDrbg supports both mechanisms.
+  DrbgHandle->PredResSupported = TRUE;
+  DrbgHandle->ReseedSupported  = TRUE;
+
+  // CtrDrbg specific implementations.
+  DrbgHandle->DrbgGetNonce           = CtrDrbgGetNonce;
+  DrbgHandle->DrbgCheckInternalState = CtrDrbgCheckInternalState;
+  DrbgHandle->DrbgUpdate             = CtrDrbgUpdate;
+  DrbgHandle->DrbgReseedAlgo         = CtrDrbgReseedAlgo;
+  DrbgHandle->DrbgGenerateAlgo       = CtrDrbgGenerateAlgo;
+  DrbgHandle->DrbgInstantiateAlgo    = CtrDrbgInstantiateAlgo;
+  DrbgHandle->DrbgUninstantiateFn    = CtrDrbgUninstantiateFn;
+
+  return EFI_SUCCESS;
+}
diff --git a/MdePkg/Library/DrbgLib/CtrDrbg.h b/MdePkg/Library/DrbgLib/CtrDrbg.h
new file mode 100644
index 000000000000..df9c5108388a
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/CtrDrbg.h
@@ -0,0 +1,100 @@
+/** @file
+  Ctr Drbg implementation.
+  (Counter Deterministic Random Bit Generator)
+  Cf. [1] s10.2.1 CTR_DRBG
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+  - [5] Unified Extensible Firmware Interface (UEFI) Specification,
+        Version 2.8 Errata B, May 2020
+        (https://www.uefi.org/specifications)
+  - [6] FIPS 197 November 26, 2001:
+        Specification for the ADVANCED ENCRYPTION STANDARD (AES)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#ifndef CTR_DRBG_LIB_H_
+#define CTR_DRBG_LIB_H_
+
+/* Blocklen when using CTR DRBG AES-128, AES-192 and
+  AES-256 algorithm.
+
+  Cf. [6] Figure 4. 'Key-Block-Round Combinations'
+  Cf. [1] Table 3 'Definitions for the CTR_DRBG'
+
+  Output block length is also called 'outlen'.
+*/
+#define CTR_DRBG_AES_BLOCKLEN  128
+
+/* Key length when using CTR DRBG AES-256 algorithm.
+
+  Cf. [1] Table 3 'Definitions for the CTR_DRBG'
+  Cf. [5] s37.5 'Random Number Generator Protocol':
+  'Security level must be at least 256 bits'
+*/
+#define CTR_DRBG_AES_256_KEYLEN  256
+
+/** Seed length when using CTR DRBG AES-256 algorithm.
+
+  Cf. [1] Table 3 'Definitions for the CTR_DRBG'
+  Seed length (seedlen = outlen + keylen)
+*/
+#define CTR_DRBG_AES_256_SEEDLEN  (CTR_DRBG_AES_BLOCKLEN +   \
+                                    CTR_DRBG_AES_256_KEYLEN)
+
+/** Ctr specific internal state.
+
+  Some fields defined at [1] s10.2.1.1 'CTR_DRBG Internal State' might be
+  in the DRBG_INTERNAL_STATE structure.
+*/
+typedef struct {
+  // Working state.
+  /// Value
+  BIT_STREAM    *Val;
+  /// Key
+  BIT_STREAM    *Key;
+  /// Counter: Number of requests for pseudorandom bits
+  ///          since instantiation or reseeding
+  UINTN         ReseedCounter;
+} CTR_INTERNAL_STATE;
+
+/** Ctr specific values.
+
+  Cf. [1] Table 3: Definitions for the CTR_DRBG
+  Some fields might be in the DRBG_VALUE_DEFINITIONS structure.
+*/
+typedef struct {
+  /// Input and output block length
+  UINTN     BlockLen;
+  /// Counter field length.
+  UINTN     CtrLen;
+  // Key length.
+  UINTN     KeyLen;
+  /// Required minimum entropy for instantiate and reseed.
+  UINTN     MinRequiredEntropy;
+  /// Seed length.
+  UINTN     SeedLen;
+  /// Maximum number of requests between two reseeds.
+  UINT64    ReseedInterval;
+} CTR_VALUE_DEFINITIONS;
+
+#endif // CTR_DRBG_LIB_H_
-- 
2.25.1


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

* [PATCH RESEND v1 7/9] MdePkg/DrbgLib: Add Drbg mechanism functions and module
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (5 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 6/9] MdePkg/DrbgLib: Add Ctr Drbg mechanism functions PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 8/9] ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe PierreGondois
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <Pierre.Gondois@arm.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3971

>From the NIST Special Publication 800-90A, the implementation
of a Drbg can be split into:
 1. DRBG Mechanism Functions (s9 of the spec), describing the
    operations generic to all the mechanisms.
 2. DRBG Algorithm Specifications (s10 of the spec), describing
    the operations specific to each mechanisms (CTR, HMAC, ...)

This patch implements 1., i.e. the operations generic to
all the mechanisms. Functions implemented here are also the
DrbgLib interface.

The .inf file associated to the module is also added here.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 MdePkg/Library/DrbgLib/DrbgLib.c         | 628 +++++++++++++++++++++++
 MdePkg/Library/DrbgLib/DrbgLib.inf       |  39 ++
 MdePkg/Library/DrbgLib/DrbgLibInternal.h | 310 +++++++++++
 MdePkg/MdePkg.dsc                        |   1 +
 4 files changed, 978 insertions(+)
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
 create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h

diff --git a/MdePkg/Library/DrbgLib/DrbgLib.c b/MdePkg/Library/DrbgLib/DrbgLib.c
new file mode 100644
index 000000000000..bfad8fc670be
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/DrbgLib.c
@@ -0,0 +1,628 @@
+/** @file
+  Drbg library.
+  Cf. [1] s9 DRBG Mechanism Functions
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation for Key Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+  - [5] Unified Extensible Firmware Interface (UEFI) Specification,
+        Version 2.8 Errata B, May 2020
+        (https://www.uefi.org/specifications)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include "Common.h"
+#include "GetEntropyInput.h"
+
+/** Check the internal state of the Drbg handle.
+
+  @param  [in] DrbgHandle   The Drbg handle.
+
+  @retval TRUE  The Drbg handle has a valid internal state.
+  @retval FALSE Otherwise.
+**/
+STATIC
+BOOLEAN
+CheckInternalState (
+  IN  DRBG_HANDLE  DrbgHandle
+  )
+{
+  if ((DrbgHandle == NULL)  ||
+      EFI_ERROR (DrbgHandle->DrbgCheckInternalState (DrbgHandle)))
+  {
+    ASSERT (DrbgHandle != NULL);
+    ASSERT_EFI_ERROR (DrbgHandle->DrbgCheckInternalState (DrbgHandle));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/** Reseed a DRBG instance.
+
+  Implementation of Reseed_function.
+  Cf. [1] s9.2 'Reseeding a DRBG Instantiation'
+
+  @param  [in] PredResRequest   Indicates whether prediction resistance
+                                is to be provided during the request.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInput         An optional additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in, out] DrbgHandle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgReseedFn (
+  IN        BOOLEAN  PredResRequest,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN  OUT   VOID     *Handle
+  )
+{
+  EFI_STATUS   Status;
+  DRBG_HANDLE  DrbgHandle;
+  BIT_STREAM   *AddInputStream;
+  BIT_STREAM   *EntropyBitsStream;
+
+  DrbgHandle = (DRBG_HANDLE)Handle;
+
+  // 1. Using state_handle, obtain the current internal state.
+  // If state_handle indicates an invalid or unused internal state,
+  // return (ERROR_FLAG).
+  if (((AddInput == NULL) ^ (AddInputLen == 0)) ||
+      !CheckInternalState (DrbgHandle))
+  {
+    ASSERT (!((AddInput == NULL) ^ (AddInputLen == 0)));
+    ASSERT (CheckInternalState (DrbgHandle));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AddInputStream    = NULL;
+  EntropyBitsStream = NULL;
+
+  // 2. If prediction_resistance_request is set, and prediction_resistance_flag
+  // is not set, then return (ERROR_FLAG).
+  if (PredResRequest && !DrbgHandle->IntState.PredResFlag) {
+    ASSERT (!(PredResRequest && !DrbgHandle->IntState.PredResFlag));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 3. If the length of the additional_input > max_additional_input_length,
+  // return (ERROR_FLAG).
+  if (AddInputLen > DrbgHandle->DrbgVal.MaxAddInputLen) {
+    ASSERT (AddInputLen <= DrbgHandle->DrbgVal.MaxAddInputLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 4. (status, entropy_input) = Get_entropy_input (security_strength,
+  // min_length, max_length, prediction_resistance_request).
+  // 5. If (status != SUCCESS), return (status).
+  //
+  // Note: in this implementation, there is no difference between
+  // ERROR_FLAG and CATASTROPHIC_ERROR_FLAG.
+  Status = DrbgHandle->DrbgGetEntropyInput (
+                         DrbgHandle,
+                         DrbgHandle->DrbgVal.MinLen,
+                         &EntropyBitsStream
+                         );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // Create a BitStream for AddInput, even for a NULL AddInput. AddInput is
+  // used during instantiation but doesn't persist in the Drbg handle.
+  Status = BitStreamInit (
+             (UINT8 *)AddInput,
+             AddInputLen,
+             &AddInputStream
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 6. new_working_state = Reseed_algorithm (working_state, entropy_input,
+  // additional_input).
+  // 7. Replace the working_state in the internal state for the DRBG
+  // instantiation (e.g., as indicated by state_handle) with the values of
+  // new_working_state obtained in step 6.
+  Status = DrbgHandle->DrbgReseedAlgo (
+                         EntropyBitsStream,
+                         AddInputStream,
+                         DrbgHandle
+                         );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // Fall trough
+  }
+
+ExitHandler:
+  if (AddInputStream != NULL) {
+    BitStreamFree (&AddInputStream);
+  }
+
+  if (EntropyBitsStream != NULL) {
+    BitStreamFree (&EntropyBitsStream);
+  }
+
+  // 8. Return (SUCCESS).
+  return Status;
+}
+
+/** Create a Drbg instance.
+
+  Implementation of Instantiate_function.
+  Cf. [1] s9.1 Instantiating a DRBG
+
+  @param  [in] DrbgMechanism    DRBG mechanism chosen.
+  @param  [in] DrbgEntropySrc   Entropy source chosen.
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                The security strenght granted can be different.
+  @param  [in] PredRes          Prediction resistance flag.
+                                If relevant, instantiate a DRBG that supports
+                                prediction resistance.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStr          Personnalization string.
+                                Might not be supported by all Drbgs.
+  @param  [in] PersStrLen       Personnalization string length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [out] HandlePtr   Pointer containting the created Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgInstantiateFn (
+  IN        DRBG_MECHANISM    DrbgMechanism,
+  IN        DRBG_ENTROPY_SRC  DrbgEntropySrc,
+  IN        UINTN             ReqSecStrength,
+  IN        BOOLEAN           PredRes,
+  IN  CONST CHAR8             *PersStr,
+  IN        UINTN             PersStrLen,
+  OUT       VOID              **HandlePtr
+  )
+{
+  EFI_STATUS   Status;
+  BIT_STREAM   *EntropyBitsStream;
+  BIT_STREAM   *PersStrBitStream;
+  DRBG_HANDLE  DrbgHandle;
+
+  if ((ReqSecStrength == 0)                   ||
+      ((PersStr == NULL) ^ (PersStrLen == 0)) ||
+      (HandlePtr == NULL))
+  {
+    ASSERT (ReqSecStrength != 0);
+    ASSERT (!((PersStr == NULL) ^ (PersStrLen == 0)));
+    ASSERT (HandlePtr != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate a Drbg.
+  DrbgHandle = AllocateZeroPool (sizeof (DRBG_INFO));
+  if (DrbgHandle == NULL) {
+    ASSERT (DrbgHandle != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // Init the handle according to the mechanism.
+  switch (DrbgMechanism) {
+    case DrbgMechansimCtr:
+      Status = CtrInitHandle (DrbgHandle);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        goto ExitHandler;
+      }
+
+      break;
+
+    default:
+      Status = EFI_INVALID_PARAMETER;
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+  }
+
+  // Init the handle according to entropy.
+  switch (DrbgEntropySrc) {
+    case DrbgEntropyNoCondFn:
+      DrbgHandle->DrbgGetEntropyInput = GetEntropyInputNoCondFn;
+      break;
+
+    default:
+      Status = EFI_INVALID_PARAMETER;
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+  }
+
+  EntropyBitsStream = NULL;
+  PersStrBitStream  = NULL;
+
+  // 1. If requested_instantiation_security_strength >
+  //                  highest_supported_security_strength,
+  // then return (ERROR_FLAG, Invalid).
+  if (ReqSecStrength > DrbgHandle->DrbgVal.HighestSuppSecStrength) {
+    ASSERT (ReqSecStrength <= DrbgHandle->DrbgVal.HighestSuppSecStrength);
+    goto ExitHandler;
+  }
+
+  // 2. If prediction_resistance_flag is set, and prediction resistance
+  // is not supported, then return (ERROR_FLAG, Invalid).
+  if (!DrbgHandle->PredResSupported && PredRes) {
+    ASSERT (!(!DrbgHandle->PredResSupported && PredRes));
+    goto ExitHandler;
+  }
+
+  if (PersStr != NULL) {
+    // 3. If the length of the personalization_string >
+    //                max_personalization_string_length,
+    // return (ERROR_FLAG, Invalid).
+    if (PersStrLen > DrbgHandle->DrbgVal.MaxPersStrLen) {
+      ASSERT (PersStrLen <= DrbgHandle->DrbgVal.MaxPersStrLen);
+      goto ExitHandler;
+    }
+  }
+
+  // 4. Set security_strength to the lowest security strength greater than or
+  // equal to requested_instantiation_security_strength from the set
+  // {112, 128, 192, 256}.
+  //
+  // Note: [5], Section 37.5 Random Number Generator Protocol:
+  // 'When a Deterministic Random Bit Generator (DRBG) is used on the
+  // output of a (raw) entropy source, its security level must be at
+  // least 256 bits.'
+  // So set the security strength to 256.
+  //
+  // Note2: Set it here so CTR_DRBG_Instantiate_algorithm has access to it.
+  DrbgHandle->IntState.SecStrength = SecStrength256bits;
+  DEBUG ((
+    DEBUG_INFO,
+    "Requested security strength = %d bits. " \
+    "Setting security strength for DRBG to %d bits.\n",
+    ReqSecStrength,
+    SecStrength256bits
+    ));
+
+  // Create a BitStream for PersStr, even for a NULL PersStr. PersStr is
+  // used during instantiation but doesn't persist in the Drbg handle.
+  Status = BitStreamInit (
+             (UINT8 *)PersStr,
+             PersStrLen,
+             &PersStrBitStream
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 5. Null step.
+  // 6. (status, entropy_input) = Get_entropy_input (security_strength,
+  // min_length, max_length, prediction_resistance_request).
+  //
+  // Note: in this implementation, there is no difference between
+  // ERROR_FLAG and CATASTROPHIC_ERROR_FLAG.
+  //
+  // 7. If (status != SUCCESS), return (status, Invalid).
+  Status = DrbgHandle->DrbgGetEntropyInput (
+                         DrbgHandle,
+                         DrbgHandle->DrbgVal.MinLen,
+                         &EntropyBitsStream
+                         );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 8. Obtain a nonce.
+  Status = DrbgHandle->DrbgGetNonce (DrbgHandle, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 9. initial_working_state = Instantiate_algorithm (entropy_input, nonce,
+  //            personalization_string, security_strength).
+  Status = DrbgHandle->DrbgInstantiateAlgo (
+                         EntropyBitsStream,
+                         PersStrBitStream,
+                         DrbgHandle
+                         );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 10. Get a state_handle for a currently empty internal state. If an empty
+  // internal state cannot be found, return (ERROR_FLAG, Invalid).
+  // 11. Set the internal state for the new instantiation (e.g., as indicated
+  // by state_handle) to the initial values for the internal state (i.e., set
+  // the working_state to the values returned as initial_working_state in
+  // step 9) and any other values required for the working_state (see
+  // Section 10), and set the administrative information to the appropriate
+  // values (e.g., the values of security_strength and the
+  // prediction_resistance_flag).
+  DrbgHandle->IntState.PredResFlag = PredRes;
+  // DrbgInstantiateAlgo already sets ReseedCounter
+
+ExitHandler:
+  if (EntropyBitsStream != NULL) {
+    BitStreamFree (&EntropyBitsStream);
+  }
+
+  if (PersStrBitStream != NULL) {
+    BitStreamFree (&PersStrBitStream);
+  }
+
+  if (EFI_ERROR (Status)) {
+    FreePool (DrbgHandle);
+    DrbgHandle = NULL;
+  }
+
+  // 12. Return (SUCCESS, state_handle).
+  *HandlePtr = (VOID **)DrbgHandle;
+  return Status;
+}
+
+/** Generate a random number.
+
+  Implementation of Generate_function.
+  Cf. [1] s9.3.1 The Generate Function
+
+  @param  [in] ReqSecStrength   Requested security strength (in bits).
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] PredResReq       Request prediction resistance.
+                                If the DrbgHandle cannot satisfy the request,
+                                an error is returned.
+  @param  [in] AddInput         Additional input.
+                                Might not be supported by all Drbgs.
+  @param  [in] AddInputLen      Additional input length (in bits).
+                                Might not be supported by all Drbgs.
+  @param  [in] ReqNbBits        Number of random bits requested.
+  @param  [in, out] OutBuffer   If success, contains the random bits.
+                                The buffer must be at least ReqNbBits bits
+                                long.
+  @param  [in, out] DrbgHandle  The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+DrbgGenerateFn (
+  IN        UINTN    ReqSecStrength,
+  IN        BOOLEAN  PredResReq,
+  IN  CONST CHAR8    *AddInput,
+  IN        UINTN    AddInputLen,
+  IN        UINTN    ReqNbBits,
+  IN  OUT   UINT8    *OutBuffer,
+  IN  OUT   VOID     *Handle
+  )
+{
+  EFI_STATUS   Status;
+  DRBG_HANDLE  DrbgHandle;
+  BOOLEAN      ReseedReq;
+  BIT_STREAM   *AddInputStream;
+  BIT_STREAM   *RandomBitsStream;
+
+  DrbgHandle = (DRBG_HANDLE)Handle;
+
+  // 1. Using state_handle, obtain the current internal state for the
+  // instantiation. If state_handle indicates an invalid or unused internal
+  // state, then return (ERROR_FLAG, Null).
+  if ((ReqSecStrength == 0)                     ||
+      ((AddInput != NULL) ^ (AddInputLen != 0)) ||
+      (ReqNbBits == 0)                          ||
+      (OutBuffer == NULL)                       ||
+      !CheckInternalState (DrbgHandle))
+  {
+    ASSERT (ReqSecStrength != 0);
+    ASSERT (!((AddInput != NULL) ^ (AddInputLen != 0)));
+    ASSERT (ReqNbBits != 0);
+    ASSERT (OutBuffer != NULL);
+    ASSERT (CheckInternalState (DrbgHandle));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AddInputStream   = NULL;
+  RandomBitsStream = NULL;
+
+  // 2. If requested_number_of_bits > max_number_of_bits_per_request,
+  // then return (ERROR_FLAG, Null).
+  if (ReqNbBits > DrbgHandle->DrbgVal.MaxNbBitsPerRequest) {
+    ASSERT (ReqNbBits <= DrbgHandle->DrbgVal.MaxNbBitsPerRequest);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 3. If requested_security_strength > the security_strength indicated
+  // in the internal state, then return (ERROR_FLAG, Null).
+  if (ReqSecStrength > DrbgHandle->IntState.SecStrength) {
+    ASSERT (ReqSecStrength <= DrbgHandle->IntState.SecStrength);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 4. If the length of the additional_input > max_additional_input_length,
+  // then return (ERROR_FLAG, Null).
+  if (AddInputLen > DrbgHandle->DrbgVal.MaxAddInputLen) {
+    ASSERT (AddInputLen <= DrbgHandle->DrbgVal.MaxAddInputLen);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 5. If prediction_resistance_request is set, and prediction_resistance_flag
+  // is not set, then return (ERROR_FLAG, Null).
+  if (PredResReq && !DrbgHandle->IntState.PredResFlag) {
+    ASSERT (!(PredResReq && !DrbgHandle->IntState.PredResFlag));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // 6. Clear the reseed_required_flag.
+  ReseedReq = FALSE;
+
+  // 7. If reseed_required_flag is set, or if prediction_resistance_request is
+  // set, then
+Step7:
+  if (ReseedReq || PredResReq) {
+    // 7.1 status = Reseed_function (state_handle,
+    //                  prediction_resistance_request, additional_input).
+    // 7.2 If (status != SUCCESS), then return (status, Null).
+    // 7.3 Using state_handle, obtain the new internal state.
+    //
+    // Note: in this implementation, there is no difference between
+    // ERROR_FLAG and CATASTROPHIC_ERROR_FLAG.
+    Status = DrbgReseedFn (
+               PredResReq,
+               AddInput,
+               AddInputLen,
+               DrbgHandle
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      goto ExitHandler;
+    }
+
+    // 7.4 additional_input = the Null string.
+    AddInput    = NULL;
+    AddInputLen = 0;
+
+    // 7.5 Clear the reseed_required_flag.
+    ReseedReq = FALSE;
+  }
+
+  // Create a BitStream for AddInput, even for a NULL AddInput. AddInput is
+  // used during instantiation but doesn't persist in the Drbg handle.
+  Status = BitStreamInit (
+             (UINT8 *)AddInput,
+             AddInputLen,
+             &AddInputStream
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // 8. (status, pseudorandom_bits, new_working_state) =
+  // Generate_algorithm (working_state, requested_number_of_bits,
+  //            additional_input).
+  Status = DrbgHandle->DrbgGenerateAlgo (
+                         AddInputStream,
+                         ReqNbBits,
+                         &RandomBitsStream,
+                         DrbgHandle
+                         );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+    ASSERT_EFI_ERROR (Status);
+    goto ExitHandler;
+  }
+
+  // Free AddInputStream now that it has been used.
+  if (AddInputStream != NULL) {
+    BitStreamFree (&AddInputStream);
+  }
+
+  // 9. If status indicates that a reseed is required before the requested
+  // bits can be generated, then
+  if (Status == EFI_NOT_READY) {
+    if (DrbgHandle->ReseedSupported) {
+      // 9.1 Set the reseed_required_flag.
+      ReseedReq = TRUE;
+
+      // 9.2 If the prediction_resistance_flag is set, then set the
+      // prediction_resistance request indication.
+      if (DrbgHandle->IntState.PredResFlag) {
+        PredResReq = TRUE;
+      }
+
+      // 9.3 Go to step 7.
+      goto Step7;
+    } else {
+      // Implementation notes:
+      // If a reseed capability is not supported, or a reseed is not desired,
+      // then generate process steps 6 and 7 are removed; generate process
+      // step 9 is replaced by:
+      // 9. If status indicates that a reseed is required before the requested
+      // bits can be generated, then
+      // 9.1 status = Uninstantiate_function (state_handle).
+      //
+      // No need to check the returned status.
+      DrbgUninstantiateFn (DrbgHandle);
+
+      // 9.2 Return an indication that the DRBG instantiation can no longer be used.
+      goto ExitHandler;
+    }
+  }
+
+  // The Drbg succeeded, copy the random bits.
+  Status = BitStreamToBuffer (RandomBitsStream, OutBuffer);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    // Fall through.
+  }
+
+  // 10. Replace the old working_state in the internal state of the DRBG
+  // instantiation (e.g., as indicated by state_handle) with the values of
+  // new_working_state.
+  // 11. Return (SUCCESS, pseudorandom_bits).
+ExitHandler:
+  if (AddInputStream != NULL) {
+    BitStreamFree (&AddInputStream);
+  }
+
+  if (RandomBitsStream != NULL) {
+    BitStreamFree (&RandomBitsStream);
+  }
+
+  return Status;
+}
+
+/** Remove a DRBG instance.
+
+  Implementation of Uninstantiate_function.
+  Cf. [1] s9.4 Removing a DRBG Instantiation
+
+  @param  [in, out] DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+DrbgUninstantiateFn (
+  IN  OUT VOID  *Handle
+  )
+{
+  DRBG_HANDLE  DrbgHandle;
+
+  DrbgHandle = (DRBG_HANDLE)Handle;
+  return DrbgHandle->DrbgUninstantiateFn (DrbgHandle);
+}
diff --git a/MdePkg/Library/DrbgLib/DrbgLib.inf b/MdePkg/Library/DrbgLib/DrbgLib.inf
new file mode 100644
index 000000000000..34272aa88d85
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/DrbgLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Drbg library
+#
+#  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001B
+  BASE_NAME      = DrbgLib
+  FILE_GUID      = 454B071B-FD44-4055-B689-E06B6FE5D3D7
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = DrbgLib
+
+#
+#  VALID_ARCHITECTURES           = AARCH64 ARM
+#
+
+[Sources]
+  BitStream.c
+  BitStream.h
+  Common.c
+  Common.h
+  CtrDrbg.c
+  CtrDrbg.h
+  DrbgLib.c
+  DrbgLibInternal.h
+  GetEntropyInput.c
+  GetEntropyInput.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  AesLib
+  BaseLib
+  TrngLib
diff --git a/MdePkg/Library/DrbgLib/DrbgLibInternal.h b/MdePkg/Library/DrbgLib/DrbgLibInternal.h
new file mode 100644
index 000000000000..6cf681951431
--- /dev/null
+++ b/MdePkg/Library/DrbgLib/DrbgLibInternal.h
@@ -0,0 +1,310 @@
+/** @file
+  Arm DRBG library internal definitions.
+  Cf. [1] s9 DRBG Mechanism Functions
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+
+  - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
+        for Random Number Generation Using Deterministic Random Bit Generators.
+        (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
+  - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
+        Sources Used for Random Bit Generation.
+        (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
+  - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
+        Random Bit Generator (RBG) Constructions.
+        (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
+  - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
+        Recommendation forKey Management:Part 1 - General.
+        (https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
+  - [5] Unified Extensible Firmware Interface (UEFI) Specification,
+        Version 2.8 Errata B, May 2020
+        (https://www.uefi.org/specifications)
+
+  @par Glossary:
+    - TRNG - True Random Number Generator
+    - Sec  - Security
+    - DRBG - Deterministic Random Bits Generator
+    - CTR  - Counter
+**/
+
+#ifndef ARM_DRBG_LIB_INTERNAL_H_
+#define ARM_DRBG_LIB_INTERNAL_H_
+
+// Forward declarations of DRBG_INFO.
+typedef struct DrbgInfo  DRBG_INFO;
+typedef DRBG_INFO        *DRBG_HANDLE;
+
+#include <Library/DrbgLib.h>
+#include <Protocol/Rng.h>
+#include "BitStream.h"
+
+/** Security strengths for block cipher algorithms.
+
+    Cf [2] 5.6.1.1, Table 2: Comparable security strengths of symmetric block
+    cipher and asymmetric-key algorithms.
+
+    [2]: 'Although 3TDEA is listed as providing 112 bits of security strength,
+          its use has been deprecated (see SP 800-131A)'
+*/
+typedef enum {
+  SecStrengthMin     = 128,               ///< Min Security strength of 128 bits.
+  SecStrength128bits = SecStrengthMin,    ///< Security strength of 128 bits.
+  SecStrength196bits = 196,               ///< Security strength of 196 bits.
+  SecStrength256bits = 256,               ///< Security strength of 256 bits.
+  SecStrengthMax     = SecStrength256bits ///< Maximum Security strength.
+} SECURITY_STRENGTH;
+
+/** Get a nonce.
+
+  @param  [in, out] DrbgHandle    The Drbg handle.
+  @param  [out]     NonceStream   Stream containing the Nonce.
+
+  @retval EFI_SUCCESS             Success.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_GET_NONCE) (
+  IN  OUT DRBG_HANDLE  DrbgHandle,
+  OUT     BIT_STREAM   *NonceStream
+  );
+
+/** Check the internal state of the Drbg handle.
+
+  @param  [in] DrbgHandle    The Drbg handle.
+
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_SUCCESS             Success.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_CHECK_INTERNAL_STATE) (
+  IN  DRBG_HANDLE  DrbgHandle
+  );
+
+/** GetEntropyInput implementation (no conditionning function).
+
+  Cf. [3] 10.3.3 Get_entropy_input Constructions for Accessing Entropy Sources
+
+  @param [in]   DrbgHandle        The Drbg hanble.
+  @param [in]   MinEntropy        Minimum entropy.
+  @param [out]  EntropyBitsStream Stream containing the generated entropy.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_GET_ENTROPY_INTPUT) (
+  IN  DRBG_HANDLE  DrbgHandle,
+  IN  UINTN        MinEntropy,
+  OUT BIT_STREAM   **EntropyBitsStream
+  );
+
+/** Update algorithm.
+
+  CTR_DRBG_Update implementation.
+
+  Cf. [1] s10.2.1.2 The Update Function (CTR_DRBG_Update)
+
+  @param [in]       ProvidedData  The data to be used. This must be exactly
+                                  seedlen bits in length.
+  @param [in, out]  DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_UPDATE) (
+  IN      BIT_STREAM   *ProvidedData,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  );
+
+/** Reseed algorithm
+
+  @param [in]       EntropyInput  The string of bits obtained from the
+                                  randomness source.
+  @param [in]       AddInput      The additional input string received
+                                  from the consuming application. Note
+                                  that the length of the additional_input
+                                  string may be zero.
+  @param [in, out]  DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_RESEED) (
+  IN      BIT_STREAM   *EntropyInput,
+  IN      BIT_STREAM   *AddInput,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  );
+
+/** Instantiate algorithm.
+
+  CTR_DRBG_Instantiate_algorithm implementation.
+
+  Cf. [1] s10.2.1.3.1 Instantiation When a Derivation Function is Not Used
+
+  @param  [in]  EntropyInput      The string of bits obtained from the
+                                  randomness source.
+  @param  [in]  PersStrBitStream  The personalization string received from the
+                                  consuming application. Note that the length
+                                  of the personalization_string may be zero.
+                                  Note: PersStrBitStream must be initialized,
+                                  even with a NULL BitStream.
+  @param  [out] DrbgHandle        The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_INSTANTIATE) (
+  IN  BIT_STREAM   *EntropyInput,
+  IN  BIT_STREAM   *PersStrBitStream,
+  OUT DRBG_HANDLE  DrbgHandle
+  );
+
+/** Generate algorithm.
+
+  @param [in]       AddInput          The additional input string received from
+                                      the consuming application. Note that the
+                                      length of the additional_input string
+                                      may be zero.
+  @param [in]       RequestedNbBits   The number of pseudorandom bits to be
+                                      returned to the generate function.
+  @param [out]      RndBitStream      BitStream containing the random bits.
+  @param [in, out]  DrbgHandle        The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.
+  @retval EFI_NOT_READY           A reseed is required before the requested
+                                  pseudorandom bits can be generated.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_GENERATE_ALGORITHM) (
+  IN      BIT_STREAM   *AddInput,
+  IN      UINTN        RequestedNbBits,
+  OUT     BIT_STREAM   **RndBitStream,
+  IN OUT  DRBG_HANDLE  DrbgHandle
+  );
+
+/** Uninstantiate a DRBG instance.
+
+  @param  [in, out] DrbgHandle    The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+typedef EFI_STATUS EFIAPI (*DRBG_UNINSTANTIATE_FUNCTION) (
+  IN  OUT DRBG_HANDLE  DrbgHandle
+  );
+
+/** Drbg algo specific value definitions.
+*/
+typedef VOID *DRBG_ALGO_VALUE_DEFINITIONS;
+
+/** Drbg algo internal state values.
+*/
+typedef VOID *DRBG_ALGO_INTERNAL_STATE;
+
+/** Drbg values definitions.
+
+  Values are specific to a Drbg mechanism.
+  Cf. [1]:
+  Table 2: Definitions for Hash-Based DRBG Mechanisms
+  Table 3: Definitions for the CTR_DRBG
+*/
+typedef struct {
+  /// Supported security strengths.
+  // Not applicable.
+  /// Highest supported security strength.
+  SECURITY_STRENGTH              HighestSuppSecStrength;
+  /// Minimum entropy input length.
+  UINTN                          MinLen;
+  /// Maximum entropy input length.
+  UINTN                          MaxLen;
+  /// Maximum personalization string length.
+  UINTN                          MaxPersStrLen;
+  /// Maximum additional_input length.
+  UINTN                          MaxAddInputLen;
+  /// Maximum number of bits per request.
+  UINTN                          MaxNbBitsPerRequest;
+
+  /// Drbg algo specific value definitions.
+  DRBG_ALGO_VALUE_DEFINITIONS    DrbgAlgoVal;
+} DRBG_VALUE_DEFINITIONS;
+
+/** Internal state.
+
+  For a Drbg mechanism, values are specific to a Drbg instance.
+*/
+typedef struct {
+  // Administrative information.
+  /// Security strength
+  SECURITY_STRENGTH           SecStrength;
+  /// Prediction resistance flag
+  BOOLEAN                     PredResFlag;
+
+  /// Drbg algo specific internal state values.
+  DRBG_ALGO_INTERNAL_STATE    DrbgAlgoIntState;
+} DRBG_INTERNAL_STATE;
+
+/** Drbg info structure.
+
+  This structure is a Drbg instance. It contains information specific to the
+  Drbg mechanism chosen (e.g. the block size for Ctr mechanism) and instance
+  specific information (i.e. the internal state of the instance).
+*/
+struct DrbgInfo {
+  /// Drbg mechanism used.
+  DRBG_MECHANISM                 DrbgMechanism;
+  /// GUID of the algorithm used.
+  EFI_RNG_ALGORITHM              Algo;
+
+  /// Values specifics to the Drbg mechanism used.
+  DRBG_VALUE_DEFINITIONS         DrbgVal;
+
+  /// Internal state of the Drbg instance.
+  DRBG_INTERNAL_STATE            IntState;
+
+  /// Prediction resistance is supported for this Drbg instance.
+  BOOLEAN                        PredResSupported;
+  /// Reseeding is supported for this Drbg instance.
+  BOOLEAN                        ReseedSupported;
+
+  /// Callback to get a nonce.
+  DRBG_GET_NONCE                 DrbgGetNonce;
+  /// Callback to check the internal state.
+  DRBG_CHECK_INTERNAL_STATE      DrbgCheckInternalState;
+  /// Callback to get some entropy.
+  DRBG_GET_ENTROPY_INTPUT        DrbgGetEntropyInput;
+
+  /// Callback to update the instance
+  /// (according to the mechanism used).
+  DRBG_UPDATE                    DrbgUpdate;
+  /// Callback to reseed the instance
+  /// (according to the mechanism used).
+  DRBG_RESEED                    DrbgReseedAlgo;
+  /// Callback to instantiate the Drbg instance
+  /// (according to the mechanism used).
+  DRBG_INSTANTIATE               DrbgInstantiateAlgo;
+  /// Callback to generate random bits the instance
+  /// (according to the mechanism used).
+  DRBG_GENERATE_ALGORITHM        DrbgGenerateAlgo;
+  /// Callback to uninstantiate the Drbg instance
+  /// (according to the mechanism used).
+  DRBG_UNINSTANTIATE_FUNCTION    DrbgUninstantiateFn;
+};
+
+/** Drbg mechanism specific instantiation steps.
+
+  @param  [in, out] DrbgHandle     The Drbg handle.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+CtrInitHandle (
+  IN  OUT DRBG_HANDLE  DrbgHandle
+  );
+
+#endif // ARM_DRBG_LIB_INTERNAL_H_
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index 4820cecd0db8..5926a179d810 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -70,6 +70,7 @@ [Components]
   MdePkg/Library/BaseTrngLibNull/BaseTrngLibNull.inf
   MdePkg/Library/AesLibNull/AesLibNull.inf
   MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
+  MdePkg/Library/DrbgLib/DrbgLib.inf
 
   MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
   MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
-- 
2.25.1


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

* [PATCH RESEND v1 8/9] ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (6 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 7/9] MdePkg/DrbgLib: Add Drbg mechanism functions and module PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 9/9] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3971

The RngDxe will require both AesLib and DrbgLib for Arm.
Thus add the libraries to ArmVirtKvmTool.dsc.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 847dbdd2af2b..f14ec7a72a42 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -81,7 +81,9 @@ [LibraryClasses.common]
   HwInfoParserLib|DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
   DynamicPlatRepoLib|DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
 
+  AesLib|ArmPkg/Library/ArmAesLib/ArmAesLib.inf
   ArmMonitorLib|ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
+  DrbgLib|MdePkg/Library/DrbgLib/DrbgLib.inf
   TrngLib|ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
 
 [LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM]
-- 
2.25.1


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

* [PATCH RESEND v1 9/9] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (7 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 8/9] ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH RESEND v1 09/10] SecurityPkg: Update Securitypkg.ci.yaml PierreGondois
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

Make use of the new DrbgLib and advertise support for the
SP800-90 Ctr 256 bits Drbg. The algorithm will be used for
Arm and AArch64 arch.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  | 75 ++++++++++++++++++-
 .../RandomNumberGenerator/RngDxe/RngDxe.inf   |  1 +
 SecurityPkg/SecurityPkg.dsc                   |  2 +
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
index 4775252d30b6..400b0a5e9a7c 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
@@ -25,6 +25,7 @@
 #include <Library/ArmLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
+#include <Library/DrbgLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/RngLib.h>
 #include <Library/DebugLib.h>
@@ -39,7 +40,7 @@
 // populated only once.
 // The valid entry with the lowest index will be the default algorithm.
 //
-#define RNG_AVAILABLE_ALGO_MAX  2
+#define RNG_AVAILABLE_ALGO_MAX  3
 STATIC BOOLEAN            mAvailableAlgoArrayInit = FALSE;
 STATIC UINTN              mAvailableAlgoArrayCount;
 STATIC EFI_RNG_ALGORITHM  mAvailableAlgoArray[RNG_AVAILABLE_ALGO_MAX];
@@ -87,11 +88,78 @@ RngInitAvailableAlgoArray (
       sizeof (EFI_RNG_ALGORITHM)
       );
     mAvailableAlgoArrayCount++;
+
+    // SP800-90 Ctr 256 bits Drbg.
+    // Arm implementation is based on the Trng.
+    CopyMem (
+      &mAvailableAlgoArray[mAvailableAlgoArrayCount],
+      &gEfiRngAlgorithmSp80090Ctr256Guid,
+      sizeof (EFI_RNG_ALGORITHM)
+      );
+    mAvailableAlgoArrayCount++;
   }
 
   mAvailableAlgoArrayInit = TRUE;
 }
 
+/** Produces and returns an RNG value using a specified Drbg algorithm.
+
+  @param[in]  DrbgMechanism     The Drbg mechanism to use.
+  @param[in]  RNGValueLength    The length in bytes of the memory buffer pointed to by
+                                RNGValue. The driver shall return exactly this numbers of bytes.
+  @param[out] RNGValue          A caller-allocated memory buffer filled by the driver with the
+                                resulting RNG value.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RngGetDrbgVal (
+  IN  DRBG_MECHANISM  DrbgMechanism,
+  IN  UINTN           RNGValueLength,
+  OUT UINT8           *RNGValue
+  )
+{
+  EFI_STATUS   Status;
+  STATIC VOID  *DrbgHandle = NULL;
+
+  // Only instantiate once.
+  if (DrbgHandle == NULL) {
+    Status = DrbgInstantiateFn (
+               DrbgMechanism,
+               DrbgEntropyNoCondFn,
+               256,
+               FALSE,
+               NULL,
+               0,
+               &DrbgHandle
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+  }
+
+  // Check overflow.
+  if (RNGValueLength > (MAX_UINTN >> 3)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = DrbgGenerateFn (
+             256,
+             FALSE,
+             NULL,
+             0,
+             RNGValueLength << 3,
+             RNGValue,
+             DrbgHandle
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
 /**
   Produces and returns an RNG value using either the default or specified RNG algorithm.
 
@@ -163,6 +231,11 @@ FoundAlgo:
     return GenerateEntropy (RNGValueLength, RNGValue);
   }
 
+  // SP800-90 Ctr 256 bits Drbg
+  if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+    return RngGetDrbgVal (DrbgMechansimCtr, RNGValueLength, RNGValue);
+  }
+
   //
   // Other algorithms are unsupported by this driver.
   //
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 20752e71ac4e..c95e958e7f85 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -63,6 +63,7 @@ [LibraryClasses]
 
 [LibraryClasses.AARCH64, LibraryClasses.ARM]
   ArmLib
+  DrbgLib
   TrngLib
 
 [Guids]
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 779aa2a061a0..cc6d6de72cea 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -95,7 +95,9 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64]
   ArmHvcLib|ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf
 
   # RngDxe dependencies
+  AesLib|MdePkg/Library/AesLibNull/AesLibNull.inf
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
+  DrbgLib|MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
 
 [LibraryClasses.ARM]
   RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
-- 
2.25.1


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

* [PATCH RESEND v1 09/10] SecurityPkg: Update Securitypkg.ci.yaml
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (8 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 9/9] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-29 19:18 ` [PATCH v1 10/10] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
  2022-06-30  0:15 ` [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib Michael D Kinney
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

Add ArmPkg.dec as a valid dependency for the SecurityPkg.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 SecurityPkg/SecurityPkg.ci.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml
index 791214239899..08e98d713224 100644
--- a/SecurityPkg/SecurityPkg.ci.yaml
+++ b/SecurityPkg/SecurityPkg.ci.yaml
@@ -31,6 +31,7 @@
     },
     "DependencyCheck": {
         "AcceptableDependencies": [
+            "ArmPkg/ArmPkg.dec",
             "MdePkg/MdePkg.dec",
             "MdeModulePkg/MdeModulePkg.dec",
             "SecurityPkg/SecurityPkg.dec",
-- 
2.25.1


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

* [PATCH v1 10/10] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (9 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH RESEND v1 09/10] SecurityPkg: Update Securitypkg.ci.yaml PierreGondois
@ 2022-06-29 19:18 ` PierreGondois
  2022-06-30  0:15 ` [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib Michael D Kinney
  11 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-06-29 19:18 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Michael D Kinney, Liming Gao, Jiewen Yao, Jian J Wang

From: Pierre Gondois <pierre.gondois@arm.com>

Make use of the new DrbgLib and advertise support for the
SP800-90 Ctr 256 bits Drbg. The algorithm will be used for
Arm and AArch64 arch.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  | 75 ++++++++++++++++++-
 .../RandomNumberGenerator/RngDxe/RngDxe.inf   |  2 +
 SecurityPkg/SecurityPkg.dsc                   |  5 ++
 3 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
index 4775252d30b6..400b0a5e9a7c 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/ArmRngDxe.c
@@ -25,6 +25,7 @@
 #include <Library/ArmLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
+#include <Library/DrbgLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/RngLib.h>
 #include <Library/DebugLib.h>
@@ -39,7 +40,7 @@
 // populated only once.
 // The valid entry with the lowest index will be the default algorithm.
 //
-#define RNG_AVAILABLE_ALGO_MAX  2
+#define RNG_AVAILABLE_ALGO_MAX  3
 STATIC BOOLEAN            mAvailableAlgoArrayInit = FALSE;
 STATIC UINTN              mAvailableAlgoArrayCount;
 STATIC EFI_RNG_ALGORITHM  mAvailableAlgoArray[RNG_AVAILABLE_ALGO_MAX];
@@ -87,11 +88,78 @@ RngInitAvailableAlgoArray (
       sizeof (EFI_RNG_ALGORITHM)
       );
     mAvailableAlgoArrayCount++;
+
+    // SP800-90 Ctr 256 bits Drbg.
+    // Arm implementation is based on the Trng.
+    CopyMem (
+      &mAvailableAlgoArray[mAvailableAlgoArrayCount],
+      &gEfiRngAlgorithmSp80090Ctr256Guid,
+      sizeof (EFI_RNG_ALGORITHM)
+      );
+    mAvailableAlgoArrayCount++;
   }
 
   mAvailableAlgoArrayInit = TRUE;
 }
 
+/** Produces and returns an RNG value using a specified Drbg algorithm.
+
+  @param[in]  DrbgMechanism     The Drbg mechanism to use.
+  @param[in]  RNGValueLength    The length in bytes of the memory buffer pointed to by
+                                RNGValue. The driver shall return exactly this numbers of bytes.
+  @param[out] RNGValue          A caller-allocated memory buffer filled by the driver with the
+                                resulting RNG value.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RngGetDrbgVal (
+  IN  DRBG_MECHANISM  DrbgMechanism,
+  IN  UINTN           RNGValueLength,
+  OUT UINT8           *RNGValue
+  )
+{
+  EFI_STATUS   Status;
+  STATIC VOID  *DrbgHandle = NULL;
+
+  // Only instantiate once.
+  if (DrbgHandle == NULL) {
+    Status = DrbgInstantiateFn (
+               DrbgMechanism,
+               DrbgEntropyNoCondFn,
+               256,
+               FALSE,
+               NULL,
+               0,
+               &DrbgHandle
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+  }
+
+  // Check overflow.
+  if (RNGValueLength > (MAX_UINTN >> 3)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = DrbgGenerateFn (
+             256,
+             FALSE,
+             NULL,
+             0,
+             RNGValueLength << 3,
+             RNGValue,
+             DrbgHandle
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
 /**
   Produces and returns an RNG value using either the default or specified RNG algorithm.
 
@@ -163,6 +231,11 @@ FoundAlgo:
     return GenerateEntropy (RNGValueLength, RNGValue);
   }
 
+  // SP800-90 Ctr 256 bits Drbg
+  if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+    return RngGetDrbgVal (DrbgMechansimCtr, RNGValueLength, RNGValue);
+  }
+
   //
   // Other algorithms are unsupported by this driver.
   //
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 599a3085102d..c95e958e7f85 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -62,6 +62,8 @@ [LibraryClasses]
   RngLib
 
 [LibraryClasses.AARCH64, LibraryClasses.ARM]
+  ArmLib
+  DrbgLib
   TrngLib
 
 [Guids]
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 882d639489ea..cc6d6de72cea 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -94,6 +94,11 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64]
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
   ArmHvcLib|ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf
 
+  # RngDxe dependencies
+  AesLib|MdePkg/Library/AesLibNull/AesLibNull.inf
+  ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
+  DrbgLib|MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
+
 [LibraryClasses.ARM]
   RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
 
-- 
2.25.1


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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
                   ` (10 preceding siblings ...)
  2022-06-29 19:18 ` [PATCH v1 10/10] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
@ 2022-06-30  0:15 ` Michael D Kinney
  2022-06-30  1:16   ` Yao, Jiewen
  2022-07-01  8:30   ` PierreGondois
  11 siblings, 2 replies; 18+ messages in thread
From: Michael D Kinney @ 2022-06-30  0:15 UTC (permalink / raw)
  To: devel@edk2.groups.io, pierre.gondois@arm.com, Kinney, Michael D
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Yao, Jiewen, Wang, Jian J

Hi Pierre,

Can you add to the Patch #0 Summary and the BZ the difference
between the existing RngLib and this new DrbgLib?

Would you recommend one be implement on top of the other?

Really glad to see test vectors were used to verify correctness.
Can you consider adding formal unit tests using the UnitTestFrameworkPkg
with those test vectors so a unit test failure would be generated if
maintenance is performed in the future that changes the behavior?

Thanks,

Mike

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of PierreGondois
> Sent: Wednesday, June 29, 2022 12:19 PM
> To: devel@edk2.groups.io
> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Yao,
> Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> 
> From: Pierre Gondois <pierre.gondois@arm.com>
> 
> Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
> 
> Add support for a Deterministic Random Bits Generator (Drbg). The
> specifications used are the following:
> 
> - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
> 	  for Random Number Generation Using Deterministic Random Bit Generators.
> 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
> - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
> 	  Sources Used for Random Bit Generation.
> 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
> - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
> 	  Random Bit Generator (RBG) Constructions.
> 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
> - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
> 	  Recommendation for Key Management:Part 1 - General.
> 
> The test vectors available in the CTR_DRBG_AES256 sections of
> https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/CTR_DRBG_noDF.pdf
> were used for validation.
> 
> This patch-set can seen at:
> https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
> 
> This patch has the following dependency:
> - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG interface
>   https://edk2.groups.io/g/devel/message/90845
> - [PATCH v1 0/7] Add AesLib and ArmAesLib
>   https://edk2.groups.io/g/devel/message/90878
> 
> Pierre Gondois (9):
>   MdePkg/DrbgLib: Drbg library interface definition
>   MdePkg/DrbgLib: Add NULL instance of Drbg Library
>   MdePkg/DrbgLib: Add BitStream implementation
>   MdePkg/DrbgLib: Add Get_entropy_input() implementation
>   MdePkg/DrbgLib: Add common wrappers
>   MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
>   MdePkg/DrbgLib: Add Drbg mechanism functions and module
>   ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
>   SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
> 
>  ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
>  MdePkg/Include/Library/DrbgLib.h              |  172 +++
>  MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
>  MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
>  MdePkg/Library/DrbgLib/Common.c               |  249 ++++
>  MdePkg/Library/DrbgLib/Common.h               |   74 ++
>  MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
>  MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
>  MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
>  MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
>  MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
>  MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
>  MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
>  MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
>  MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
>  MdePkg/MdePkg.dec                             |    4 +
>  MdePkg/MdePkg.dsc                             |    2 +
>  .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
>  .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
>  SecurityPkg/SecurityPkg.dsc                   |    2 +
>  20 files changed, 4342 insertions(+), 1 deletion(-)
>  create mode 100644 MdePkg/Include/Library/DrbgLib.h
>  create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
>  create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
>  create mode 100644 MdePkg/Library/DrbgLib/Common.c
>  create mode 100644 MdePkg/Library/DrbgLib/Common.h
>  create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
>  create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
>  create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
>  create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
>  create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
>  create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
>  create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
>  create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
>  create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
> 
> --
> 2.25.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#90898): https://edk2.groups.io/g/devel/message/90898
> Mute This Topic: https://groups.io/mt/92072283/1643496
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [michael.d.kinney@intel.com]
> -=-=-=-=-=-=
> 


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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-06-30  0:15 ` [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib Michael D Kinney
@ 2022-06-30  1:16   ` Yao, Jiewen
  2022-07-01  9:49     ` PierreGondois
  2022-07-01  8:30   ` PierreGondois
  1 sibling, 1 reply; 18+ messages in thread
From: Yao, Jiewen @ 2022-06-30  1:16 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io, pierre.gondois@arm.com
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Wang, Jian J

More question:
Please educate me how you plan to include DrbgLib to openssl?
Currently, it is using RngLib.
https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L634?

Thank you
Yao Jiewen

> -----Original Message-----
> From: Kinney, Michael D <michael.d.kinney@intel.com>
> Sent: Thursday, June 30, 2022 8:16 AM
> To: devel@edk2.groups.io; pierre.gondois@arm.com; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
> Jian J <jian.j.wang@intel.com>
> Subject: RE: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> 
> Hi Pierre,
> 
> Can you add to the Patch #0 Summary and the BZ the difference
> between the existing RngLib and this new DrbgLib?
> 
> Would you recommend one be implement on top of the other?
> 
> Really glad to see test vectors were used to verify correctness.
> Can you consider adding formal unit tests using the UnitTestFrameworkPkg
> with those test vectors so a unit test failure would be generated if
> maintenance is performed in the future that changes the behavior?
> 
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> PierreGondois
> > Sent: Wednesday, June 29, 2022 12:19 PM
> > To: devel@edk2.groups.io
> > Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> > Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Yao,
> > Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> > Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> >
> > From: Pierre Gondois <pierre.gondois@arm.com>
> >
> > Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
> >
> > Add support for a Deterministic Random Bits Generator (Drbg). The
> > specifications used are the following:
> >
> > - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
> > 	  for Random Number Generation Using Deterministic Random Bit
> Generators.
> > 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
> > - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
> > 	  Sources Used for Random Bit Generation.
> > 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
> > - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
> > 	  Random Bit Generator (RBG) Constructions.
> > 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
> > - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
> > 	  Recommendation for Key Management:Part 1 - General.
> >
> > The test vectors available in the CTR_DRBG_AES256 sections of
> > https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-
> Guidelines/documents/examples/CTR_DRBG_noDF.pdf
> > were used for validation.
> >
> > This patch-set can seen at:
> > https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
> >
> > This patch has the following dependency:
> > - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG interface
> >   https://edk2.groups.io/g/devel/message/90845
> > - [PATCH v1 0/7] Add AesLib and ArmAesLib
> >   https://edk2.groups.io/g/devel/message/90878
> >
> > Pierre Gondois (9):
> >   MdePkg/DrbgLib: Drbg library interface definition
> >   MdePkg/DrbgLib: Add NULL instance of Drbg Library
> >   MdePkg/DrbgLib: Add BitStream implementation
> >   MdePkg/DrbgLib: Add Get_entropy_input() implementation
> >   MdePkg/DrbgLib: Add common wrappers
> >   MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
> >   MdePkg/DrbgLib: Add Drbg mechanism functions and module
> >   ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
> >   SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
> >
> >  ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
> >  MdePkg/Include/Library/DrbgLib.h              |  172 +++
> >  MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
> >  MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
> >  MdePkg/Library/DrbgLib/Common.c               |  249 ++++
> >  MdePkg/Library/DrbgLib/Common.h               |   74 ++
> >  MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
> >  MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
> >  MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
> >  MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
> >  MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
> >  MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
> >  MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
> >  MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
> >  MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
> >  MdePkg/MdePkg.dec                             |    4 +
> >  MdePkg/MdePkg.dsc                             |    2 +
> >  .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
> >  .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
> >  SecurityPkg/SecurityPkg.dsc                   |    2 +
> >  20 files changed, 4342 insertions(+), 1 deletion(-)
> >  create mode 100644 MdePkg/Include/Library/DrbgLib.h
> >  create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
> >  create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
> >  create mode 100644 MdePkg/Library/DrbgLib/Common.c
> >  create mode 100644 MdePkg/Library/DrbgLib/Common.h
> >  create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
> >  create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
> >  create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
> >  create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
> >  create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
> >  create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
> >  create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
> >  create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
> >  create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
> >
> > --
> > 2.25.1
> >
> >
> >
> > -=-=-=-=-=-=
> > Groups.io Links: You receive all messages sent to this group.
> > View/Reply Online (#90898): https://edk2.groups.io/g/devel/message/90898
> > Mute This Topic: https://groups.io/mt/92072283/1643496
> > Group Owner: devel+owner@edk2.groups.io
> > Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [michael.d.kinney@intel.com]
> > -=-=-=-=-=-=
> >


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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-06-30  0:15 ` [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib Michael D Kinney
  2022-06-30  1:16   ` Yao, Jiewen
@ 2022-07-01  8:30   ` PierreGondois
  1 sibling, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-07-01  8:30 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Yao, Jiewen, Wang, Jian J

Hello Mike,

On 6/30/22 02:15, Kinney, Michael D wrote:
> Hi Pierre,
> 
> Can you add to the Patch #0 Summary and the BZ the difference
> between the existing RngLib and this new DrbgLib?

There was a discussion in late 2020 about the DrbgLib at:
https://edk2.groups.io/g/devel/topic/78823009#71619

The relation between the RngLib and the DrbgLib is available
in slide 11 of:
https://edk2.groups.io/g/devel/files/Designs/2021/0116/EDKII%20-%20Proposed%20update%20to%20RNG%20implementation.pdf


I will the same details in the BZ.

> 
> Would you recommend one be implement on top of the other?

The DrbgLib requires to have a True Random Number Generator for
its entropy source, which I don't think the RngLib is guaranteed to be.
The DrbgLib should rely on a TrngLib instead.

> 
> Really glad to see test vectors were used to verify correctness.
> Can you consider adding formal unit tests using the UnitTestFrameworkPkg
> with those test vectors so a unit test failure would be generated if
> maintenance is performed in the future that changes the behavior?

Yes sure, I will add these tests to the UnitTestFrameworkPkg.

Regards,
Pierre

> 
> Thanks,
> 
> Mike
> 
>> -----Original Message-----
>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of PierreGondois
>> Sent: Wednesday, June 29, 2022 12:19 PM
>> To: devel@edk2.groups.io
>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>> Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Yao,
>> Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
>> Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>
>> From: Pierre Gondois <pierre.gondois@arm.com>
>>
>> Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
>>
>> Add support for a Deterministic Random Bits Generator (Drbg). The
>> specifications used are the following:
>>
>> - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
>> 	  for Random Number Generation Using Deterministic Random Bit Generators.
>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
>> - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
>> 	  Sources Used for Random Bit Generation.
>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
>> - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
>> 	  Random Bit Generator (RBG) Constructions.
>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
>> - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
>> 	  Recommendation for Key Management:Part 1 - General.
>>
>> The test vectors available in the CTR_DRBG_AES256 sections of
>> https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/CTR_DRBG_noDF.pdf
>> were used for validation.
>>
>> This patch-set can seen at:
>> https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
>>
>> This patch has the following dependency:
>> - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG interface
>>    https://edk2.groups.io/g/devel/message/90845
>> - [PATCH v1 0/7] Add AesLib and ArmAesLib
>>    https://edk2.groups.io/g/devel/message/90878
>>
>> Pierre Gondois (9):
>>    MdePkg/DrbgLib: Drbg library interface definition
>>    MdePkg/DrbgLib: Add NULL instance of Drbg Library
>>    MdePkg/DrbgLib: Add BitStream implementation
>>    MdePkg/DrbgLib: Add Get_entropy_input() implementation
>>    MdePkg/DrbgLib: Add common wrappers
>>    MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
>>    MdePkg/DrbgLib: Add Drbg mechanism functions and module
>>    ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
>>    SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
>>
>>   ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
>>   MdePkg/Include/Library/DrbgLib.h              |  172 +++
>>   MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
>>   MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
>>   MdePkg/Library/DrbgLib/Common.c               |  249 ++++
>>   MdePkg/Library/DrbgLib/Common.h               |   74 ++
>>   MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
>>   MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
>>   MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
>>   MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
>>   MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
>>   MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
>>   MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
>>   MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
>>   MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
>>   MdePkg/MdePkg.dec                             |    4 +
>>   MdePkg/MdePkg.dsc                             |    2 +
>>   .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
>>   .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
>>   SecurityPkg/SecurityPkg.dsc                   |    2 +
>>   20 files changed, 4342 insertions(+), 1 deletion(-)
>>   create mode 100644 MdePkg/Include/Library/DrbgLib.h
>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
>>   create mode 100644 MdePkg/Library/DrbgLib/Common.c
>>   create mode 100644 MdePkg/Library/DrbgLib/Common.h
>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
>>
>> --
>> 2.25.1
>>
>>
>>
>> -=-=-=-=-=-=
>> Groups.io Links: You receive all messages sent to this group.
>> View/Reply Online (#90898): https://edk2.groups.io/g/devel/message/90898
>> Mute This Topic: https://groups.io/mt/92072283/1643496
>> Group Owner: devel+owner@edk2.groups.io
>> Unsubscribe: https://edk2.groups.io/g/devel/unsub [michael.d.kinney@intel.com]
>> -=-=-=-=-=-=
>>
> 

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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-06-30  1:16   ` Yao, Jiewen
@ 2022-07-01  9:49     ` PierreGondois
  2022-07-02  6:25       ` Yao, Jiewen
  0 siblings, 1 reply; 18+ messages in thread
From: PierreGondois @ 2022-07-01  9:49 UTC (permalink / raw)
  To: Yao, Jiewen, Kinney, Michael D, devel@edk2.groups.io
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Wang, Jian J

Hello Yao,
On 6/30/22 03:16, Yao, Jiewen wrote:
> More question:
> Please educate me how you plan to include DrbgLib to openssl?
> Currently, it is using RngLib.
> https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/OpensslLib.inf#L634?

There was a discussion about the DrbgLib in late 2020 at:
https://edk2.groups.io/g/devel/topic/78823009#71619

The interraction between between all the libraries is described in slide 11 of:
https://edk2.groups.io/g/devel/files/Designs/2021/0116/EDKII%20-%20Proposed%20update%20to%20RNG%20implementation.pdf

The OpensslLib relies on the RngLib because of this function call:
https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/rand_pool.c#L49
Based on the slide 11, it is possible to have a RngLib implementation
using the DrbgLib either through RngDxeLib or through a new
RngLib|RngDrbgLib.

Regards,
Pierre

> 
> Thank you
> Yao Jiewen
> 
>> -----Original Message-----
>> From: Kinney, Michael D <michael.d.kinney@intel.com>
>> Sent: Thursday, June 30, 2022 8:16 AM
>> To: devel@edk2.groups.io; pierre.gondois@arm.com; Kinney, Michael D
>> <michael.d.kinney@intel.com>
>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
>> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
>> <gaoliming@byosoft.com.cn>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
>> Jian J <jian.j.wang@intel.com>
>> Subject: RE: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>
>> Hi Pierre,
>>
>> Can you add to the Patch #0 Summary and the BZ the difference
>> between the existing RngLib and this new DrbgLib?
>>
>> Would you recommend one be implement on top of the other?
>>
>> Really glad to see test vectors were used to verify correctness.
>> Can you consider adding formal unit tests using the UnitTestFrameworkPkg
>> with those test vectors so a unit test failure would be generated if
>> maintenance is performed in the future that changes the behavior?
>>
>> Thanks,
>>
>> Mike
>>
>>> -----Original Message-----
>>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
>> PierreGondois
>>> Sent: Wednesday, June 29, 2022 12:19 PM
>>> To: devel@edk2.groups.io
>>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
>> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>>> Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D
>> <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Yao,
>>> Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
>>> Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>>
>>> From: Pierre Gondois <pierre.gondois@arm.com>
>>>
>>> Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
>>>
>>> Add support for a Deterministic Random Bits Generator (Drbg). The
>>> specifications used are the following:
>>>
>>> - [1] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation
>>> 	  for Random Number Generation Using Deterministic Random Bit
>> Generators.
>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
>>> - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
>>> 	  Sources Used for Random Bit Generation.
>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
>>> - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
>>> 	  Random Bit Generator (RBG) Constructions.
>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
>>> - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
>>> 	  Recommendation for Key Management:Part 1 - General.
>>>
>>> The test vectors available in the CTR_DRBG_AES256 sections of
>>> https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-
>> Guidelines/documents/examples/CTR_DRBG_noDF.pdf
>>> were used for validation.
>>>
>>> This patch-set can seen at:
>>> https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
>>>
>>> This patch has the following dependency:
>>> - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG interface
>>>    https://edk2.groups.io/g/devel/message/90845
>>> - [PATCH v1 0/7] Add AesLib and ArmAesLib
>>>    https://edk2.groups.io/g/devel/message/90878
>>>
>>> Pierre Gondois (9):
>>>    MdePkg/DrbgLib: Drbg library interface definition
>>>    MdePkg/DrbgLib: Add NULL instance of Drbg Library
>>>    MdePkg/DrbgLib: Add BitStream implementation
>>>    MdePkg/DrbgLib: Add Get_entropy_input() implementation
>>>    MdePkg/DrbgLib: Add common wrappers
>>>    MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
>>>    MdePkg/DrbgLib: Add Drbg mechanism functions and module
>>>    ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
>>>    SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
>>>
>>>   ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
>>>   MdePkg/Include/Library/DrbgLib.h              |  172 +++
>>>   MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
>>>   MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
>>>   MdePkg/Library/DrbgLib/Common.c               |  249 ++++
>>>   MdePkg/Library/DrbgLib/Common.h               |   74 ++
>>>   MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
>>>   MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
>>>   MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
>>>   MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
>>>   MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
>>>   MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
>>>   MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
>>>   MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
>>>   MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
>>>   MdePkg/MdePkg.dec                             |    4 +
>>>   MdePkg/MdePkg.dsc                             |    2 +
>>>   .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
>>>   .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
>>>   SecurityPkg/SecurityPkg.dsc                   |    2 +
>>>   20 files changed, 4342 insertions(+), 1 deletion(-)
>>>   create mode 100644 MdePkg/Include/Library/DrbgLib.h
>>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
>>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
>>>   create mode 100644 MdePkg/Library/DrbgLib/Common.c
>>>   create mode 100644 MdePkg/Library/DrbgLib/Common.h
>>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
>>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
>>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
>>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
>>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
>>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
>>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
>>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
>>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
>>>
>>> --
>>> 2.25.1
>>>
>>>
>>>
>>> -=-=-=-=-=-=
>>> Groups.io Links: You receive all messages sent to this group.
>>> View/Reply Online (#90898): https://edk2.groups.io/g/devel/message/90898
>>> Mute This Topic: https://groups.io/mt/92072283/1643496
>>> Group Owner: devel+owner@edk2.groups.io
>>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
>> [michael.d.kinney@intel.com]
>>> -=-=-=-=-=-=
>>>
> 

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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-07-01  9:49     ` PierreGondois
@ 2022-07-02  6:25       ` Yao, Jiewen
  2022-07-04 13:18         ` PierreGondois
  0 siblings, 1 reply; 18+ messages in thread
From: Yao, Jiewen @ 2022-07-02  6:25 UTC (permalink / raw)
  To: Pierre Gondois, Kinney, Michael D, devel@edk2.groups.io
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Wang, Jian J

Thanks for the PPT.

It is helpful for me to understand the background. Some questions and suggestions:

1) The PPT jumps from current status (page 7~9) to proposed updates (page 10~12) directly.
I am not sure what is the problem statement. Why we need do the new proposal?

2) Page 11 shows AesLib|AesNiInstructionLib (x64).
Is that something you want to do?
Since X64 already have RDSEED and RDRAND instruction, why this is needed for X64? 

3) Page 11 shows AesLib|SoftAesLib.
Many AES software implementation is vulnerable to side channel attack. 
Will side channel attack be under consideration?
What is security property you want to maintain with the AesLib API and SoftAesLib implementation?
Or this AesLib interface is only for DrbgLib?
What is the API design goal?

4) Page 11 shows that RngLib is still the only public interface.
My concern is that to introduce more RngLib related lib just confuses the consumer.

I already got lots of questions - "We have RngLib and CrytpoLib/RandomBytes(), which one I should use to generate 8 bytes random data?"

Introducing more lib instance means we will have more questions from consumers in the future, such as
A) We have RngLib, TrngLib, DrbgLib, which one I should use to get random data?
B) We have AesLib and CryptoLib/AesXXX() function, which one I should use to encrypt my data?

So far, I don’t see the immediate need for X64 platform, I would like to recommend put them to ArmPkg only.
As such, the generic consumer only knows the RngLib interface.

Thank you
Yao Jiewen


> -----Original Message-----
> From: Pierre Gondois <pierre.gondois@arm.com>
> Sent: Friday, July 1, 2022 5:50 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; devel@edk2.groups.io
> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Wang, Jian J <jian.j.wang@intel.com>
> Subject: Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> 
> Hello Yao,
> On 6/30/22 03:16, Yao, Jiewen wrote:
> > More question:
> > Please educate me how you plan to include DrbgLib to openssl?
> > Currently, it is using RngLib.
> >
> https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/
> OpensslLib.inf#L634?
> 
> There was a discussion about the DrbgLib in late 2020 at:
> https://edk2.groups.io/g/devel/topic/78823009#71619
> 
> The interraction between between all the libraries is described in slide 11 of:
> https://edk2.groups.io/g/devel/files/Designs/2021/0116/EDKII%20-
> %20Proposed%20update%20to%20RNG%20implementation.pdf
> 
> The OpensslLib relies on the RngLib because of this function call:
> https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/
> rand_pool.c#L49
> Based on the slide 11, it is possible to have a RngLib implementation
> using the DrbgLib either through RngDxeLib or through a new
> RngLib|RngDrbgLib.
> 
> Regards,
> Pierre
> 
> >
> > Thank you
> > Yao Jiewen
> >
> >> -----Original Message-----
> >> From: Kinney, Michael D <michael.d.kinney@intel.com>
> >> Sent: Thursday, June 30, 2022 8:16 AM
> >> To: devel@edk2.groups.io; pierre.gondois@arm.com; Kinney, Michael D
> >> <michael.d.kinney@intel.com>
> >> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
> >> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> >> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
> >> <gaoliming@byosoft.com.cn>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
> >> Jian J <jian.j.wang@intel.com>
> >> Subject: RE: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> >>
> >> Hi Pierre,
> >>
> >> Can you add to the Patch #0 Summary and the BZ the difference
> >> between the existing RngLib and this new DrbgLib?
> >>
> >> Would you recommend one be implement on top of the other?
> >>
> >> Really glad to see test vectors were used to verify correctness.
> >> Can you consider adding formal unit tests using the UnitTestFrameworkPkg
> >> with those test vectors so a unit test failure would be generated if
> >> maintenance is performed in the future that changes the behavior?
> >>
> >> Thanks,
> >>
> >> Mike
> >>
> >>> -----Original Message-----
> >>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> >> PierreGondois
> >>> Sent: Wednesday, June 29, 2022 12:19 PM
> >>> To: devel@edk2.groups.io
> >>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
> >> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> >>> Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D
> >> <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>;
> Yao,
> >>> Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> >>> Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
> >>>
> >>> From: Pierre Gondois <pierre.gondois@arm.com>
> >>>
> >>> Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
> >>>
> >>> Add support for a Deterministic Random Bits Generator (Drbg). The
> >>> specifications used are the following:
> >>>
> >>> - [1] NIST Special Publication 800-90A Revision 1, June 2015,
> Recommendation
> >>> 	  for Random Number Generation Using Deterministic Random Bit
> >> Generators.
> >>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
> >>> - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
> >>> 	  Sources Used for Random Bit Generation.
> >>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
> >>> - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
> >>> 	  Random Bit Generator (RBG) Constructions.
> >>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
> >>> - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
> >>> 	  Recommendation for Key Management:Part 1 - General.
> >>>
> >>> The test vectors available in the CTR_DRBG_AES256 sections of
> >>> https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-
> >> Guidelines/documents/examples/CTR_DRBG_noDF.pdf
> >>> were used for validation.
> >>>
> >>> This patch-set can seen at:
> >>> https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
> >>>
> >>> This patch has the following dependency:
> >>> - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG
> interface
> >>>    https://edk2.groups.io/g/devel/message/90845
> >>> - [PATCH v1 0/7] Add AesLib and ArmAesLib
> >>>    https://edk2.groups.io/g/devel/message/90878
> >>>
> >>> Pierre Gondois (9):
> >>>    MdePkg/DrbgLib: Drbg library interface definition
> >>>    MdePkg/DrbgLib: Add NULL instance of Drbg Library
> >>>    MdePkg/DrbgLib: Add BitStream implementation
> >>>    MdePkg/DrbgLib: Add Get_entropy_input() implementation
> >>>    MdePkg/DrbgLib: Add common wrappers
> >>>    MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
> >>>    MdePkg/DrbgLib: Add Drbg mechanism functions and module
> >>>    ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
> >>>    SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
> >>>
> >>>   ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
> >>>   MdePkg/Include/Library/DrbgLib.h              |  172 +++
> >>>   MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
> >>>   MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
> >>>   MdePkg/Library/DrbgLib/Common.c               |  249 ++++
> >>>   MdePkg/Library/DrbgLib/Common.h               |   74 ++
> >>>   MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
> >>>   MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
> >>>   MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
> >>>   MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
> >>>   MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
> >>>   MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
> >>>   MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
> >>>   MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
> >>>   MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
> >>>   MdePkg/MdePkg.dec                             |    4 +
> >>>   MdePkg/MdePkg.dsc                             |    2 +
> >>>   .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
> >>>   .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
> >>>   SecurityPkg/SecurityPkg.dsc                   |    2 +
> >>>   20 files changed, 4342 insertions(+), 1 deletion(-)
> >>>   create mode 100644 MdePkg/Include/Library/DrbgLib.h
> >>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
> >>>   create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
> >>>   create mode 100644 MdePkg/Library/DrbgLib/Common.c
> >>>   create mode 100644 MdePkg/Library/DrbgLib/Common.h
> >>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
> >>>   create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
> >>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
> >>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
> >>>   create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
> >>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
> >>>   create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
> >>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
> >>>   create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
> >>>
> >>> --
> >>> 2.25.1
> >>>
> >>>
> >>>
> >>> -=-=-=-=-=-=
> >>> Groups.io Links: You receive all messages sent to this group.
> >>> View/Reply Online (#90898):
> https://edk2.groups.io/g/devel/message/90898
> >>> Mute This Topic: https://groups.io/mt/92072283/1643496
> >>> Group Owner: devel+owner@edk2.groups.io
> >>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> >> [michael.d.kinney@intel.com]
> >>> -=-=-=-=-=-=
> >>>
> >

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

* Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
  2022-07-02  6:25       ` Yao, Jiewen
@ 2022-07-04 13:18         ` PierreGondois
  0 siblings, 0 replies; 18+ messages in thread
From: PierreGondois @ 2022-07-04 13:18 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Sami Mujawar, Leif Lindholm, Ard Biesheuvel, Rebecca Cran,
	Gao, Liming, Wang, Jian J, Kinney, Michael D



On 7/2/22 08:25, Yao, Jiewen wrote:
> Thanks for the PPT.
> 
> It is helpful for me to understand the background. Some questions and suggestions:
> 
> 1) The PPT jumps from current status (page 7~9) to proposed updates (page 10~12) directly.
> I am not sure what is the problem statement. Why we need do the new proposal?

The goal is to have a Drbg and its advantages:
- Reproducibility
- A Drbg is supposed to be faster than a Trng
- Just have a Drbg when there is none

Arm (resp. Intel) has specific instructions to get a deterministic/true
random number: RNRD/RNDRRS (resp. RDRAND/RDSEED). Some platforms might not
support these instructions, but still have a TRNG IP.

Another point is that a Drbg library would allow to choose which Drbg
to use. The patch-set currently add support for a Aes-Ctr Drbg.

> 
> 2) Page 11 shows AesLib|AesNiInstructionLib (x64).
> Is that something you want to do?

We didn't plan to add Intel's implementation, but the AesLib interface should
allow to do it seamlessly.

> Since X64 already have RDSEED and RDRAND instruction, why this is needed for X64?

Cf. 1), Intel should also benefit from the DrbgLib (provided that Intels's
AesLib/TrngLib libraries are implemented).

> 
> 3) Page 11 shows AesLib|SoftAesLib.
> Many AES software implementation is vulnerable to side channel attack.
> Will side channel attack be under consideration?

Side channel attack haven't been studied yet for this implementation. Do
you have specific concerns ?

> What is security property you want to maintain with the AesLib API and SoftAesLib implementation?
> Or this AesLib interface is only for DrbgLib?
> What is the API design goal?

The design goal is to have an AES basic block encryption interface.

The AesLib would also be used in an AES CBC implementation (not done yet).
The OpensslLib already provides an AES CBC implementation, but it is outside
of edk2 project scope.

> 
> 4) Page 11 shows that RngLib is still the only public interface.
> My concern is that to introduce more RngLib related lib just confuses the consumer.
> 
> I already got lots of questions - "We have RngLib and CrytpoLib/RandomBytes(), which one I should use to generate 8 bytes random data?"
> 
> Introducing more lib instance means we will have more questions from consumers in the future, such as
> A) We have RngLib, TrngLib, DrbgLib, which one I should use to get random data?
> B) We have AesLib and CryptoLib/AesXXX() function, which one I should use to encrypt my data?

I understand your concern. If we added some documentation about the different
options for each library implementation, would it be better ?

> 
> So far, I don’t see the immediate need for X64 platform, I would like to recommend put them to ArmPkg only.
> As such, the generic consumer only knows the RngLib interface.

Are you talking about the library interface or/and implementation ?
I will try to see if the ArmPkg maintainers are ok with that.

Thanks for the involvement,
Regards,
Pierre

> 
> Thank you
> Yao Jiewen
> 
> 
>> -----Original Message-----
>> From: Pierre Gondois <pierre.gondois@arm.com>
>> Sent: Friday, July 1, 2022 5:50 PM
>> To: Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
>> <michael.d.kinney@intel.com>; devel@edk2.groups.io
>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
>> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
>> <gaoliming@byosoft.com.cn>; Wang, Jian J <jian.j.wang@intel.com>
>> Subject: Re: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>
>> Hello Yao,
>> On 6/30/22 03:16, Yao, Jiewen wrote:
>>> More question:
>>> Please educate me how you plan to include DrbgLib to openssl?
>>> Currently, it is using RngLib.
>>>
>> https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/
>> OpensslLib.inf#L634?
>>
>> There was a discussion about the DrbgLib in late 2020 at:
>> https://edk2.groups.io/g/devel/topic/78823009#71619
>>
>> The interraction between between all the libraries is described in slide 11 of:
>> https://edk2.groups.io/g/devel/files/Designs/2021/0116/EDKII%20-
>> %20Proposed%20update%20to%20RNG%20implementation.pdf
>>
>> The OpensslLib relies on the RngLib because of this function call:
>> https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/OpensslLib/
>> rand_pool.c#L49
>> Based on the slide 11, it is possible to have a RngLib implementation
>> using the DrbgLib either through RngDxeLib or through a new
>> RngLib|RngDrbgLib.
>>
>> Regards,
>> Pierre
>>
>>>
>>> Thank you
>>> Yao Jiewen
>>>
>>>> -----Original Message-----
>>>> From: Kinney, Michael D <michael.d.kinney@intel.com>
>>>> Sent: Thursday, June 30, 2022 8:16 AM
>>>> To: devel@edk2.groups.io; pierre.gondois@arm.com; Kinney, Michael D
>>>> <michael.d.kinney@intel.com>
>>>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
>>>> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>>>> Rebecca Cran <rebecca@bsdio.com>; Gao, Liming
>>>> <gaoliming@byosoft.com.cn>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
>>>> Jian J <jian.j.wang@intel.com>
>>>> Subject: RE: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>>>
>>>> Hi Pierre,
>>>>
>>>> Can you add to the Patch #0 Summary and the BZ the difference
>>>> between the existing RngLib and this new DrbgLib?
>>>>
>>>> Would you recommend one be implement on top of the other?
>>>>
>>>> Really glad to see test vectors were used to verify correctness.
>>>> Can you consider adding formal unit tests using the UnitTestFrameworkPkg
>>>> with those test vectors so a unit test failure would be generated if
>>>> maintenance is performed in the future that changes the behavior?
>>>>
>>>> Thanks,
>>>>
>>>> Mike
>>>>
>>>>> -----Original Message-----
>>>>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
>>>> PierreGondois
>>>>> Sent: Wednesday, June 29, 2022 12:19 PM
>>>>> To: devel@edk2.groups.io
>>>>> Cc: Sami Mujawar <sami.mujawar@arm.com>; Leif Lindholm
>>>> <quic_llindhol@quicinc.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
>>>>> Rebecca Cran <rebecca@bsdio.com>; Kinney, Michael D
>>>> <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>;
>> Yao,
>>>>> Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
>>>>> Subject: [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib
>>>>>
>>>>> From: Pierre Gondois <pierre.gondois@arm.com>
>>>>>
>>>>> Bugzilla: Bug 3971 (https://bugzilla.tianocore.org/show_bug.cgi?id=3971)
>>>>>
>>>>> Add support for a Deterministic Random Bits Generator (Drbg). The
>>>>> specifications used are the following:
>>>>>
>>>>> - [1] NIST Special Publication 800-90A Revision 1, June 2015,
>> Recommendation
>>>>> 	  for Random Number Generation Using Deterministic Random Bit
>>>> Generators.
>>>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
>>>>> - [2] NIST Special Publication 800-90B, Recommendation for the Entropy
>>>>> 	  Sources Used for Random Bit Generation.
>>>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90b/final)
>>>>> - [3] (Second Draft) NIST Special Publication 800-90C, Recommendation for
>>>>> 	  Random Bit Generator (RBG) Constructions.
>>>>> 	  (https://csrc.nist.gov/publications/detail/sp/800-90c/draft)
>>>>> - [4] NIST Special Publication 800-57 Part 1 Revision 5, May 2020,
>>>>> 	  Recommendation for Key Management:Part 1 - General.
>>>>>
>>>>> The test vectors available in the CTR_DRBG_AES256 sections of
>>>>> https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-
>>>> Guidelines/documents/examples/CTR_DRBG_noDF.pdf
>>>>> were used for validation.
>>>>>
>>>>> This patch-set can seen at:
>>>>> https://github.com/PierreARM/edk2/tree/Arm_Drbg_v1
>>>>>
>>>>> This patch has the following dependency:
>>>>> - [PATCH v3 00/22] Add Raw algorithm support using Arm FW-TRNG
>> interface
>>>>>     https://edk2.groups.io/g/devel/message/90845
>>>>> - [PATCH v1 0/7] Add AesLib and ArmAesLib
>>>>>     https://edk2.groups.io/g/devel/message/90878
>>>>>
>>>>> Pierre Gondois (9):
>>>>>     MdePkg/DrbgLib: Drbg library interface definition
>>>>>     MdePkg/DrbgLib: Add NULL instance of Drbg Library
>>>>>     MdePkg/DrbgLib: Add BitStream implementation
>>>>>     MdePkg/DrbgLib: Add Get_entropy_input() implementation
>>>>>     MdePkg/DrbgLib: Add common wrappers
>>>>>     MdePkg/DrbgLib: Add Ctr Drbg mechanism functions
>>>>>     MdePkg/DrbgLib: Add Drbg mechanism functions and module
>>>>>     ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe
>>>>>     SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm
>>>>>
>>>>>    ArmVirtPkg/ArmVirtKvmTool.dsc                 |    2 +
>>>>>    MdePkg/Include/Library/DrbgLib.h              |  172 +++
>>>>>    MdePkg/Library/DrbgLib/BitStream.c            | 1114 +++++++++++++++++
>>>>>    MdePkg/Library/DrbgLib/BitStream.h            |  366 ++++++
>>>>>    MdePkg/Library/DrbgLib/Common.c               |  249 ++++
>>>>>    MdePkg/Library/DrbgLib/Common.h               |   74 ++
>>>>>    MdePkg/Library/DrbgLib/CtrDrbg.c              |  899 +++++++++++++
>>>>>    MdePkg/Library/DrbgLib/CtrDrbg.h              |  100 ++
>>>>>    MdePkg/Library/DrbgLib/DrbgLib.c              |  628 ++++++++++
>>>>>    MdePkg/Library/DrbgLib/DrbgLib.inf            |   39 +
>>>>>    MdePkg/Library/DrbgLib/DrbgLibInternal.h      |  310 +++++
>>>>>    MdePkg/Library/DrbgLib/GetEntropyInput.c      |   72 ++
>>>>>    MdePkg/Library/DrbgLib/GetEntropyInput.h      |   48 +
>>>>>    MdePkg/Library/DrbgLibNull/DrbgLib.c          |  165 +++
>>>>>    MdePkg/Library/DrbgLibNull/DrbgLibNull.inf    |   21 +
>>>>>    MdePkg/MdePkg.dec                             |    4 +
>>>>>    MdePkg/MdePkg.dsc                             |    2 +
>>>>>    .../RandomNumberGenerator/RngDxe/ArmRngDxe.c  |   75 +-
>>>>>    .../RandomNumberGenerator/RngDxe/RngDxe.inf   |    1 +
>>>>>    SecurityPkg/SecurityPkg.dsc                   |    2 +
>>>>>    20 files changed, 4342 insertions(+), 1 deletion(-)
>>>>>    create mode 100644 MdePkg/Include/Library/DrbgLib.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/BitStream.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/BitStream.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/Common.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/Common.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/CtrDrbg.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/DrbgLib.inf
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/DrbgLibInternal.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLib/GetEntropyInput.h
>>>>>    create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLib.c
>>>>>    create mode 100644 MdePkg/Library/DrbgLibNull/DrbgLibNull.inf
>>>>>
>>>>> --
>>>>> 2.25.1
>>>>>
>>>>>
>>>>>
>>>>> -=-=-=-=-=-=
>>>>> Groups.io Links: You receive all messages sent to this group.
>>>>> View/Reply Online (#90898):
>> https://edk2.groups.io/g/devel/message/90898
>>>>> Mute This Topic: https://groups.io/mt/92072283/1643496
>>>>> Group Owner: devel+owner@edk2.groups.io
>>>>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
>>>> [michael.d.kinney@intel.com]
>>>>> -=-=-=-=-=-=
>>>>>
>>>

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

end of thread, other threads:[~2022-07-04 13:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-06-29 19:18 [PATCH RESEND v1 0/9] Add DrbgLib PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 1/9] MdePkg/DrbgLib: Drbg library interface definition PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 2/9] MdePkg/DrbgLib: Add NULL instance of Drbg Library PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 3/9] MdePkg/DrbgLib: Add BitStream implementation PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 4/9] MdePkg/DrbgLib: Add Get_entropy_input() implementation PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 5/9] MdePkg/DrbgLib: Add common wrappers PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 6/9] MdePkg/DrbgLib: Add Ctr Drbg mechanism functions PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 7/9] MdePkg/DrbgLib: Add Drbg mechanism functions and module PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 8/9] ArmVirtPkg: Kvmtool: Add AesLib/DrbgLib for RngDxe PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 9/9] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
2022-06-29 19:18 ` [PATCH RESEND v1 09/10] SecurityPkg: Update Securitypkg.ci.yaml PierreGondois
2022-06-29 19:18 ` [PATCH v1 10/10] SecurityPkg/RngDxe: Use DrbgLib in RngDxe for Arm PierreGondois
2022-06-30  0:15 ` [edk2-devel] [PATCH RESEND v1 0/9] Add DrbgLib Michael D Kinney
2022-06-30  1:16   ` Yao, Jiewen
2022-07-01  9:49     ` PierreGondois
2022-07-02  6:25       ` Yao, Jiewen
2022-07-04 13:18         ` PierreGondois
2022-07-01  8:30   ` PierreGondois

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