Check if sys/random.h is required for getentropy. #10301

pull jameshilliard wants to merge 1 commits into bitcoin:master from jameshilliard:getentropy-rand changing 2 files +21 −1
  1. jameshilliard commented at 5:26 AM on April 30, 2017: contributor

    This should check and include sys/random.h if required for osx as mentioned here.

  2. fanquake added the label MacOSX on Apr 30, 2017
  3. laanwj commented at 7:11 AM on May 1, 2017: member

    utACK (can someone on MacOSX 10.12+ test this please?)

  4. jameshilliard commented at 2:09 PM on May 1, 2017: contributor

    I tested this on MacOSX 10.12.4 myself, should we have a runtime /dev/random fallback for getentropy like we do for the linux SYS_getrandom?

  5. laanwj commented at 2:26 PM on May 1, 2017: member

    I tested this on MacOSX 10.12.4 myself, should we have a runtime /dev/random fallback for getentropy like we do for the linux SYS_getrandom?

    As I understand it, MacOSX guarantees that anything compiled with the MacOSX 10.12 SDK, which is necessary to get autotools to detect this in the first place doesn't work on earlier versions of the OS. In which case this would be unnecessary.

    Feel free to correct me though @jonasschnelli @theuni.

  6. theuni commented at 6:29 PM on May 1, 2017: member

    @laanwj macOS uses weak imports for new symbols. They're fine to use as long as they're checked at runtime. This is how we're able to build with 10.11 (soon 10.12), but remain back-compat to 10.8. See an example of runtime handling at MacNotificationHandler::hasUserNotificationCenterSupport.

    getentropy does not exist in the 10.11 sdk. So I'm assuming that it is a weak import introduced in 10.12. Meaning that this would (I believe) blow up at runtime on <= 10.11 when built with 10.12.

  7. sipa commented at 10:55 PM on May 1, 2017: member

    @theuni I'm unsure whether your comment above means that this PR is fine or the opposite.

  8. theuni commented at 12:00 AM on May 2, 2017: member

    @sipa Sorry for being unclear. Cautiously, the opposite. I believe that this PR would cause runtime crashes when building with SDK >= 10.12, and running on < 10.12. We definitely need someone to test that scenario before merge, as 10.12 will likely be the SDK we use for 0.15.

  9. jameshilliard commented at 12:02 AM on May 2, 2017: contributor

    @theuni so this means we need to do a runtime check and fallback like we do for SYS_getrandom?

    Something like this maybe?

    if (getentropy != NULL) {
        if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
            RandFailure();
        }
    } else {
        GetDevURandom(ent32);
    }
    
  10. theuni commented at 12:21 AM on May 2, 2017: member

    @jameshilliard Yes. According to the apple docs it would look something like:

    #if defined(HAVE_GETENTROPY_RAND)
    #if defined(MAC_OSX)
    if (getentropy != NULL) {
        getentropy(foo, bar);
    } else {
    // fallback
    }
    #else
    getentropy(foo, bar);
    #endif
    #endif
    
  11. jameshilliard commented at 2:03 AM on May 2, 2017: contributor

    I've added a runtime fallback but I don't have an OSX system with anything older than 10.12 to test against.

  12. jameshilliard commented at 2:28 AM on May 2, 2017: contributor

    Apparently the Solaris version of getentropy is not safe to use directly for cryptographic functions unlike OpenBSD and OSX and getrandom should be used there instead.

    On Solaris the output of getentropy(2) is entropy and should not be used where randomness is needed, in particular it must not be used where an IV or nonce is needed when calling a cryptographic operation. It is intended only for seeding a user space RBG (Random Bit Generator) system. More specifically the data returned by getentropy(2) has not had the required FIPS 140-2 processing for the DRBG applied to it.

  13. sipa commented at 2:32 AM on May 2, 2017: member

    It is intended only for seeding a user space RBG (Random Bit Generator) system.

    Great, that's what we're doing.

  14. jonasschnelli commented at 6:47 AM on May 2, 2017: contributor

    I'll give it a test (build with 10.12 and run it own 10.8). Will report soon.

    And I agree with @theuni (Using getentropy – which way introduced in 10.12 would crash in < 10.12). Here's the 10.12 manpage for genentropy for the records:

    
    
    
    
    
    
    
    GETENTROPY(2)               BSD System Calls Manual              GETENTROPY(2)
    
    NAME
         getentropy -- get entropy
    
    SYNOPSIS
         #include <sys/random.h>
    
         int
         getentropy(void *buf, size_t buflen);
    
    DESCRIPTION
         getentropy() fills a buffer with random data, which can be used as input
         for process-context pseudorandom generators like arc4random(3).
    
         The maximum buffer size permitted is 256 bytes.  If buflen exceeds this,
         an error of EIO will be indicated.
    
         getentropy() should be used as a replacement for random(4) when random
         data derived directly from the kernel random byte generator is required.
         Unlike the random(4) pseudo-devices, it is not vulnerable to file
         descriptor exhaustion attacks and is available when sandboxed or in a
         chroot, making it more reliable for security-critical applications.
    
         However, it should be noted that getentropy() is primarily intended for
         use in the construction and seeding of userspace PRNGs like arc4random(3)
         or CC_crypto(3).  Clients who simply require random data should use
         arc4random(3), CCRandomGenerateBytes() from CC_crypto(3), or
         SecRandomCopyBytes() from the Security framework instead of getentropy()
         or random(4)
    
    RETURN VALUES
         Upon successful completion, the value 0 is returned; otherwise the
         value -1 is returned and the global variable errno is set to indicate the
         error.
    
    ERRORS
         getentropy() will succeed unless:
    
         [EINVAL]           The buf parameter points to an invalid address.
    
         [EIO]              Too many bytes requested, or some other fatal error
                            occurred.
    
    SEE ALSO
         arc4random(3) CC_crypto(3) random(4)
    
    HISTORY
         The getentropy() function appeared in OSX 10.12
    
    BSD                             October 2 2015                             BSD
    
  15. in configure.ac:620 in e0c0e53bc4 outdated
     616 | @@ -617,6 +617,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]],
     617 |   [ AC_MSG_RESULT(no)]
     618 |  )
     619 |  
     620 | +AC_MSG_CHECKING(for getentropy rand)
    


    jonasschnelli commented at 6:56 AM on May 2, 2017:

    nit: for getentropy rand sounds after we are looking for a new identifier/function. I recommend to use for getentropy via random.h.

  16. laanwj commented at 10:36 AM on May 3, 2017: member

    Apparently the Solaris version of getentropy is not safe to use directly for cryptographic functions unlike OpenBSD and OSX and getrandom should be used there instead.

    Most of the OSes warn against using kernel entropy directly for cryptographic primitives. For example OpenBSD:

         getentropy() is not intended for regular code; please use the
         arc4random(3) family of functions instead.
    

    The foremost reason for this is because of the performance characteristics of calling the kernel for every 256 bytes of random data that is needed, the functionality is not set up for high-bandwidth randomness.

    Solaris' reason is more interesting [

    More specifically the data returned by getentropy(2) has not had the required FIPS 140-2 processing for the DRBG applied to it.

    ] This seems to imply that the function returns lower-quality instead of higher-quality entropy?!

    In any case we're fine - we always combine the output with that of the OpenSSL random number generator, the OS entropy is added as an extra safety measure.

  17. in src/random.cpp:245 in c417cf3ba4 outdated
     165 |       * error if more are requested.
     166 |       * The call cannot return less than the requested number of bytes.
     167 |       */
     168 | +    #if defined(MAC_OSX)
     169 | +    // Fallback for OSX < 10.12
     170 | +    if (&getentropy != NULL) {
    


    laanwj commented at 10:44 AM on May 3, 2017:

    It seems harmless to do the &getentropy != NULL check for other platforms too (avoiding the MAC_OSX specific code).

  18. in src/random.cpp:168 in eaef5a3208 outdated
     163 | @@ -164,20 +164,13 @@ void GetOSRand(unsigned char *ent32)
     164 |       * error if more are requested.
     165 |       * The call cannot return less than the requested number of bytes.
     166 |       */
     167 | -    #if defined(MAC_OSX)
     168 | -    // Fallback for OSX < 10.12
    


    laanwj commented at 1:58 PM on May 3, 2017:

    Keeping this comment would make sense (so those reading the code understand why the check is there)

  19. laanwj commented at 10:52 AM on June 7, 2017: member

    This has a lot of discussion but not really (ut)ACKs. Is the current approach ok, anything left to do here?

  20. laanwj assigned theuni on Jun 26, 2017
  21. laanwj commented at 12:17 PM on July 25, 2017: member

    This is no longer relevant after #10855 (only use getentropy on openbsd)

  22. laanwj closed this on Jul 25, 2017

  23. jameshilliard commented at 3:14 PM on July 26, 2017: contributor

    @laanwj It seems #10855 would not result in getentropy being included on systems like OSX, wouldn't this still be needed?

  24. laanwj commented at 5:28 PM on July 26, 2017: member

    That's intentional, getentropy is only to be used on OpenBSD as there it's a system call. On OSX and Linux it's emulation of something at most so there it's not used.

    Edit: hrmph, on so OSX 10.12 it's a system call too, so in principle it could be used, but you'd have to ask @theuni.

  25. jameshilliard commented at 5:39 PM on July 26, 2017: contributor

    on so OSX 10.12 it's a system call too, so in principle it could be used, but you'd have to ask @theuni.

    Yeah, that was the main purpose of this PR.

  26. laanwj reopened this on Jul 26, 2017

  27. laanwj commented at 5:45 PM on July 26, 2017: member

    Reopening then, I had understood from the title that it just adds a check, which would no longer be relevant when the function is only used on obsd. Needs rebase.

  28. gmaxwell commented at 5:55 PM on July 26, 2017: contributor

    This seems to imply that the function returns lower-quality instead of higher-quality entropy?!

    Nah, FIPS 140-2 processing means standard mandated low qualityness. :P Basically they do post processing to make sure they don't return all zeros or whatnot, which means (negligibly) lower entropy. The original motivation is to make certain kinds of hardware RNG failures fail secure instead of fail to making your keys all zeros; but then people go cargo-cult applying these tests on far end of cryptographic whitening, where they make no sense.

    In our case we use it to feed our own entropy pool, so that processing isn't useful for us (to the extent that it's useful anywhere).

  29. Check if sys/random.h is required for getentropy on OSX. ee2d10ad0c
  30. jameshilliard force-pushed on Jul 27, 2017
  31. jameshilliard commented at 12:45 PM on July 27, 2017: contributor

    I've modified this to check for OSX explicitly. Should I try and make this more universal or is that good enough for now?

  32. theuni commented at 3:16 PM on July 31, 2017: member

    I think this is ok as-is. It'd be nice to add a little refactor on top (later) to:

    • early-return on success, and have a single fall-back for /dev/urandom
    • Move detection out to a separate function so that we can log what's in use.
  33. theuni commented at 3:25 PM on July 31, 2017: member

    utACK ee2d10ad0c0e04d0b9da4535a6fff265ac2501e5. I'm a little paranoid that an overly clever linker might try to optimize this check out of lto builds, but the crash would be obvious in that case.

  34. laanwj merged this on Aug 7, 2017
  35. laanwj closed this on Aug 7, 2017

  36. laanwj referenced this in commit 318392ca7c on Aug 7, 2017
  37. PastaPastaPasta referenced this in commit 52aef4cfec on Aug 2, 2019
  38. PastaPastaPasta referenced this in commit 2a295be586 on Aug 6, 2019
  39. barrystyle referenced this in commit be6fb4e218 on Jan 22, 2020
  40. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 18:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me