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 for non-blocking getrandom #365

Open
newpavlov opened this issue Jun 6, 2023 · 2 comments
Open

Support for non-blocking getrandom #365

newpavlov opened this issue Jun 6, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@newpavlov
Copy link
Member

In some scenarios (e.g. for seeding HashMap) it's desirable to get potentially less secure numbers than to block indefinitely. The motivation is largely equivalent to motivation behind the GRND_NONBLOCK flag used in the getrandom syscall. We probably should add support for such scenarios, either by adding an additional argument or by introducing a separate set of non-blocking functions.

Relevant PRs: #353 #352

@briansmith
Copy link
Contributor

briansmith commented Oct 5, 2023

  • I support adding a non-blocking API for targets that have native non-blocking syscalls like getrandom on Linux.
  • I'm less eager to implement support for legacy non-blocking reading from "/dev/[u]random".
  • The caller should implement their own fallback logic for when getrandom isn't available.
  • getrandom should not simulate a non-blocking syscall on systems that have no non-blocking API.
  • I don't think applications should have to do #[cfg]-based conditional code to access a non-blocking API. The API should be present everywhere, and in environments where it isn't available, it should return "no non-blocking API available."
  • Failing to get random bytes from a non-blocking call is not an error; it is an expected condition. It shouldn't be modeled as an error.

This suggests an API something like this:

#[must_use]
enum NonBlocking<'a> {
    /// The system successfully filled the buffer with random data.
    Filled(&'a [u8]),

    /// The system is not ready to fulfill the request, but it might be ready later.
    NotReady,

    /// The system doesn't implement a non-blocking API.
    NotImplemented
}
fn getrandom_nonblocking<'a>(dest: &'a mut [u8]) -> Result<NonBlocking<'a>> { ... }
fn getrandom_uninit_nonblocking<'a>(dest: &'a mut [MaybeUninit<u8>])) -> Result<NonBlocking<'a>> { ... }

@newpavlov
Copy link
Member Author

I'm less eager to implement support for legacy non-blocking reading from "/dev/[u]random".

I agree. We could support sources which respect entropy estimates, but I don't think they are used much in practice nowadays.

The caller should implement their own fallback logic for when getrandom isn't available.

I think some platforms may provide randomness even if PRNG did not get enough initialization entropy (like /dev/urandom on Linux and randABytes on VxWorks). In such cases I think it would be better to return less secure randomness than ask users to implement their own fallback (which likely will be even less secure). In other words, we probably should add an option "give me random numbers even if they may be not secure enough".

Failing to get random bytes from a non-blocking call is not an error; it is an expected condition. It shouldn't be modeled as an error.

I think it's fine to return EAGAIN-like errors when user has explicitly asked for a non-blocking source. Our API is relatively low level and "try again" error codes is a common approach with OS APIs.

To summarize, we probably need combination of the following options:

  • Secure, may block (default).
  • Secure, non-blocking, returns "try again" instead of blocking or "not supported".
  • Potentially insecure, may block (on systems which do not support non-blocking API uses the blocking secure API).
  • Potentially insecure, non-blocking, returns "try again" instead of blocking or "not supported".

It may be represented as two separate options: quality of generated randomness and blocking behavior. The former also may include the "super secure" option to cover the GRND_RANDOM flag.

@newpavlov newpavlov added the enhancement New feature or request label Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants