From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by mx.groups.io with SMTP id smtpd.web08.13943.1620744227805729160 for ; Tue, 11 May 2021 07:43:47 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=VFsGMsB+; spf=pass (domain: kernel.org, ip: 198.145.29.99, mailfrom: ardb@kernel.org) Received: by mail.kernel.org (Postfix) with ESMTPSA id D4945613C1 for ; Tue, 11 May 2021 14:43:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1620744226; bh=9IP6C5JS/jMgN/LxxgmYKnjNU6yytq+hOvU2yDo9JQk=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=VFsGMsB+cH+NoJ7Lul3Y2L0krBfPkte3MxniXlHVo5j4bO/1G7tfRhUczkrQZclW8 vDUMpxz11z6oLn9+WtdeP0YpKNiHeK53sFjPlAUBdNfhyztYQZbDta2CXE4aj1SIda Wg1jE7ZVV+ueP336VdUpjdRxDyLTLigWuucW8mjvCvWvHuraS+vPvD9PATXCoQTGfu 1zZYV54IkJRYdMl2rimj8BFceI7U+5gEfk1mUAlJiXPL+Dekwh7a0ezMXwWs4AfWal cRhtrGcL+aP7UwYSr3aQBk3Czh7eVB8endkDYLYbOXQK7EIn3ybppB74dgX/xANzzO nUzLDKNFAxaAQ== Received: by mail-ot1-f49.google.com with SMTP id g15-20020a9d128f0000b02902a7d7a7bb6eso17690641otg.9 for ; Tue, 11 May 2021 07:43:46 -0700 (PDT) X-Gm-Message-State: AOAM532PoBsY/eCVPfWLI3IftH4Xoxfe6amgokzMPJQj+Th6AfpLppb1 CSikv4FIjE1T+gsIncISo3sXtbLpYI/uT7xI1sw= X-Google-Smtp-Source: ABdhPJzDnv7dbrUGFI1tVDxgKKPERsi5SdZa1yxD6ZsWkuhP4lUHYS8UlVdvfyBzu+37yERZs2fw5XW29kyzkxXyMAA= X-Received: by 2002:a9d:7cd8:: with SMTP id r24mr14531116otn.90.1620744225678; Tue, 11 May 2021 07:43:45 -0700 (PDT) MIME-Version: 1.0 References: <20210510215308.28745-1-rebecca@nuviainc.com> <20210510215308.28745-3-rebecca@nuviainc.com> In-Reply-To: <20210510215308.28745-3-rebecca@nuviainc.com> From: "Ard Biesheuvel" Date: Tue, 11 May 2021 16:43:33 +0200 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v3 2/2] SecurityPkg: Add support for RngDxe on AARCH64 To: Rebecca Cran , Jiewen Yao , Jian J Wang Cc: edk2-devel-groups-io , Michael D Kinney , Liming Gao , Zhiguang Liu , Ard Biesheuvel , Sami Mujawar Content-Type: text/plain; charset="UTF-8" On Mon, 10 May 2021 at 23:53, Rebecca Cran wrote: > > AARCH64 support has been added to BaseRngLib via the optional > ARMv8.5 FEAT_RNG. > > Refactor RngDxe to support AARCH64, note support for it in the > VALID_ARCHITECTURES line of RngDxe.inf and enable it in SecurityPkg.dsc. > > Signed-off-by: Rebecca Cran I'm happy to take these and merge them if I can get an ack from a SecurityPkg maintainer. > --- > SecurityPkg/SecurityPkg.dec | 2 + > SecurityPkg/SecurityPkg.dsc | 11 +- > SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf | 24 ++- > SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.h | 0 > SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.h | 17 -- > SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h | 117 ++++++++++++++ > SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 127 +++++++++++++++ > SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.c | 0 > SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.c | 45 +----- > SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 146 +++++++++++++++++ > SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c | 170 ++++++++------------ > 11 files changed, 483 insertions(+), 176 deletions(-) > > diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec > index dfbbb0365a2b..4001650fa28e 100644 > --- a/SecurityPkg/SecurityPkg.dec > +++ b/SecurityPkg/SecurityPkg.dec > @@ -297,6 +297,8 @@ [PcdsFixedAtBuild, PcdsPatchableInModule] > gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|UINT32|0x00010030 > gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|UINT32|0x00010031 > > + gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00010032 > + > [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] > ## Image verification policy for OptionRom. Only following values are valid:

> # NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and has been removed.
> diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc > index 12ccd1634941..bd4b810bce61 100644 > --- a/SecurityPkg/SecurityPkg.dsc > +++ b/SecurityPkg/SecurityPkg.dsc > @@ -259,6 +259,12 @@ [Components] > [Components.IA32, Components.X64, Components.ARM, Components.AARCH64] > SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf > > +[Components.IA32, Components.X64, Components.AARCH64] > + # > + # Random Number Generator > + # > + SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf > + > [Components.IA32, Components.X64] > SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf > > @@ -334,11 +340,6 @@ [Components.IA32, Components.X64] > SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf > SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf > > - # > - # Random Number Generator > - # > - SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf > - > # > # Opal Password solution > # > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf > index 99d6f6b35fc2..f3300971993f 100644 > --- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf > @@ -26,15 +26,22 @@ [Defines] > # > # The following information is for reference only and not required by the build tools. > # > -# VALID_ARCHITECTURES = IA32 X64 > +# VALID_ARCHITECTURES = IA32 X64 AARCH64 > # > > [Sources.common] > RngDxe.c > - RdRand.c > - RdRand.h > - AesCore.c > - AesCore.h > + RngDxeInternals.h > + > +[Sources.IA32, Sources.X64] > + Rand/RngDxe.c > + Rand/RdRand.c > + Rand/RdRand.h > + Rand/AesCore.c > + Rand/AesCore.h > + > +[Sources.AARCH64] > + AArch64/RngDxe.c > > [Packages] > MdePkg/MdePkg.dec > @@ -50,12 +57,19 @@ [LibraryClasses] > RngLib > > [Guids] > + gEfiRngAlgorithmSp80090Hash256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > + gEfiRngAlgorithmSp80090Hmac256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > gEfiRngAlgorithmSp80090Ctr256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > + gEfiRngAlgorithmX9313DesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > + gEfiRngAlgorithmX931AesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > gEfiRngAlgorithmRaw ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG > > [Protocols] > gEfiRngProtocolGuid ## PRODUCES > > +[Pcd] > + gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm ## CONSUMES > + > [Depex] > TRUE > > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h > similarity index 100% > rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h > rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h > similarity index 72% > rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h > rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h > index 12ab1f34ec6d..072378e062e7 100644 > --- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h > @@ -23,23 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include > #include > > -/** > - Calls RDRAND to fill a buffer of arbitrary size with random bytes. > - > - @param[in] Length Size of the buffer, in bytes, to fill with. > - @param[out] RandBuffer Pointer to the buffer to store the random result. > - > - @retval EFI_SUCCESS Random bytes generation succeeded. > - @retval EFI_NOT_READY Failed to request random bytes. > - > -**/ > -EFI_STATUS > -EFIAPI > -RdRandGetBytes ( > - IN UINTN Length, > - OUT UINT8 *RandBuffer > - ); > - > /** > Generate high-quality entropy source through RDRAND. > > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h > new file mode 100644 > index 000000000000..2660ed5875e0 > --- /dev/null > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h > @@ -0,0 +1,117 @@ > +/** @file > + Function prototypes for UEFI Random Number Generator protocol support. > + > + Copyright (c) 2021, NUVIA Inc. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef RNGDXE_INTERNALS_H_ > +#define RNGDXE_INTERNALS_H_ > + > +/** > + Returns information about the random number generation implementation. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > + @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList. > + On output with a return code of EFI_SUCCESS, the size > + in bytes of the data returned in RNGAlgorithmList. On output > + with a return code of EFI_BUFFER_TOO_SMALL, > + the size of RNGAlgorithmList required to obtain the list. > + @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver > + with one EFI_RNG_ALGORITHM element for each supported > + RNG algorithm. The list must not change across multiple > + calls to the same driver. The first algorithm in the list > + is the default algorithm for the driver. > + > + @retval EFI_SUCCESS The RNG algorithm list was returned successfully. > + @retval EFI_UNSUPPORTED The services is not supported by this driver. > + @retval EFI_DEVICE_ERROR The list of algorithms could not be retrieved due to a > + hardware or firmware error. > + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. > + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetInfo ( > + IN EFI_RNG_PROTOCOL *This, > + IN OUT UINTN *RNGAlgorithmListSize, > + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList > + ); > + > +/** > + Produces and returns an RNG value using either the default or specified RNG algorithm. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > + @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG > + algorithm to use. May be NULL in which case the function will > + use its default RNG algorithm. > + @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. > + > + @retval EFI_SUCCESS The RNG value was returned successfully. > + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by > + this driver. > + @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or > + firmware error. > + @retval EFI_NOT_READY There is not enough random data available to satisfy the length > + requested by RNGValueLength. > + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetRNG ( > + IN EFI_RNG_PROTOCOL *This, > + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL > + IN UINTN RNGValueLength, > + OUT UINT8 *RNGValue > + ); > + > +/** > + Returns information about the random number generation implementation. > + > + @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList. > + On output with a return code of EFI_SUCCESS, the size > + in bytes of the data returned in RNGAlgorithmList. On output > + with a return code of EFI_BUFFER_TOO_SMALL, > + the size of RNGAlgorithmList required to obtain the list. > + @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver > + with one EFI_RNG_ALGORITHM element for each supported > + RNG algorithm. The list must not change across multiple > + calls to the same driver. The first algorithm in the list > + is the default algorithm for the driver. > + > + @retval EFI_SUCCESS The RNG algorithm list was returned successfully. > + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result. > + > +**/ > +UINTN > +EFIAPI > +ArchGetSupportedRngAlgorithms ( > + IN OUT UINTN *RNGAlgorithmListSize, > + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList > + ); > + > +/** > + Runs CPU RNG instruction to fill a buffer of arbitrary size with random bytes. > + > + @param[in] Length Size of the buffer, in bytes, to fill with. > + @param[out] RandBuffer Pointer to the buffer to store the random result. > + > + @retval EFI_SUCCESS Random bytes generation succeeded. > + @retval EFI_NOT_READY Failed to request random bytes. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetBytes ( > + IN UINTN Length, > + OUT UINT8 *RandBuffer > + ); > + > +#endif // RNGDXE_INTERNALS_H_ > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c > new file mode 100644 > index 000000000000..2810a9eb94ad > --- /dev/null > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c > @@ -0,0 +1,127 @@ > +/** @file > + RNG Driver to produce the UEFI Random Number Generator protocol. > + > + The driver will use the RNDR instruction to produce random numbers. > + > + RNG Algorithms defined in UEFI 2.4: > + - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID > + - EFI_RNG_ALGORITHM_RAW - Unsupported > + - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID > + - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID > + - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported > + - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported > + > + Copyright (c) 2021, NUVIA Inc. All rights reserved.
> + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
> + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "RngDxeInternals.h" > + > +/** > + Produces and returns an RNG value using either the default or specified RNG algorithm. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > + @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG > + algorithm to use. May be NULL in which case the function will > + use its default RNG algorithm. > + @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. > + > + @retval EFI_SUCCESS The RNG value was returned successfully. > + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by > + this driver. > + @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or > + firmware error. > + @retval EFI_NOT_READY There is not enough random data available to satisfy the length > + requested by RNGValueLength. > + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetRNG ( > + IN EFI_RNG_PROTOCOL *This, > + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL > + IN UINTN RNGValueLength, > + OUT UINT8 *RNGValue > + ) > +{ > + EFI_STATUS Status; > + > + if ((RNGValueLength == 0) || (RNGValue == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (RNGAlgorithm == NULL) { > + // > + // Use the default RNG algorithm if RNGAlgorithm is NULL. > + // > + RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm); > + } > + > + if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) { > + Status = RngGetBytes (RNGValueLength, RNGValue); > + return Status; > + } > + > + // > + // Other algorithms are unsupported by this driver. > + // > + return EFI_UNSUPPORTED; > +} > + > +/** > + Returns information about the random number generation implementation. > + > + @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList. > + On output with a return code of EFI_SUCCESS, the size > + in bytes of the data returned in RNGAlgorithmList. On output > + with a return code of EFI_BUFFER_TOO_SMALL, > + the size of RNGAlgorithmList required to obtain the list. > + @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver > + with one EFI_RNG_ALGORITHM element for each supported > + RNG algorithm. The list must not change across multiple > + calls to the same driver. The first algorithm in the list > + is the default algorithm for the driver. > + > + @retval EFI_SUCCESS The RNG algorithm list was returned successfully. > + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result. > + > +**/ > +UINTN > +EFIAPI > +ArchGetSupportedRngAlgorithms ( > + IN OUT UINTN *RNGAlgorithmListSize, > + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList > + ) > +{ > + UINTN RequiredSize; > + EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm; > + > + RequiredSize = sizeof (EFI_RNG_ALGORITHM); > + > + if (*RNGAlgorithmListSize < RequiredSize) { > + *RNGAlgorithmListSize = RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm); > + > + CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM)); > + > + *RNGAlgorithmListSize = RequiredSize; > + return EFI_SUCCESS; > +} > + > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c > similarity index 100% > rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c > rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c > similarity index 71% > rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c > rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c > index e7dd5ab18111..83025a47d43d 100644 > --- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c > @@ -8,48 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > **/ > #include > > -#include "RdRand.h" > #include "AesCore.h" > - > -/** > - Calls RDRAND to fill a buffer of arbitrary size with random bytes. > - > - @param[in] Length Size of the buffer, in bytes, to fill with. > - @param[out] RandBuffer Pointer to the buffer to store the random result. > - > - @retval EFI_SUCCESS Random bytes generation succeeded. > - @retval EFI_NOT_READY Failed to request random bytes. > - > -**/ > -EFI_STATUS > -EFIAPI > -RdRandGetBytes ( > - IN UINTN Length, > - OUT UINT8 *RandBuffer > - ) > -{ > - BOOLEAN IsRandom; > - UINT64 TempRand[2]; > - > - while (Length > 0) { > - IsRandom = GetRandomNumber128 (TempRand); > - if (!IsRandom) { > - return EFI_NOT_READY; > - } > - if (Length >= sizeof (TempRand)) { > - WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]); > - RandBuffer += sizeof (UINT64); > - WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]); > - RandBuffer += sizeof (UINT64); > - Length -= sizeof (TempRand); > - } else { > - CopyMem (RandBuffer, TempRand, Length); > - Length = 0; > - } > - } > - > - return EFI_SUCCESS; > -} > +#include "RdRand.h" > +#include "RngDxeInternals.h" > > /** > Creates a 128bit random value that is fully forward and backward prediction resistant, > @@ -92,7 +53,7 @@ RdRandGetSeed128 ( > // > for (Index = 0; Index < 32; Index++) { > MicroSecondDelay (10); > - Status = RdRandGetBytes (16, RandByte); > + Status = RngGetBytes (16, RandByte); > if (EFI_ERROR (Status)) { > return Status; > } > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c > new file mode 100644 > index 000000000000..6b628a9f8bc6 > --- /dev/null > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c > @@ -0,0 +1,146 @@ > +/** @file > + RNG Driver to produce the UEFI Random Number Generator protocol. > + > + The driver will use the new RDRAND instruction to produce high-quality, high-performance > + entropy and random number. > + > + RNG Algorithms defined in UEFI 2.4: > + - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported > + (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG) > + - EFI_RNG_ALGORITHM_RAW - Supported > + (Structuring RDRAND invocation can be guaranteed as high-quality entropy source) > + - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported > + - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported > + - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported > + - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported > + > + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
> + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "RdRand.h" > +#include "RngDxeInternals.h" > + > +/** > + Produces and returns an RNG value using either the default or specified RNG algorithm. > + > + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > + @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG > + algorithm to use. May be NULL in which case the function will > + use its default RNG algorithm. > + @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. > + > + @retval EFI_SUCCESS The RNG value was returned successfully. > + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by > + this driver. > + @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or > + firmware error. > + @retval EFI_NOT_READY There is not enough random data available to satisfy the length > + requested by RNGValueLength. > + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetRNG ( > + IN EFI_RNG_PROTOCOL *This, > + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL > + IN UINTN RNGValueLength, > + OUT UINT8 *RNGValue > + ) > +{ > + EFI_STATUS Status; > + > + if ((RNGValueLength == 0) || (RNGValue == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = EFI_UNSUPPORTED; > + if (RNGAlgorithm == NULL) { > + // > + // Use the default RNG algorithm if RNGAlgorithm is NULL. > + // > + RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid; > + } > + > + // > + // NIST SP800-90-AES-CTR-256 supported by RDRAND > + // > + if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) { > + Status = RngGetBytes (RNGValueLength, RNGValue); > + return Status; > + } > + > + // > + // The "raw" algorithm is intended to provide entropy directly > + // > + if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) { > + // > + // When a DRBG is used on the output of a entropy source, > + // its security level must be at least 256 bits according to UEFI Spec. > + // > + if (RNGValueLength < 32) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = RdRandGenerateEntropy (RNGValueLength, RNGValue); > + return Status; > + } > + > + // > + // Other algorithms were unsupported by this driver. > + // > + return Status; > +} > + > +/** > + Returns information about the random number generation implementation. > + > + @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList. > + On output with a return code of EFI_SUCCESS, the size > + in bytes of the data returned in RNGAlgorithmList. On output > + with a return code of EFI_BUFFER_TOO_SMALL, > + the size of RNGAlgorithmList required to obtain the list. > + @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver > + with one EFI_RNG_ALGORITHM element for each supported > + RNG algorithm. The list must not change across multiple > + calls to the same driver. The first algorithm in the list > + is the default algorithm for the driver. > + > + @retval EFI_SUCCESS The RNG algorithm list was returned successfully. > + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result. > + > +**/ > +UINTN > +EFIAPI > +ArchGetSupportedRngAlgorithms ( > + IN OUT UINTN *RNGAlgorithmListSize, > + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList > + ) > +{ > + UINTN RequiredSize; > + EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm; > + > + RequiredSize = 2 * sizeof (EFI_RNG_ALGORITHM); > + > + if (*RNGAlgorithmListSize < RequiredSize) { > + *RNGAlgorithmListSize = RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm); > + > + CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM)); > + > + // x86 platforms also support EFI_RNG_ALGORITHM_RAW via RDSEED > + CopyMem(&RNGAlgorithmList[1], &gEfiRngAlgorithmRaw, sizeof (EFI_RNG_ALGORITHM)); > + > + *RNGAlgorithmListSize = RequiredSize; > + return EFI_SUCCESS; > +} > + > diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c > index 13d3dbd0bfbe..b959c70536ea 100644 > --- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c > +++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c > @@ -1,34 +1,32 @@ > /** @file > RNG Driver to produce the UEFI Random Number Generator protocol. > > - The driver will use the new RDRAND instruction to produce high-quality, high-performance > - entropy and random number. > + The driver uses CPU RNG instructions to produce high-quality, > + high-performance entropy and random number. > > RNG Algorithms defined in UEFI 2.4: > - - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported > - (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG) > - - EFI_RNG_ALGORITHM_RAW - Supported > - (Structuring RDRAND invocation can be guaranteed as high-quality entropy source) > - - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported > - - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported > - - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported > - - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported > + - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID > + - EFI_RNG_ALGORITHM_RAW > + - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID > + - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID > + - EFI_RNG_ALGORITHM_X9_31_3DES_GUID > + - EFI_RNG_ALGORITHM_X9_31_AES_GUID > > Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
> (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> + > SPDX-License-Identifier: BSD-2-Clause-Patent > > **/ > > -#include "RdRand.h" > +#include > +#include > +#include > +#include > +#include > +#include > > -// > -// Supported RNG Algorithms list by this driver. > -// > -EFI_RNG_ALGORITHM mSupportedRngAlgorithms[] = { > - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID, > - EFI_RNG_ALGORITHM_RAW > -}; > +#include "RngDxeInternals.h" > > /** > Returns information about the random number generation implementation. > @@ -62,106 +60,23 @@ RngGetInfo ( > ) > { > EFI_STATUS Status; > - UINTN RequiredSize; > > if ((This == NULL) || (RNGAlgorithmListSize == NULL)) { > return EFI_INVALID_PARAMETER; > } > > - RequiredSize = sizeof (mSupportedRngAlgorithms); > - if (*RNGAlgorithmListSize < RequiredSize) { > - Status = EFI_BUFFER_TOO_SMALL; > + // > + // Return algorithm list supported by driver. > + // > + if (RNGAlgorithmList != NULL) { > + Status = ArchGetSupportedRngAlgorithms (RNGAlgorithmListSize, RNGAlgorithmList); > } else { > - // > - // Return algorithm list supported by driver. > - // > - if (RNGAlgorithmList != NULL) { > - CopyMem (RNGAlgorithmList, mSupportedRngAlgorithms, RequiredSize); > - Status = EFI_SUCCESS; > - } else { > - Status = EFI_INVALID_PARAMETER; > - } > + Status = EFI_INVALID_PARAMETER; > } > - *RNGAlgorithmListSize = RequiredSize; > > return Status; > } > > -/** > - Produces and returns an RNG value using either the default or specified RNG algorithm. > - > - @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. > - @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG > - algorithm to use. May be NULL in which case the function will > - use its default RNG algorithm. > - @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. > - > - @retval EFI_SUCCESS The RNG value was returned successfully. > - @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by > - this driver. > - @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or > - firmware error. > - @retval EFI_NOT_READY There is not enough random data available to satisfy the length > - requested by RNGValueLength. > - @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. > - > -**/ > -EFI_STATUS > -EFIAPI > -RngGetRNG ( > - IN EFI_RNG_PROTOCOL *This, > - IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL > - IN UINTN RNGValueLength, > - OUT UINT8 *RNGValue > - ) > -{ > - EFI_STATUS Status; > - > - if ((RNGValueLength == 0) || (RNGValue == NULL)) { > - return EFI_INVALID_PARAMETER; > - } > - > - Status = EFI_UNSUPPORTED; > - if (RNGAlgorithm == NULL) { > - // > - // Use the default RNG algorithm if RNGAlgorithm is NULL. > - // > - RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid; > - } > - > - // > - // NIST SP800-90-AES-CTR-256 supported by RDRAND > - // > - if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) { > - Status = RdRandGetBytes (RNGValueLength, RNGValue); > - return Status; > - } > - > - // > - // The "raw" algorithm is intended to provide entropy directly > - // > - if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) { > - // > - // When a DRBG is used on the output of a entropy source, > - // its security level must be at least 256 bits according to UEFI Spec. > - // > - if (RNGValueLength < 32) { > - return EFI_INVALID_PARAMETER; > - } > - > - Status = RdRandGenerateEntropy (RNGValueLength, RNGValue); > - return Status; > - } > - > - // > - // Other algorithms were unsupported by this driver. > - // > - return Status; > -} > - > // > // The Random Number Generator (RNG) protocol > // > @@ -204,3 +119,44 @@ RngDriverEntry ( > > return Status; > } > + > + > +/** > + Calls RDRAND to fill a buffer of arbitrary size with random bytes. > + > + @param[in] Length Size of the buffer, in bytes, to fill with. > + @param[out] RandBuffer Pointer to the buffer to store the random result. > + > + @retval EFI_SUCCESS Random bytes generation succeeded. > + @retval EFI_NOT_READY Failed to request random bytes. > + > +**/ > +EFI_STATUS > +EFIAPI > +RngGetBytes ( > + IN UINTN Length, > + OUT UINT8 *RandBuffer > + ) > +{ > + BOOLEAN IsRandom; > + UINT64 TempRand[2]; > + > + while (Length > 0) { > + IsRandom = GetRandomNumber128 (TempRand); > + if (!IsRandom) { > + return EFI_NOT_READY; > + } > + if (Length >= sizeof (TempRand)) { > + WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]); > + RandBuffer += sizeof (UINT64); > + WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]); > + RandBuffer += sizeof (UINT64); > + Length -= sizeof (TempRand); > + } else { > + CopyMem (RandBuffer, TempRand, Length); > + Length = 0; > + } > + } > + > + return EFI_SUCCESS; > +} > -- > 2.26.2 >