From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f169.google.com (mail-oi1-f169.google.com [209.85.167.169]) by mx.groups.io with SMTP id smtpd.web11.10837.1620397414821228922 for ; Fri, 07 May 2021 07:23:35 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=Arbrlgsw; spf=pass (domain: nuviainc.com, ip: 209.85.167.169, mailfrom: rebecca@nuviainc.com) Received: by mail-oi1-f169.google.com with SMTP id k25so8863094oic.4 for ; Fri, 07 May 2021 07:23:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cF/r43Q/1VJhDtY5xUBjccp2AwuANbWShwzodCw6WSI=; b=Arbrlgsw6npWx8Y5zRJ7+oY2x8E/6Mn+LNa6bmPemh7wVLw/jJnI5cDxatggM2nrET mAq2Lc3pNYYHfxvqHGTenzQzvujzOXv+32r58VETtlJFiH6H0Qeyna0KffwQIpQErl/9 iDeL6DTWIZHTHrGanbN0Xzn5bZ4uzEqEy9x0DFa4GDZ1E+c4aaNcksRdUXzJDe7SV+EJ xTMF9KqcXo5cb/DJC6cWrNJd0Qzlg24lptyCKJwswvpHmUI4WYisqPb+NGc24a4FaLzT 0iSLD7AROgZcStcyr/3or+j6m4l7vm1eu7dHQRDBvG4kato0MxkidqlpwdVTcDYjlODK htJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cF/r43Q/1VJhDtY5xUBjccp2AwuANbWShwzodCw6WSI=; b=a5rvuUcibqhQBgr1zfKnGqqqy+/TyUwiFxJOLJ7rGv9SgfApQPWBu8kZyBOBKNr99N T74R519WbKiP7w4DEW5zIC4ewsZ/eEBrGuQWH4133qNuuSIDtk4KWCeP1cb22UUYHUWJ hoewbeXDpu9o6AY2Yi8u0qAGHfvdpXRtEoF23n9rMWAWElV3A5A+zPQp891phSSeuZEg XIgyzexR9ld9qfIoPgPyclUS8qoPAB2uB8eTo8OT4++ieNeY6uDbdadD0si7LAj9n3Zi xWML+N0ePyNcEJ6IlJPT/2HgWtkrKycPmxskykQ5bl/zGYbQhdug0RmhJk+zHtENSECm KyYg== X-Gm-Message-State: AOAM530zzd1eYMjvEEjUye2skBYqM7ZJUhQtzRrf2ZX+4CyrolZPukGF E9L/Jae54nT5j49/uR94XFvIZIO2ZYi/HXSuDiMFddh8IQAK7DdBXbF42zOMz54J+dBLipYwAHf UQWUxZL6pREm/EmU+xQOWa4TO4fu7Cxw3hzZxTzRBjN8Oi/eD8gh5sjXZlFZ4DFwQZranWQ== X-Google-Smtp-Source: ABdhPJw56GS3L+VdCpIMNICNbhS7DJ171XXvB4lrG+cQvGpzzLenN11cdTdBUHXpzkzpFYdn8oiH5g== X-Received: by 2002:a54:4184:: with SMTP id 4mr15709299oiy.87.1620397413325; Fri, 07 May 2021 07:23:33 -0700 (PDT) Return-Path: Received: from cube.nuviainc.com (c-174-52-16-57.hsd1.ut.comcast.net. [174.52.16.57]) by smtp.gmail.com with ESMTPSA id 88sm1215641otx.2.2021.05.07.07.23.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 May 2021 07:23:32 -0700 (PDT) From: "Rebecca Cran" To: devel@edk2.groups.io, Jiewen Yao , Jian J Wang , Michael D Kinney , Liming Gao , Zhiguang Liu , Ard Biesheuvel , Sami Mujawar Cc: Rebecca Cran Subject: [PATCH v2 2/2] SecurityPkg: Add support for RngDxe on AARCH64 Date: Fri, 7 May 2021 08:23:15 -0600 Message-Id: <20210507142315.679-3-rebecca@nuviainc.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210507142315.679-1-rebecca@nuviainc.com> References: <20210507142315.679-1-rebecca@nuviainc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- 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..a45104fe3e6c 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|{0}|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