commit 4022277272b5213ef34cfeed46d006800b131687 Author: Fernando Fernandez Mancera ffernandezmancera@gmail.com Date: Mon Jan 8 13:57:06 2018 +0100
Refactor crypto.[ch] into smaller OpenSSL module.
Add two new files (crypto_openssl.c, crypto_openssl.h) as new module of crypto.[ch]. This new module includes all functions and dependencies related to OpenSSL management. Those have been removed from crypto.[ch].
All new changes related to OpenSSL management must be done in these files.
Follows #24658
Signed-off-by: Fernando Fernandez Mancera ffernandezmancera@gmail.com --- src/common/crypto.c | 143 -------------------------------------------- src/common/crypto.h | 35 ----------- src/common/crypto_openssl.c | 115 +++++++++++++++++++++++++++++++++++ src/common/crypto_openssl.h | 105 ++++++++++++++++++++++++++++++++ 4 files changed, 220 insertions(+), 178 deletions(-)
diff --git a/src/common/crypto.c b/src/common/crypto.c index c9db7cb4b..0abb4a1af 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -29,21 +29,6 @@ #include "crypto_ed25519.h" #include "crypto_format.h"
-DISABLE_GCC_WARNING(redundant-decls) - -#include <openssl/err.h> -#include <openssl/rsa.h> -#include <openssl/pem.h> -#include <openssl/evp.h> -#include <openssl/engine.h> -#include <openssl/rand.h> -#include <openssl/bn.h> -#include <openssl/dh.h> -#include <openssl/conf.h> -#include <openssl/hmac.h> - -ENABLE_GCC_WARNING(redundant-decls) - #if __GNUC__ && GCC_VERSION >= 402 #if GCC_VERSION >= 406 #pragma GCC diagnostic pop @@ -82,40 +67,12 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "keccak-tiny/keccak-tiny.h"
-#ifdef ANDROID -/* Android's OpenSSL seems to have removed all of its Engine support. */ -#define DISABLE_ENGINES -#endif - -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \ - !defined(LIBRESSL_VERSION_NUMBER) -/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require - * seting up various callbacks. - * - * OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype, - * while the previous one was restored in pre5, and the function made a no-op - * (along with a deprecated annotation, which produces a compiler warning). - * - * While it is possible to support all three versions of the thread API, - * a version that existed only for one snapshot pre-release is kind of - * pointless, so let's not. - */ -#define NEW_THREAD_API -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */ - /** Longest recognized */ #define MAX_DNS_LABEL_SIZE 63
/** Largest strong entropy request */ #define MAX_STRONGEST_RAND_SIZE 256
-#ifndef NEW_THREAD_API -/** A number of preallocated mutexes for use by OpenSSL. */ -static tor_mutex_t **openssl_mutexes_ = NULL; -/** How many mutexes have we allocated for use by OpenSSL? */ -static int n_openssl_mutexes_ = 0; -#endif /* !defined(NEW_THREAD_API) */ - /** A public key, or a public/private key-pair. */ struct crypto_pk_t { @@ -129,7 +86,6 @@ struct crypto_dh_t { DH *dh; /**< The openssl DH object */ };
-static int setup_openssl_threading(void); static int tor_check_dh_key(int severity, const BIGNUM *bn);
/** Return the number of bytes added by padding method <b>padding</b>. @@ -220,52 +176,6 @@ try_load_engine(const char *path, const char *engine) } #endif /* !defined(DISABLE_ENGINES) */
-/* Returns a trimmed and human-readable version of an openssl version string -* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10 -* May 2012' and this will parse them into a form similar to '1.0.0b' */ -static char * -parse_openssl_version_str(const char *raw_version) -{ - const char *end_of_version = NULL; - /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's - trim that down. */ - if (!strcmpstart(raw_version, "OpenSSL ")) { - raw_version += strlen("OpenSSL "); - end_of_version = strchr(raw_version, ' '); - } - - if (end_of_version) - return tor_strndup(raw_version, - end_of_version-raw_version); - else - return tor_strdup(raw_version); -} - -static char *crypto_openssl_version_str = NULL; -/* Return a human-readable version of the run-time openssl version number. */ -const char * -crypto_openssl_get_version_str(void) -{ - if (crypto_openssl_version_str == NULL) { - const char *raw_version = OpenSSL_version(OPENSSL_VERSION); - crypto_openssl_version_str = parse_openssl_version_str(raw_version); - } - return crypto_openssl_version_str; -} - -static char *crypto_openssl_header_version_str = NULL; -/* Return a human-readable version of the compile-time openssl version -* number. */ -const char * -crypto_openssl_get_header_version_str(void) -{ - if (crypto_openssl_header_version_str == NULL) { - crypto_openssl_header_version_str = - parse_openssl_version_str(OPENSSL_VERSION_TEXT); - } - return crypto_openssl_header_version_str; -} - /** Make sure that openssl is using its default PRNG. Return 1 if we had to * adjust it; 0 otherwise. */ STATIC int @@ -3347,36 +3257,6 @@ memwipe(void *mem, uint8_t byte, size_t sz) memset(mem, byte, sz); }
-#ifndef OPENSSL_THREADS -#error OpenSSL has been built without thread support. Tor requires an \ - OpenSSL library with thread support enabled. -#endif - -#ifndef NEW_THREAD_API -/** Helper: OpenSSL uses this callback to manipulate mutexes. */ -static void -openssl_locking_cb_(int mode, int n, const char *file, int line) -{ - (void)file; - (void)line; - if (!openssl_mutexes_) - /* This is not a really good fix for the - * "release-freed-lock-from-separate-thread-on-shutdown" problem, but - * it can't hurt. */ - return; - if (mode & CRYPTO_LOCK) - tor_mutex_acquire(openssl_mutexes_[n]); - else - tor_mutex_release(openssl_mutexes_[n]); -} - -static void -tor_set_openssl_thread_id(CRYPTO_THREADID *threadid) -{ - CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id()); -} -#endif /* !defined(NEW_THREAD_API) */ - #if 0 /* This code is disabled, because OpenSSL never actually uses these callbacks. */ @@ -3428,29 +3308,6 @@ openssl_dynlock_destroy_cb_(struct CRYPTO_dynlock_value *v, #endif /* 0 */
/** @{ */ -/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being - * multithreaded. Returns 0. */ -static int -setup_openssl_threading(void) -{ -#ifndef NEW_THREAD_API - int i; - int n = CRYPTO_num_locks(); - n_openssl_mutexes_ = n; - openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *)); - for (i=0; i < n; ++i) - openssl_mutexes_[i] = tor_mutex_new(); - CRYPTO_set_locking_callback(openssl_locking_cb_); - CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id); -#endif /* !defined(NEW_THREAD_API) */ -#if 0 - CRYPTO_set_dynlock_create_callback(openssl_dynlock_create_cb_); - CRYPTO_set_dynlock_lock_callback(openssl_dynlock_lock_cb_); - CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_); -#endif - return 0; -} - /** Uninitialize the crypto library. Return 0 on success. Does not detect * failure. */ diff --git a/src/common/crypto.h b/src/common/crypto.h index f9aeeee2c..879af45fe 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -20,41 +20,8 @@ #include "testsupport.h" #include "compat.h"
-#include <openssl/engine.h> #include "keccak-tiny/keccak-tiny.h"
-/* - Macro to create an arbitrary OpenSSL version number as used by - OPENSSL_VERSION_NUMBER or SSLeay(), since the actual numbers are a bit hard - to read. - - Don't use this directly, instead use one of the other OPENSSL_V macros - below. - - The format is: 4 bits major, 8 bits minor, 8 bits fix, 8 bits patch, 4 bit - status. - */ -#define OPENSSL_VER(a,b,c,d,e) \ - (((a)<<28) | \ - ((b)<<20) | \ - ((c)<<12) | \ - ((d)<< 4) | \ - (e)) -/** An openssl release number. For example, OPENSSL_V(0,9,8,'j') is the - * version for the released version of 0.9.8j */ -#define OPENSSL_V(a,b,c,d) \ - OPENSSL_VER((a),(b),(c),(d)-'a'+1,0xf) -/** An openssl release number for the first release in the series. For - * example, OPENSSL_V_NOPATCH(1,0,0) is the first released version of OpenSSL - * 1.0.0. */ -#define OPENSSL_V_NOPATCH(a,b,c) \ - OPENSSL_VER((a),(b),(c),0,0xf) -/** The first version that would occur for any alpha or beta in an openssl - * series. For example, OPENSSL_V_SERIES(0,9,8) is greater than any released - * 0.9.7, and less than any released 0.9.8. */ -#define OPENSSL_V_SERIES(a,b,c) \ - OPENSSL_VER((a),(b),(c),0,0) - /** Length of the output of our message digest. */ #define DIGEST_LEN 20 /** Length of the output of our second (improved) message digests. (For now @@ -131,8 +98,6 @@ typedef struct crypto_xof_t crypto_xof_t; typedef struct crypto_dh_t crypto_dh_t;
/* global state */ -const char * crypto_openssl_get_version_str(void); -const char * crypto_openssl_get_header_version_str(void); int crypto_early_init(void) ATTR_WUR; int crypto_global_init(int hardwareAccel, const char *accelName, diff --git a/src/common/crypto_openssl.c b/src/common/crypto_openssl.c new file mode 100644 index 000000000..03485c052 --- /dev/null +++ b/src/common/crypto_openssl.c @@ -0,0 +1,115 @@ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file crypto_openssl.c + * + * \brief Block of functions related to operations from OpenSSL. + **/ + +#include "crypto_openssl.h" + +#ifndef NEW_THREAD_API +/** A number of preallocated mutexes for use by OpenSSL. */ +tor_mutex_t **openssl_mutexes_ = NULL; +/** How many mutexes have we allocated for use by OpenSSL? */ +int n_openssl_mutexes_ = 0; +#endif /* !defined(NEW_THREAD_API) */ + +/* Returns a trimmed and human-readable version of an openssl version string +* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10 +* May 2012' and this will parse them into a form similar to '1.0.0b' */ +char * +parse_openssl_version_str(const char *raw_version) +{ + const char *end_of_version = NULL; + /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's + trim that down. */ + if (!strcmpstart(raw_version, "OpenSSL ")) { + raw_version += strlen("OpenSSL "); + end_of_version = strchr(raw_version, ' '); + } + + if (end_of_version) + return tor_strndup(raw_version, + end_of_version-raw_version); + else + return tor_strdup(raw_version); +} + +char *crypto_openssl_version_str = NULL; +/* Return a human-readable version of the run-time openssl version number. */ +const char * +crypto_openssl_get_version_str(void) +{ + if (crypto_openssl_version_str == NULL) { + const char *raw_version = OpenSSL_version(OPENSSL_VERSION); + crypto_openssl_version_str = parse_openssl_version_str(raw_version); + } + return crypto_openssl_version_str; +} + +char *crypto_openssl_header_version_str = NULL; +/* Return a human-readable version of the compile-time openssl version +* number. */ +const char * +crypto_openssl_get_header_version_str(void) +{ + if (crypto_openssl_header_version_str == NULL) { + crypto_openssl_header_version_str = + parse_openssl_version_str(OPENSSL_VERSION_TEXT); + } + return crypto_openssl_header_version_str; +} + +#ifndef OPENSSL_THREADS +#error OpenSSL has been built without thread support. Tor requires an \ + OpenSSL library with thread support enabled. +#endif + +#ifndef NEW_THREAD_API +/** Helper: OpenSSL uses this callback to manipulate mutexes. */ +void +openssl_locking_cb_(int mode, int n, const char *file, int line) +{ + (void)file; + (void)line; + if (!openssl_mutexes_) + /* This is not a really good fix for the + * "release-freed-lock-from-separate-thread-on-shutdown" problem, but + * it can't hurt. */ + return; + if (mode & CRYPTO_LOCK) + tor_mutex_acquire(openssl_mutexes_[n]); + else + tor_mutex_release(openssl_mutexes_[n]); +} + +void +tor_set_openssl_thread_id(CRYPTO_THREADID *threadid) +{ + CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id()); +} +#endif /* !defined(NEW_THREAD_API) */ + +/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being + * multithreaded. Returns 0. */ +int +setup_openssl_threading(void) +{ +#ifndef NEW_THREAD_API + int i; + int n = CRYPTO_num_locks(); + n_openssl_mutexes_ = n; + openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *)); + for (i=0; i < n; ++i) + openssl_mutexes_[i] = tor_mutex_new(); + CRYPTO_set_locking_callback(openssl_locking_cb_); + CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id); +#endif /* !defined(NEW_THREAD_API) */ + return 0; +} + diff --git a/src/common/crypto_openssl.h b/src/common/crypto_openssl.h new file mode 100644 index 000000000..7b5545f69 --- /dev/null +++ b/src/common/crypto_openssl.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file crypto_openssl.h + * + * \brief Headers for crypto_openssl.c + **/ + +#ifndef TOR_CRYPTO_OPENSSL_H +#define TOR_CRYPTO_OPENSSL_H + +#include <stdio.h> +#include "util.h" + +#include <openssl/engine.h> + +DISABLE_GCC_WARNING(redundant-decls) + +#include <openssl/err.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/evp.h> +#include <openssl/engine.h> +#include <openssl/rand.h> +#include <openssl/bn.h> +#include <openssl/dh.h> +#include <openssl/conf.h> +#include <openssl/hmac.h> + +ENABLE_GCC_WARNING(redundant-decls) + +/* + Macro to create an arbitrary OpenSSL version number as used by + OPENSSL_VERSION_NUMBER or SSLeay(), since the actual numbers are a bit hard + to read. + + Don't use this directly, instead use one of the other OPENSSL_V macros + below. + + The format is: 4 bits major, 8 bits minor, 8 bits fix, 8 bits patch, 4 bit + status. + */ +#define OPENSSL_VER(a,b,c,d,e) \ + (((a)<<28) | \ + ((b)<<20) | \ + ((c)<<12) | \ + ((d)<< 4) | \ + (e)) +/** An openssl release number. For example, OPENSSL_V(0,9,8,'j') is the + * version for the released version of 0.9.8j */ +#define OPENSSL_V(a,b,c,d) \ + OPENSSL_VER((a),(b),(c),(d)-'a'+1,0xf) +/** An openssl release number for the first release in the series. For + * example, OPENSSL_V_NOPATCH(1,0,0) is the first released version of OpenSSL + * 1.0.0. */ +#define OPENSSL_V_NOPATCH(a,b,c) \ + OPENSSL_VER((a),(b),(c),0,0xf) +/** The first version that would occur for any alpha or beta in an openssl + * series. For example, OPENSSL_V_SERIES(0,9,8) is greater than any released + * 0.9.7, and less than any released 0.9.8. */ +#define OPENSSL_V_SERIES(a,b,c) \ + OPENSSL_VER((a),(b),(c),0,0) + +#ifdef ANDROID +/* Android's OpenSSL seems to have removed all of its Engine support. */ +#define DISABLE_ENGINES +#endif + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \ + !defined(LIBRESSL_VERSION_NUMBER) +/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require + * seting up various callbacks. + * + * OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype, + * while the previous one was restored in pre5, and the function made a no-op + * (along with a deprecated annotation, which produces a compiler warning). + * + * While it is possible to support all three versions of the thread API, + * a version that existed only for one snapshot pre-release is kind of + * pointless, so let's not. + */ +#define NEW_THREAD_API +#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */ + +tor_mutex_t **openssl_mutexes_; +int n_openssl_mutexes_; + +/* global openssl state */ +const char * crypto_openssl_get_version_str(void); +const char * crypto_openssl_get_header_version_str(void); + +/* generics OpenSSL functions */ +char * parse_openssl_version_str(const char *raw_version); +void openssl_locking_cb_(int mode, int n, const char *file, int line); +void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid); + +/* OpenSSL threading setup function */ +int setup_openssl_threading(void); + +#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */ +
tor-commits@lists.torproject.org