Merge remote-tracking branch 'ffmancera/bug24658-openssl'

This commit is contained in:
Nick Mathewson 2018-01-23 14:02:45 -05:00
commit 13a2acba3c
8 changed files with 236 additions and 166 deletions

View File

@ -18,6 +18,7 @@
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
#include "crypto.h" #include "crypto.h"
#include "crypto_openssl_mgt.h"
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) #if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0)
#error "We require OpenSSL >= 1.0.0" #error "We require OpenSSL >= 1.0.0"

View File

@ -8,7 +8,7 @@
#define TOR_COMPAT_OPENSSL_H #define TOR_COMPAT_OPENSSL_H
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
#include "crypto_openssl_mgt.h"
/** /**
* \file compat_openssl.h * \file compat_openssl.h
* *

View File

@ -82,40 +82,12 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "keccak-tiny/keccak-tiny.h" #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 */ /** Longest recognized */
#define MAX_DNS_LABEL_SIZE 63 #define MAX_DNS_LABEL_SIZE 63
/** Largest strong entropy request */ /** Largest strong entropy request */
#define MAX_STRONGEST_RAND_SIZE 256 #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. */ /** A public key, or a public/private key-pair. */
struct crypto_pk_t struct crypto_pk_t
{ {
@ -129,7 +101,6 @@ struct crypto_dh_t {
DH *dh; /**< The openssl DH object */ DH *dh; /**< The openssl DH object */
}; };
static int setup_openssl_threading(void);
static int tor_check_dh_key(int severity, const BIGNUM *bn); static int tor_check_dh_key(int severity, const BIGNUM *bn);
/** Return the number of bytes added by padding method <b>padding</b>. /** Return the number of bytes added by padding method <b>padding</b>.
@ -220,52 +191,6 @@ try_load_engine(const char *path, const char *engine)
} }
#endif /* !defined(DISABLE_ENGINES) */ #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 /** Make sure that openssl is using its default PRNG. Return 1 if we had to
* adjust it; 0 otherwise. */ * adjust it; 0 otherwise. */
STATIC int STATIC int
@ -3348,36 +3273,6 @@ memwipe(void *mem, uint8_t byte, size_t sz)
memset(mem, byte, 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 #if 0
/* This code is disabled, because OpenSSL never actually uses these callbacks. /* This code is disabled, because OpenSSL never actually uses these callbacks.
*/ */
@ -3429,29 +3324,6 @@ openssl_dynlock_destroy_cb_(struct CRYPTO_dynlock_value *v,
#endif /* 0 */ #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 /** Uninitialize the crypto library. Return 0 on success. Does not detect
* failure. * failure.
*/ */
@ -3494,8 +3366,7 @@ crypto_global_cleanup(void)
} }
#endif /* !defined(NEW_THREAD_API) */ #endif /* !defined(NEW_THREAD_API) */
tor_free(crypto_openssl_version_str); crypto_openssl_free_all();
tor_free(crypto_openssl_header_version_str);
crypto_early_initialized_ = 0; crypto_early_initialized_ = 0;
crypto_global_initialized_ = 0; crypto_global_initialized_ = 0;

View File

@ -21,41 +21,8 @@
#include "compat.h" #include "compat.h"
#include "util.h" #include "util.h"
#include <openssl/engine.h>
#include "keccak-tiny/keccak-tiny.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. */ /** Length of the output of our message digest. */
#define DIGEST_LEN 20 #define DIGEST_LEN 20
/** Length of the output of our second (improved) message digests. (For now /** Length of the output of our second (improved) message digests. (For now
@ -132,8 +99,6 @@ typedef struct crypto_xof_t crypto_xof_t;
typedef struct crypto_dh_t crypto_dh_t; typedef struct crypto_dh_t crypto_dh_t;
/* global state */ /* 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_early_init(void) ATTR_WUR;
int crypto_global_init(int hardwareAccel, int crypto_global_init(int hardwareAccel,
const char *accelName, const char *accelName,

View File

@ -6,6 +6,7 @@
#include "testsupport.h" #include "testsupport.h"
#include "torint.h" #include "torint.h"
#include "crypto_openssl_mgt.h"
/** Length of a curve25519 public key when encoded. */ /** Length of a curve25519 public key when encoded. */
#define CURVE25519_PUBKEY_LEN 32 #define CURVE25519_PUBKEY_LEN 32

View File

@ -0,0 +1,145 @@
/* 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_mgt.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)
#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) */
/** Declare STATIC functions */
STATIC char * parse_openssl_version_str(const char *raw_version);
#ifndef NEW_THREAD_API
STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
#endif
/* 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);
}
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. */
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) */
/** 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;
}
/** free OpenSSL variables */
void
crypto_openssl_free_all(void)
{
tor_free(crypto_openssl_version_str);
tor_free(crypto_openssl_header_version_str);
}

View File

@ -0,0 +1,85 @@
/* 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>
/*
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) && ... */
/* global openssl state */
const char * crypto_openssl_get_version_str(void);
const char * crypto_openssl_get_header_version_str(void);
/* OpenSSL threading setup function */
int setup_openssl_threading(void);
/* Tor OpenSSL utility functions */
void crypto_openssl_free_all(void);
#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */

View File

@ -113,6 +113,7 @@ LIBOR_CRYPTO_A_SRC = \
src/common/compress_zlib.c \ src/common/compress_zlib.c \
src/common/compress_zstd.c \ src/common/compress_zstd.c \
src/common/crypto.c \ src/common/crypto.c \
src/common/crypto_openssl_mgt.c \
src/common/crypto_pwbox.c \ src/common/crypto_pwbox.c \
src/common/crypto_s2k.c \ src/common/crypto_s2k.c \
src/common/crypto_format.c \ src/common/crypto_format.c \
@ -164,6 +165,7 @@ COMMONHEADERS = \
src/common/crypto_curve25519.h \ src/common/crypto_curve25519.h \
src/common/crypto_ed25519.h \ src/common/crypto_ed25519.h \
src/common/crypto_format.h \ src/common/crypto_format.h \
src/common/crypto_openssl_mgt.h \
src/common/crypto_pwbox.h \ src/common/crypto_pwbox.h \
src/common/crypto_s2k.h \ src/common/crypto_s2k.h \
src/common/di_ops.h \ src/common/di_ops.h \