From 7c263d47f4694b67a8fc7fa1b43ae71f1bdfafe9 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 28 Jun 2019 15:21:09 -0700 Subject: [PATCH 1/2] Check for AMD RDRAND bug --- src/rdrand.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/rdrand.rs b/src/rdrand.rs index a03eb0a4c..2e486265b 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -23,6 +23,13 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { for _ in 0..RETRY_LIMIT { let mut el = mem::uninitialized(); if _rdrand64_step(&mut el) == 1 { + // AMD CPUs from families 14h to 16h (pre Ryzen) will sometimes give + // bogus random data. Discard these values and warn the user. + // See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505 + if el == 0 || el == !0 { + error!("RDRAND returned suspicious value {}, CPU RNG is broken", el); + return Err(Error::UNKNOWN) + } return Ok(el.to_ne_bytes()); } } @@ -36,14 +43,14 @@ compile_error!( "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd." ); -#[cfg(any(target_env = "sgx", target_feature = "rdrand"))] +#[cfg(target_feature = "rdrand")] fn is_rdrand_supported() -> bool { true } // TODO use is_x86_feature_detected!("rdrand") when that works in core. See: // https://github.com/rust-lang-nursery/stdsimd/issues/464 -#[cfg(not(any(target_env = "sgx", target_feature = "rdrand")))] +#[cfg(not(target_feature = "rdrand"))] fn is_rdrand_supported() -> bool { use core::arch::x86_64::__cpuid; use lazy_static::lazy_static; From 4c9817af163e24c04d202e728562c732ef202c18 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 28 Jun 2019 17:07:05 -0700 Subject: [PATCH 2/2] Don't do this check on SGX --- src/rdrand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdrand.rs b/src/rdrand.rs index 2e486265b..addd9f0e9 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -26,7 +26,7 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { // AMD CPUs from families 14h to 16h (pre Ryzen) will sometimes give // bogus random data. Discard these values and warn the user. // See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505 - if el == 0 || el == !0 { + if cfg!(not(target_env = "sgx")) && (el == 0 || el == !0) { error!("RDRAND returned suspicious value {}, CPU RNG is broken", el); return Err(Error::UNKNOWN) }