Skip to content

Commit c40a53e

Browse files
committed
Add hermit support
We can just use secure_rand64, which should allow us to avoid aarch64 issues. Note we have to build all of libstd to test this, see hermit-os/hermit-rs#103 for more information. Signed-off-by: Joe Richey <[email protected]>
1 parent 347a300 commit c40a53e

File tree

6 files changed

+38
-8
lines changed

6 files changed

+38
-8
lines changed

.github/workflows/tests.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,13 @@ jobs:
293293
override: true
294294
- name: UEFI (RDRAND)
295295
run: cargo build -Z build-std=core --features=rdrand --target=x86_64-unknown-uefi
296-
- name: Hermit (RDRAND)
297-
run: cargo build -Z build-std=core --features=rdrand --target=x86_64-unknown-hermit
298296
- name: L4Re (RDRAND)
299297
run: cargo build -Z build-std=core --features=rdrand --target=x86_64-unknown-l4re-uclibc
300298
- name: VxWorks
301299
run: cargo build -Z build-std=core --target=x86_64-wrs-vxworks
300+
# Switch to build-std=core when https://github.com/hermitcore/rusty-hermit/pull/103 is fixed.
301+
- name: Hermit
302+
run: cargo build -Z build-std --target=x86_64-unknown-hermit
302303

303304
clippy-fmt:
304305
name: Clippy + rustfmt

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ libc = { version = "0.2.64", default-features = false }
2323
[target.'cfg(target_os = "wasi")'.dependencies]
2424
wasi = "0.10"
2525

26+
[target.'cfg(target_os = "hermit")'.dependencies]
27+
hermit-abi = "0.1.17"
28+
2629
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
2730
wasm-bindgen = { version = "0.2.62", default-features = false, optional = true }
2831
js-sys = { version = "0.3", optional = true }

src/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ impl Error {
5353
pub const NODE_CRYPTO: Error = internal_error(12);
5454
/// NodeJS does not have support for `crypto.randomFillSync`.
5555
pub const NODE_RANDOM_FILL_SYNC: Error = internal_error(13);
56+
/// RustyHermit target is missing required RNG hardware.
57+
pub const HERMIT_HARDWARE_UNAVAILABLE: Error = internal_error(14);
5658

5759
/// Codes below this point represent OS Errors (i.e. positive i32 values).
5860
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are

src/hermit.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! Implementation for Hermit uses `secure_rand64` instead of `rand` so that we
2+
//! fail instead of returning insecure random numbers.
3+
use crate::Error;
4+
use hermit_abi::secure_rand64;
5+
6+
fn secure_bytes() -> Result<[u8; 8], Error> {
7+
// SAFETY: This function shouldn't actually be unsafe
8+
match unsafe { secure_rand64() } {
9+
Some(v) => Ok(v.to_ne_bytes()),
10+
None => Err(Error::HERMIT_HARDWARE_UNAVAILABLE),
11+
}
12+
}
13+
14+
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
15+
let mut chunks = dest.chunks_exact_mut(8);
16+
for chunk in chunks.by_ref() {
17+
chunk.copy_from_slice(&secure_bytes()?);
18+
}
19+
let rem = chunks.into_remainder();
20+
if !rem.is_empty() {
21+
rem.copy_from_slice(&secure_bytes()?[..rem.len()]);
22+
}
23+
Ok(())
24+
}

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ cfg_if! {
196196
} else if #[cfg(target_os = "vxworks")] {
197197
mod util_libc;
198198
#[path = "vxworks.rs"] mod imp;
199+
} else if #[cfg(target_os = "hermit")] {
200+
#[path = "hermit.rs"] mod imp;
199201
} else if #[cfg(windows)] {
200202
#[path = "windows.rs"] mod imp;
201203
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {

src/rdrand.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,13 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
8383
unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> {
8484
// We use chunks_exact_mut instead of chunks_mut as it allows almost all
8585
// calls to memcpy to be elided by the compiler.
86-
let mut chunks = dest.chunks_exact_mut(WORD_SIZE);
86+
let mut chunks = dest.chunks_exact_mut(8);
8787
for chunk in chunks.by_ref() {
8888
chunk.copy_from_slice(&rdrand()?);
8989
}
90-
91-
let tail = chunks.into_remainder();
92-
let n = tail.len();
93-
if n > 0 {
94-
tail.copy_from_slice(&rdrand()?[..n]);
90+
let rem = chunks.into_remainder();
91+
if !rem.is_empty() {
92+
rem.copy_from_slice(&rdrand()?[..rem.len()]);
9593
}
9694
Ok(())
9795
}

0 commit comments

Comments
 (0)