Skip to content

Conversation

@lpereira
Copy link
Contributor

@lpereira lpereira commented Jan 8, 2020

Linux-specific getrandom(2) will generate random numbers drawing from the same pool as /dev/urandom when called with the GRND_NONBLOCK flag. This avoids having an open file descriptor at all times for random number generation.

In order to introduce the possibility of using this system call, the code has been cleaned up as such:

  • Auxiliary functions have been introduced to fill a buffer with random numbers, for various different methods
  • Opening /dev/urandom will only happen if getrandom() or arc4random() aren't available; otherwise, no file descriptor will be used for that
  • XORing with results from lrand48() will only happen if we detect that the first few bytes are either 0- or 1-filled. There is a comment explaining the rationale.
  • Even if XORing is deemed necessary, the loop will now XOR 4 bytes at a time instead of just 1 at a time.

@lpereira
Copy link
Contributor Author

lpereira commented Jan 8, 2020

(Figuring out now how to write benchmarks for this.)

@lpereira lpereira requested a review from janvorli January 8, 2020 00:50
@lpereira lpereira force-pushed the use-getrandom-for-interop-getrandombytes branch from 869f99c to 578be74 Compare January 9, 2020 00:43
Linux-specific getrandom(2) will generate random numbers drawing from
the same pool as /dev/urandom when called with the GRND_NONBLOCK flag.
This avoids having an open file descriptor at all times for random
number generation.

In order to introduce the possibility of using this system call, the
code has been cleaned up as such:

 - Auxiliary functions have been introduced to fill a buffer with
   random numbers, for various different methods
 - Opening /dev/urandom will only happen if getrandom() or arc4random()
   aren't available; otherwise, no file descriptor will be used for
   that
 - XORing with results from lrand48() will only happen if we detect that
   the first few bytes are either 0- or 1-filled.  There is a comment
   explaining the rationale.
 - Even if XORing is deemed necessary, the loop will now XOR 4 bytes at
   a time instead of just 1 at a time.
@lpereira lpereira force-pushed the use-getrandom-for-interop-getrandombytes branch from 578be74 to dc381eb Compare January 15, 2020 22:50

lastLrandRound = 0;
// Ensure dead store elimination does not yank the previous assignment
__asm__ __volatile__("" ::"g"(lastLrandRound) : "memory");
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure I understand why we assign to the variable right before it goes out of scope at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a common defensive programming strategy to avoid having potentially sensitive data in some register. It doesn't guarantee much (e.g. vectorized memcpy() can keep stuff in SIMD registers), though.

Copy link
Member

Choose a reason for hiding this comment

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

Why is it important to use this defensive strategy here?

@stephentoub
Copy link
Member

@lpereira, what's the status of this?

@stephentoub
Copy link
Member

stephentoub commented Apr 17, 2020

@lpereira informed me she won't be working on this any more, so I'm going to close it. If anyone's interested in completing it, please feel free to cherry-pick and open a new PR. Thanks.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants