aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2017-05-30 20:56:15 -0500
committerAlex Gaynor <alex.gaynor@gmail.com>2017-05-30 21:56:15 -0400
commitb637aec1624e558b0e158064264a2523a4dcba31 (patch)
tree02709cf3c87c29375e1fc52100648709a7625abf /src
parent5ca7eb75069883bc5be9a078ee85207461fb5d55 (diff)
downloadcryptography-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')
-rw-r--r--src/_cffi_src/openssl/src/osrandom_engine.c58
-rw-r--r--src/_cffi_src/openssl/src/osrandom_engine.h19
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