* [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 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
* 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