diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2017-05-30 20:56:15 -0500 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2017-05-30 21:56:15 -0400 |
commit | b637aec1624e558b0e158064264a2523a4dcba31 (patch) | |
tree | 02709cf3c87c29375e1fc52100648709a7625abf /src/_cffi_src | |
parent | 5ca7eb75069883bc5be9a078ee85207461fb5d55 (diff) | |
download | cryptography-b637aec1624e558b0e158064264a2523a4dcba31.tar.gz cryptography-b637aec1624e558b0e158064264a2523a4dcba31.tar.bz2 cryptography-b637aec1624e558b0e158064264a2523a4dcba31.zip |
runtime detection of getentropy for macOS via weak-linking (#3650)
* runtime detection of getentropy for macOS via weak-linking
In the before time, in the long long ago, there was a desire to use
getentropy on macOS. So some code was written and it detected getentropy
support by seeing if SYS_getentropy was available in the headers. But
lo, it turns out Apple ships headers for different SDK versions and
users on < 10.12 were getting headers that had SYS_getentropy even
though their OS did not support it. There was much wailing and
gnashing of teeth, but the frustrated developers remembered that Apple
wants their developers to use weak linking. With weak linking the mighty
developer can specify a minimum version and any symbol that was added
after that version will be weakly linked. Then, at runtime, the dynamic
linker will make unavailable symbols thus marked into NULLs. So, the
developer need only alter their code to do runtime detection of weakly
linked symbols and then a single binary may be compiled that will
correctly select getentropy or /dev/urandom at runtime. Hallelujah!
* oops
* separate the enum
* okay just apple
Diffstat (limited to 'src/_cffi_src')
-rw-r--r-- | src/_cffi_src/openssl/src/osrandom_engine.c | 58 | ||||
-rw-r--r-- | src/_cffi_src/openssl/src/osrandom_engine.h | 19 |
2 files changed, 55 insertions, 22 deletions
diff --git a/src/_cffi_src/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c index d5c73868..0f51e99b 100644 --- a/src/_cffi_src/openssl/src/osrandom_engine.c +++ b/src/_cffi_src/openssl/src/osrandom_engine.c @@ -199,28 +199,50 @@ static void dev_urandom_close(void) { #if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY static const char *Cryptography_osrandom_engine_name = "osrandom_engine getentropy()"; +static int getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_NOT_INIT; + static int osrandom_init(ENGINE *e) { +#if !defined(__APPLE__) + getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS; +#else + if (getentropy != NULL) { + getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS; + } else { + getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK; + int fd = dev_urandom_fd(); + if (fd < 0) { + return 0; + } + } +#endif return 1; } static int osrandom_rand_bytes(unsigned char *buffer, int size) { int len, res; - while (size > 0) { - /* OpenBSD and macOS restrict maximum buffer size to 256. */ - len = size > 256 ? 256 : size; - res = getentropy(buffer, len); - if (res < 0) { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED, - __FILE__, __LINE__ - ); - return 0; + + switch(getentropy_works) { + case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK: + return dev_urandom_read(buffer, size); + case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS: + while (size > 0) { + /* OpenBSD and macOS restrict maximum buffer size to 256. */ + len = size > 256 ? 256 : size; + res = getentropy(buffer, len); + if (res < 0) { + ERR_Cryptography_OSRandom_error( + CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, + CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED, + __FILE__, __LINE__ + ); + return 0; + } + buffer += len; + size -= len; } - buffer += len; - size -= len; + return 1; } - return 1; + __builtin_unreachable(); } static int osrandom_finish(ENGINE *e) { @@ -232,7 +254,13 @@ static int osrandom_rand_status(void) { } static const char *osurandom_get_implementation(void) { - return "getentropy"; + switch(getentropy_works) { + case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK: + return "/dev/urandom"; + case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS: + return "getentropy"; + } + __builtin_unreachable(); } #endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY */ diff --git a/src/_cffi_src/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h index 5abe8fc0..c400ea3e 100644 --- a/src/_cffi_src/openssl/src/osrandom_engine.h +++ b/src/_cffi_src/openssl/src/osrandom_engine.h @@ -13,7 +13,6 @@ #ifdef __APPLE__ #include <sys/random.h> - #include <AvailabilityMacros.h> #endif #ifdef __linux__ @@ -34,11 +33,9 @@ #if defined(_WIN32) /* Windows */ #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM - #elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 - /* macOS 10.12+ */ - #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY - #elif defined(BSD) && defined(SYS_getentropy) && !defined(__APPLE__) - /* OpenBSD 5.6+ */ + #elif defined(BSD) && defined(SYS_getentropy) + /* OpenBSD 5.6+ & macOS with SYS_getentropy defined, although < 10.12 will fallback + * to urandom */ #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY #elif defined(__linux__) && defined(SYS_getrandom) /* Linux 3.4.17+ */ @@ -51,7 +48,9 @@ /* Fallbacks need /dev/urandom helper functions. */ #if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM || \ - CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM + CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM || \ + (CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY && \ + defined(__APPLE__)) #define CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM 1 #endif @@ -62,6 +61,12 @@ enum { CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS }; +enum { + CRYPTOGRAPHY_OSRANDOM_GETENTROPY_NOT_INIT, + CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK, + CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS +}; + /* engine ctrl */ #define CRYPTOGRAPHY_OSRANDOM_GET_IMPLEMENTATION ENGINE_CMD_BASE |