From: "Pedro Falcato" <pedro.falcato@gmail.com>
To: devel@edk2.groups.io
Cc: Pedro Falcato <pedro.falcato@gmail.com>,
Michael D Kinney <michael.d.kinney@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>,
Zhiguang Liu <zhiguang.liu@intel.com>,
"Jason A . Donenfeld" <Jason@zx2c4.com>
Subject: [PATCH v2 1/1] MdePkg/BaseRngLib: Add a smoketest for RDRAND and check CPUID
Date: Tue, 22 Nov 2022 15:32:12 +0000 [thread overview]
Message-ID: <20221122153212.570984-1-pedro.falcato@gmail.com> (raw)
RDRAND has notoriously been broken many times over its lifespan.
Add a smoketest to RDRAND, in order to better sniff out potential
security concerns.
Also add a proper CPUID test in order to support older CPUs which may
not have it; it was previously being tested but then promptly ignored.
Many thanks to Jason Donenfeld for relicensing his linux RDRAND detection
code to MIT and the public domain.
>On Tue, Nov 22, 2022 at 2:21 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
<..>
> I (re)wrote that function in Linux. I hereby relicense it as MIT, and
> also place it into public domain. Do with it what you will now.
>
> Jason
Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
---
MdePkg/Library/BaseRngLib/Rand/RdRand.c | 83 ++++++++++++++++++++++---
1 file changed, 75 insertions(+), 8 deletions(-)
diff --git a/MdePkg/Library/BaseRngLib/Rand/RdRand.c b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
index 070d41e2555f..c8f837c315f1 100644
--- a/MdePkg/Library/BaseRngLib/Rand/RdRand.c
+++ b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
@@ -2,6 +2,7 @@
Random number generator services that uses RdRand instruction access
to provide high-quality random numbers.
+Copyright (c) 2022, Pedro Falcato. All rights reserved.<BR>
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
@@ -22,6 +23,72 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
STATIC BOOLEAN mRdRandSupported;
+//
+// Intel SDM says 10 tries is good enough for reliable RDRAND usage.
+//
+#define RDRAND_RETRIES 10
+
+#define RDRAND_TEST_SAMPLES 8
+
+#define RDRAND_MIN_CHANGE 5
+
+STATIC
+BOOLEAN
+TestRdRand (
+ VOID
+ )
+{
+ //
+ // Test for notoriously broken rdrand implementations that always return the same
+ // value, like the Zen 3 uarch (all-1s) or other several AMD families on suspend/resume (also all-1s).
+ // Note that this should be expanded to extensively test for other sorts of possible errata.
+ //
+
+ //
+ // Testing algorithm inspired by linux's arch/x86/kernel/cpu/rdrand.c:x86_init_rdrand
+ // as relicensed by the author, Jason Donenfeld, in the EDK2 mailing list.
+ // As is, the algorithm samples rdrand $RDRAND_TEST_SAMPLES times and expects
+ // a different result $RDRAND_MIN_CHANGE times for reliable RDRAND usage.
+ //
+ UINT32 Prev;
+ UINT8 Idx;
+ UINT8 TestIteration;
+ UINT32 Changed;
+
+ Changed = 0;
+
+ for (TestIteration = 0; TestIteration < RDRAND_TEST_SAMPLES; TestIteration++) {
+ UINT32 Sample;
+ //
+ // Note: We use a retry loop for rdrand. Normal users get this in BaseRng.c
+ // Any failure to get a random number will assume RDRAND does not work.
+ //
+ for (Idx = 0; Idx < RDRAND_RETRIES; Idx++) {
+ if (AsmRdRand32 (&Sample)) {
+ break;
+ }
+ }
+
+ if (Idx == RDRAND_RETRIES) {
+ DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: Failed to get an RDRAND random number - disabling\n"));
+ return FALSE;
+ }
+
+ if (TestIteration != 0) {
+ Changed += Sample != Prev;
+ }
+
+ Prev = Sample;
+ }
+
+ if (Changed < RDRAND_MIN_CHANGE) {
+ DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: RDRAND not reliable - disabling\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
The constructor function checks whether or not RDRAND instruction is supported
by the host hardware.
@@ -46,10 +113,13 @@ BaseRngLibConstructor (
// CPUID. A value of 1 indicates that processor support RDRAND instruction.
//
AsmCpuid (1, 0, 0, &RegEcx, 0);
- ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+ if (mRdRandSupported) {
+ mRdRandSupported = TestRdRand ();
+ }
+
return EFI_SUCCESS;
}
@@ -68,6 +138,7 @@ ArchGetRandomNumber16 (
OUT UINT16 *Rand
)
{
+ ASSERT (mRdRandSupported);
return AsmRdRand16 (Rand);
}
@@ -86,6 +157,7 @@ ArchGetRandomNumber32 (
OUT UINT32 *Rand
)
{
+ ASSERT (mRdRandSupported);
return AsmRdRand32 (Rand);
}
@@ -104,6 +176,7 @@ ArchGetRandomNumber64 (
OUT UINT64 *Rand
)
{
+ ASSERT (mRdRandSupported);
return AsmRdRand64 (Rand);
}
@@ -120,11 +193,5 @@ ArchIsRngSupported (
VOID
)
{
- /*
- Existing software depends on this always returning TRUE, so for
- now hard-code it.
-
- return mRdRandSupported;
- */
- return TRUE;
+ return mRdRandSupported;
}
--
2.38.1
next reply other threads:[~2022-11-22 15:32 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-22 15:32 Pedro Falcato [this message]
2022-11-22 15:38 ` [PATCH v2 1/1] MdePkg/BaseRngLib: Add a smoketest for RDRAND and check CPUID Jason A. Donenfeld
2022-11-22 15:56 ` Pedro Falcato
2022-11-22 16:54 ` [edk2-devel] " Michael D Kinney
2022-11-22 17:11 ` Jason A. Donenfeld
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221122153212.570984-1-pedro.falcato@gmail.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox