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

Add VxWorks support #86

Merged
merged 14 commits into from
Oct 23, 2019
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ matrix:
- cargo xbuild --target=x86_64-unknown-uefi
- cargo xbuild --target=x86_64-unknown-hermit
- cargo xbuild --target=x86_64-unknown-l4re-uclibc
- cargo xbuild --target=x86_64-wrs-vxworks
# also test minimum dependency versions are usable
- cargo generate-lockfile -Z minimal-versions
- cargo build --target=x86_64-sun-solaris
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
//! | Haiku | `/dev/random` (identical to `/dev/urandom`)
//! | L4RE, SGX, UEFI | [RDRAND][18]
//! | Hermit | [RDRAND][18] as [`sys_rand`][22] is currently broken.
//! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure`
//! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14])
//! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16])
//! | WASI | [`__wasi_random_get`][17]
Expand Down Expand Up @@ -171,6 +172,7 @@ mod util;
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "vxworks",
))]
#[allow(dead_code)]
mod util_libc;
Expand Down Expand Up @@ -225,6 +227,8 @@ cfg_if! {
#[path = "solaris_illumos.rs"] mod imp;
} else if #[cfg(target_os = "wasi")] {
#[path = "wasi.rs"] mod imp;
} else if #[cfg(target_os = "vxworks")] {
#[path = "vxworks.rs"] mod imp;
} else if #[cfg(all(windows, getrandom_uwp))] {
#[path = "windows_uwp.rs"] mod imp;
} else if #[cfg(windows)] {
Expand Down
3 changes: 3 additions & 0 deletions src/util_libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ cfg_if! {
}

pub fn last_os_error() -> Error {
#[cfg(not(target_os = "vxworks"))]
let errno = unsafe { *errno_location() };
#[cfg(target_os = "vxworks")]
let errno = unsafe { libc::errnoGet() };
if errno > 0 {
Error::from(NonZeroU32::new(errno as u32).unwrap())
} else {
Expand Down
36 changes: 36 additions & 0 deletions src/vxworks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation for VxWorks
use crate::error::Error;
use crate::util_libc::last_os_error;
use core::sync::atomic::{AtomicBool, Ordering::Relaxed};

static RNG_INIT: AtomicBool = AtomicBool::new(false);
newpavlov marked this conversation as resolved.
Show resolved Hide resolved

pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
while !RNG_INIT.load(Relaxed) {
Copy link
Member

Choose a reason for hiding this comment

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

We should use LazyBool here, something like:

fn rng_init() -> bool {
    loop {
        let ret = unsafe { libc::randSecure() }
        if ret != 0 {
            return ret > 0;
        }
        unsafe { libc::usleep(10) };
    }
}
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
    static RNG_INIT: LazyBool = LazyBool::new();
    if !RNG_INIT.unsync_init(rng_init) {
        return Err(RAND_SECURE_FATAL);
    }

    // Prevent overflow of i32
    ...

You could also use a lambda, if you think it would look better.

Copy link
Member Author

Choose a reason for hiding this comment

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

@BaoshanPang @n-salim
Is it possible for the system to recover after randSecure failure or can we assume that once it has failed it will always fail?

Choose a reason for hiding this comment

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

Yes, the system can recover after randSecure failure. This is the randSecure's function desciption:

  • randSecure - determine if state is secure
  • This routine determines if state is secure and returns status.
  • When the system boots, the SW random number lib contains no entropy. Once
  • enough entropy has been collected in order to make the random numbers
  • cryptographically secure, the state is considered to be secure.
  • It will make a system call to a kernel side handler.
  • RETURNS: 1 if the state is secure, 0 if the state is not secure, ERROR if
  • the random number generator module is not initialized.
  • ERRNOS: N/A

Copy link
Member

Choose a reason for hiding this comment

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

"ERROR if the random number generator module is not initialized."

If I'm understanding this right, the RNG module might not be initialized, but it could become initialized later?

If that's the case, the current code looks good to me.

let ret = unsafe { libc::randSecure() };
if ret < 0 {
return Err(last_os_error());
} else if ret > 0 {
RNG_INIT.store(true, Relaxed);
break;
}
unsafe { libc::usleep(10) };
}

// Prevent overflow of i32
for chunk in dest.chunks_mut(i32::max_value() as usize) {
let ret = unsafe { libc::randABytes(chunk.as_mut_ptr(), chunk.len() as i32) };
if ret < 0 {
return Err(last_os_error());
}
}
Ok(())
}