Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support x86_64-unknown-uefi #30

Merged
merged 6 commits into from
Jun 17, 2019
Merged

Support x86_64-unknown-uefi #30

merged 6 commits into from
Jun 17, 2019

Conversation

josephlr
Copy link
Member

@josephlr josephlr commented Jun 12, 2019

Closes #27 and adds support for the x86_64-unknown-uefi target. For our purposes, this target is quite similar to SGX in that the only source of RNG is RDRAND.

This PR:

  • Uses cargo xbuild to make sure we can build on this target.
  • Adds in feature detection using is_x86_feature_detected! macro. We use it from std_detect instead of std. Note that while this macro is not part of core, std_detect supports no_std targets on x86 (as it just makes cached calls to CPUID).

Note: we don't use EFI_RNG_PROTOCOL as most motherboard firmwares don't implement it, and those that do (i.e. EDK2) just call RDRAND anyway.

@josephlr
Copy link
Member Author

Note that because this removed the compiler error when cfg(not(target_feature = "rdrand")) all the rdrand methods are now unsafe (as it is UD behavior to call them if rdrand is not supported). We also need to keep these functions unsafe as they need the #[target_feature(enable = "rdrand")] annotation to enable rdrand to be inlined (which is critical for performance in this case). See the difference:

Also, @dhardy @newpavlov to use std_detect (outside of std) requires nightly. Is this acceptable? If not I can just copy the rdrand detection code from there (it's only 5 lines).

@dhardy
Copy link
Member

dhardy commented Jun 13, 2019

I'm still not convinced whether we should omit the CPU detection just to avoid a CPUID test. @nagisa?

I think there's no other reason we can't support SGX with stable compilers? If so then copying the code sounds best.

@josephlr
Copy link
Member Author

I'm still not convinced whether we should omit the CPU detection just to avoid a CPUID test.

To be clear, the CPUID test is only omitted if the compiler already knows it can support RDRAND. This is crucial for SGX, as the CPUID instruction is illegal in an enclave.

If so then copying the code sounds best.

Will do

@nagisa
Copy link

nagisa commented Jun 13, 2019 via email

@nagisa
Copy link

nagisa commented Jun 13, 2019 via email

@josephlr
Copy link
Member Author

Caveat: the macro is not supported on non-std targets. In that case you
still want to maintain something similar.

Ya this is the issue, because most of the targets we would want to use RDRAND on are no_std (like UEFI, or SGX targets that aren't x86_64-fortanix-unknown-sgx). I added a comment linking to the stdsimd issue.

@josephlr
Copy link
Member Author

@dhardy @nagisa does the is_rdrand_supported() look correct?

@nagisa
Copy link

nagisa commented Jun 13, 2019

https://github.com/nagisa/rust_rdrand/blob/fa7b3b13f393a1eaf345fb8d207631ca2a8a78bc/src/lib.rs#L143 is what I have in the rdrand library, your’s seems equivalent.

Copy link
Member

@dhardy dhardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks okay to me other than inverted logic

src/rdrand.rs Outdated Show resolved Hide resolved
Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to detect if EFI_RNG_PROTOCOL is implemented and use RDRAND as a fallback?

src/rdrand.rs Outdated Show resolved Hide resolved
@josephlr
Copy link
Member Author

Is there a way to detect if EFI_RNG_PROTOCOL is implemented and use RDRAND as a fallback?

Not without access to the EFI system table. Using EFI_RNG_PROTOCOL would be possible in theory if solving #4 gave us a way to externally provide randomness, but in practice EFI_RNG_PROTOCOL is almost always either unimplemented or aliased to RDRAND.

@dhardy
Copy link
Member

dhardy commented Jun 14, 2019

Agreed, that sounds like a needless complication.

$ cargo build --target=x86_64-fortanix-unknown-sgx --all-features
   Compiling getrandom v0.1.3 (/home/travis/build/rust-random/getrandom)
error[E0537]: invalid predicate `and`
  --> src/rdrand.rs:34:7
   |
34 | #[cfg(and(target_env = "sgx", not(target_feature = "rdrand")))]
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I think you want all.

src/lib.rs Outdated Show resolved Hide resolved
@josephlr
Copy link
Member Author

I think you want all.

Fixed

src/rdrand.rs Outdated Show resolved Hide resolved
Cargo.toml Show resolved Hide resolved
@newpavlov
Copy link
Member

@dhardy
I think we can merge it?

@dhardy dhardy merged commit 0b87a09 into rust-random:master Jun 17, 2019
@josephlr josephlr deleted the uefi branch June 17, 2019 08:28
return Ok(el.to_ne_bytes());
}
};
let mut el = mem::uninitialized();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit late to the party here, but I was curious why this uses mem::uninitialized() instead of mem::zeroed().

Zeroing seems relatively lightweight compared to RDRAND itself, would make RNG failures more obvious, and eliminates the potential risk of using attacker-controlled values which appear plausibly random at first glance as e.g. cryptographic keys.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, zeroed could be a better choice. Although in practice it does not matter, as both zeroed and uninitialized get optimized out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarcieri good catch! It also gets rid of a deprecation warning on the latest nightly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

rdrand implementation should enable the feature itself
5 participants