Commit fdaa4830 authored by Nick Mathewson's avatar Nick Mathewson
Browse files

Merge branch 'nss_dh_squashed' into nss_dh_squashed_merged

parents 7e4ac028 17f922d3
......@@ -133,6 +133,14 @@ TOR_INTERNAL_TESTING_LIBS = \
src/lib/libtor-trace.a
endif
TOR_LDFLAGS_CRYPTLIB=@TOR_LDFLAGS_openssl@
TOR_LIBS_CRYPTLIB=@TOR_OPENSSL_LIBS@
TOR_CFLAGS_CRYPTLIB=
if USE_NSS
TOR_CFLAGS_CRYPTLIB+=@NSS_CFLAGS@
TOR_LIBS_CRYPTLIB+=@NSS_LIBS@
endif
# All libraries used to link tor-cov
include src/include.am
......
o Major features (experimental, library support):
- When built with --enable-nss, Tor now uses the NSS library for digests,
AES, and pseudorandom numbers. Closes ticket 26815.
o Major features (experimental, library support):
- Tor now has _partial_ support for using the NSS cryptography library in
place of OpenSSL. When Tor is configured with --enable-nss, it will
use NSS for several (but not yet all) of its cryptography. (It still
relies on OpenSSL for the rest.) Eventually, if all goes as planned,
"--enable-nss" will produce a version of Tor that does not depend on
OpenSSL. Implements ticket 26816.
WARNING: This feature is experimental. Don't use it for real security
yet, until the code has had much more review, and more bugs have been
shaken out.
......@@ -5,6 +5,7 @@
BUILDDIR=@BUILDDIR@
TOR_LDFLAGS_zlib=@TOR_LDFLAGS_zlib@
TOR_LDFLAGS_nss=@TOR_LDFLAGS_nss@
TOR_LDFLAGS_openssl=@TOR_LDFLAGS_openssl@
TOR_LDFLAGS_libevent=@TOR_LDFLAGS_libevent@
TOR_ZLIB_LIBS=@TOR_ZLIB_LIBS@
......@@ -20,3 +21,4 @@ TOR_LZMA_LIBS=@TOR_LZMA_LIBS@
TOR_ZSTD_LIBS=@TOR_ZSTD_LIBS@
LIBS=@LIBS@
LDFLAGS=@LDFLAGS@
NSS_LIBS=@NSS_LIBS@
\ No newline at end of file
......@@ -53,6 +53,8 @@ AC_ARG_ENABLE(restart-debugging,
AS_HELP_STRING(--enable-restart-debugging, [Build Tor with support for debugging in-process restart. Developers only.]))
AC_ARG_ENABLE(zstd-advanced-apis,
AS_HELP_STRING(--disable-zstd-advanced-apis, [Build without support for zstd's "static-only" APIs.]))
AC_ARG_ENABLE(nss,
AS_HELP_STRING(--enable-nss, [Use Mozilla's NSS TLS library. (EXPERIMENTAL)]))
if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then
AC_MSG_ERROR([Can't disable assertions outside of coverage build])
......@@ -64,6 +66,15 @@ AM_CONDITIONAL(DISABLE_ASSERTS_IN_UNIT_TESTS, test "x$enable_asserts_in_tests" =
AM_CONDITIONAL(LIBFUZZER_ENABLED, test "x$enable_libfuzzer" = "xyes")
AM_CONDITIONAL(OSS_FUZZ_ENABLED, test "x$enable_oss_fuzz" = "xyes")
AM_CONDITIONAL(USE_RUST, test "x$enable_rust" = "xyes")
AM_CONDITIONAL(USE_NSS, test "x$enable_nss" = "xyes")
AM_CONDITIONAL(USE_OPENSSL, true)
if test "x$enable_nss" = "xyes"; then
AC_DEFINE(ENABLE_NSS, 1,
[Defined if we're building with NSS in addition to OpenSSL.])
fi
AC_DEFINE(ENABLE_OPENSSL, 1,
[Defined if we're building with OpenSSL or LibreSSL])
if test "$enable_static_tor" = "yes"; then
enable_static_libevent="yes";
......@@ -847,6 +858,17 @@ fi
LIBS="$save_LIBS"
AC_SUBST(TOR_LIB_MATH)
dnl ------------------------------------------------------
dnl Hello, NSS. You're new around here.
if test "x$enable_nss" = "xyes"; then
PKG_CHECK_MODULES(NSS,
[nss],
[have_nss=yes],
[have_nss=no; AC_MSG_ERROR([You asked for NSS but I can't find it.])])
AC_SUBST(NSS_CFLAGS)
AC_SUBST(NSS_LIBS)
fi
dnl ------------------------------------------------------
dnl Where do you live, openssl? And how do we call you?
......
......@@ -14,10 +14,10 @@ src_app_tor_SOURCES = src/app/main/tor_main.c
# This seems to matter nowhere but on windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
src_app_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
src_app_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
src_app_tor_LDADD = $(TOR_INTERNAL_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
......@@ -26,9 +26,9 @@ if COVERAGE_ENABLED
src_app_tor_cov_SOURCES = $(src_app_tor_SOURCES)
src_app_tor_cov_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_app_tor_cov_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_app_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
src_app_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
src_app_tor_cov_LDADD = $(TOR_INTERNAL_TESTING_LIBS) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ \
@CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
......
......@@ -22,7 +22,7 @@
#define ONION_NTOR_PRIVATE
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_hkdf.h"
#include "lib/crypt_ops/crypto_util.h"
......
......@@ -7,7 +7,7 @@
#include "core/or/or.h"
#include "core/or/circuitlist.h"
#include "app/config/config.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_util.h"
#include "core/crypto/hs_ntor.h" // for HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN
#include "core/or/relay.h"
......
......@@ -121,6 +121,7 @@
#include "lib/evloop/compat_libevent.h"
#include "lib/encoding/confline.h"
#include "lib/evloop/timers.h"
#include "lib/crypt_ops/crypto_init.h"
#include <event2/event.h>
......
......@@ -27,7 +27,8 @@
#include "lib/cc/torint.h"
#include "lib/container/map.h"
#include "lib/container/smartlist.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_rsa.h"
#include "lib/ctime/di_ops.h"
#include "lib/defs/dh_sizes.h"
#include "lib/encoding/binascii.h"
......
......@@ -25,6 +25,7 @@
#ifdef TINYTEST_LOCAL
#include "tinytest_local.h"
#endif
#define TINYTEST_POSTFORK
#include <stdio.h>
#include <stdlib.h>
......@@ -118,6 +119,12 @@ testcase_run_bare_(const struct testcase_t *testcase)
#ifndef NO_FORKING
#ifdef TINYTEST_POSTFORK
void tinytest_postfork(void);
#else
static void tinytest_postfork(void) { }
#endif
static enum outcome
testcase_run_forked_(const struct testgroup_t *group,
const struct testcase_t *testcase)
......@@ -187,6 +194,7 @@ testcase_run_forked_(const struct testgroup_t *group,
int test_r, write_r;
char b[1];
close(outcome_pipe[0]);
tinytest_postfork();
test_r = testcase_run_bare_(testcase);
assert(0<=(int)test_r && (int)test_r<=2);
b[0] = "NYS"[test_r];
......
......@@ -14,7 +14,7 @@
#include "lib/string/util_string.h"
#include "lib/string/printf.h"
#include "lib/memarea/memarea.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_rsa.h"
#include <string.h>
......
......@@ -55,6 +55,7 @@
#include "lib/tls/tortls.h"
#include "lib/encoding/confline.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_init.h"
/**
* \file router.c
......
......@@ -12,7 +12,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "app/config/config.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "core/or/dos.h"
#include "core/or/relay.h"
#include "feature/rend/rendmid.h"
......
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file aes_nss.c
* \brief Use NSS to implement AES_CTR.
**/
#include "orconfig.h"
#include "lib/crypt_ops/aes.h"
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/util_bug.h"
DISABLE_GCC_WARNING(strict-prototypes)
#include <pk11pub.h>
#include <secerr.h>
ENABLE_GCC_WARNING(strict-prototypes)
aes_cnt_cipher_t *
aes_new_cipher(const uint8_t *key, const uint8_t *iv,
int key_bits)
{
const CK_MECHANISM_TYPE ckm = CKM_AES_CTR;
SECItem keyItem = { .type = siBuffer,
.data = (unsigned char *)key,
.len = (key_bits / 8) };
CK_AES_CTR_PARAMS params;
params.ulCounterBits = 128;
memcpy(params.cb, iv, 16);
SECItem ivItem = { .type = siBuffer,
.data = (unsigned char *)&params,
.len = sizeof(params) };
PK11SlotInfo *slot = NULL;
PK11SymKey *keyObj = NULL;
SECItem *ivObj = NULL;
PK11Context *result = NULL;
slot = PK11_GetBestSlot(ckm, NULL);
if (!slot)
goto err;
keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap,
CKA_ENCRYPT, &keyItem, NULL);
if (!keyObj)
goto err;
ivObj = PK11_ParamFromIV(ckm, &ivItem);
if (!ivObj)
goto err;
PORT_SetError(SEC_ERROR_IO);
result = PK11_CreateContextBySymKey(ckm, CKA_ENCRYPT, keyObj, ivObj);
err:
memwipe(&params, 0, sizeof(params));
if (ivObj)
SECITEM_FreeItem(ivObj, PR_TRUE);
if (keyObj)
PK11_FreeSymKey(keyObj);
if (slot)
PK11_FreeSlot(slot);
tor_assert(result);
return (aes_cnt_cipher_t *)result;
}
void
aes_cipher_free_(aes_cnt_cipher_t *cipher)
{
if (!cipher)
return;
PK11_DestroyContext((PK11Context*) cipher, PR_TRUE);
}
void
aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data_, size_t len_)
{
tor_assert(len_ <= INT_MAX);
SECStatus s;
PK11Context *ctx = (PK11Context*)cipher;
unsigned char *data = (unsigned char *)data_;
int len = (int) len_;
int result_len = 0;
s = PK11_CipherOp(ctx, data, &result_len, len, data, len);
tor_assert(s == SECSuccess);
tor_assert(result_len == len);
}
int
evaluate_evp_for_aes(int force_value)
{
(void)force_value;
return 0;
}
int
evaluate_ctr_for_aes(void)
{
return 0;
}
......@@ -5,8 +5,8 @@
/* See LICENSE for licensing information */
/**
* \file aes.c
* \brief Implements a counter-mode stream cipher on top of AES.
* \file aes_openssl.c
* \brief Use OpenSSL to implement AES_CTR.
**/
#include "orconfig.h"
......
......@@ -5,280 +5,23 @@
/* See LICENSE for licensing information */
/**
* \file crypto.c
* \brief Wrapper functions to present a consistent interface to
* public-key and symmetric cryptography operations from OpenSSL and
* other places.
* \file crypto_cipher.c
* \brief Symmetric cryptography (low-level) with AES.
**/
#include "orconfig.h"
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h>
/* Windows defines this; so does OpenSSL 0.9.8h and later. We don't actually
* use either definition. */
#undef OCSP_RESPONSE
#endif /* defined(_WIN32) */
#define CRYPTO_PRIVATE
#include "lib/crypt_ops/compat_openssl.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_rsa.h"
#include "lib/crypt_ops/crypto_util.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/conf.h>
#include <openssl/hmac.h>
#include <openssl/ssl.h>
ENABLE_GCC_WARNING(redundant-decls)
#if __GNUC__ && GCC_VERSION >= 402
#if GCC_VERSION >= 406
#pragma GCC diagnostic pop
#else
#pragma GCC diagnostic warning "-Wredundant-decls"
#endif
#endif /* __GNUC__ && GCC_VERSION >= 402 */
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/cc/torint.h"
#include "lib/crypt_ops/aes.h"
#include "lib/encoding/binascii.h"
#include "keccak-tiny/keccak-tiny.h"
#include "siphash.h"
#include <string.h>
/** Boolean: has OpenSSL's crypto been initialized? */
static int crypto_early_initialized_ = 0;
/** Boolean: has OpenSSL's crypto been initialized? */
static int crypto_global_initialized_ = 0;
#ifndef DISABLE_ENGINES
/** Log any OpenSSL engines we're using at NOTICE. */
static void
log_engine(const char *fn, ENGINE *e)
{
if (e) {
const char *name, *id;
name = ENGINE_get_name(e);
id = ENGINE_get_id(e);
log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
fn, name?name:"?", id?id:"?");
} else {
log_info(LD_CRYPTO, "Using default implementation for %s", fn);
}
}
#endif /* !defined(DISABLE_ENGINES) */
#ifndef DISABLE_ENGINES
/** Try to load an engine in a shared library via fully qualified path.
*/
static ENGINE *
try_load_engine(const char *path, const char *engine)
{
ENGINE *e = ENGINE_by_id("dynamic");
if (e) {
if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
!ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
!ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
ENGINE_free(e);
e = NULL;
}
}
return e;
}
#endif /* !defined(DISABLE_ENGINES) */
static int have_seeded_siphash = 0;
/** Set up the siphash key if we haven't already done so. */
int
crypto_init_siphash_key(void)
{
struct sipkey key;
if (have_seeded_siphash)
return 0;
crypto_rand((char*) &key, sizeof(key));
siphash_set_global_key(&key);
have_seeded_siphash = 1;
return 0;
}
/** Initialize the crypto library. Return 0 on success, -1 on failure.
*/
int
crypto_early_init(void)
{
if (!crypto_early_initialized_) {
crypto_early_initialized_ = 1;
#ifdef OPENSSL_1_1_API
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
OPENSSL_INIT_ADD_ALL_CIPHERS |
OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
#else
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
#endif
setup_openssl_threading();
unsigned long version_num = OpenSSL_version_num();
const char *version_str = OpenSSL_version(OPENSSL_VERSION);
if (version_num == OPENSSL_VERSION_NUMBER &&
!strcmp(version_str, OPENSSL_VERSION_TEXT)) {
log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
"(%lx: %s).", version_num, version_str);
} else {
log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
"version we're running with. If you get weird crashes, that "
"might be why. (Compiled with %lx: %s; running with %lx: %s).",
(unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
version_num, version_str);
}
crypto_force_rand_ssleay();
if (crypto_seed_rng() < 0)
return -1;
if (crypto_init_siphash_key() < 0)
return -1;
curve25519_init();
ed25519_init();
}
return 0;
}
/** Initialize the crypto library. Return 0 on success, -1 on failure.
*/
int
crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
{
if (!crypto_global_initialized_) {
if (crypto_early_init() < 0)
return -1;
crypto_global_initialized_ = 1;
if (useAccel > 0) {
#ifdef DISABLE_ENGINES
(void)accelName;
(void)accelDir;
log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
#else
ENGINE *e = NULL;
log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
if (accelName) {
if (accelDir) {
log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
" via path \"%s\".", accelName, accelDir);
e = try_load_engine(accelName, accelDir);
} else {
log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
" acceleration support.", accelName);
e = ENGINE_by_id(accelName);
}
if (!e) {
log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
accelName);
} else {
log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
accelName);
}
}
if (e) {
log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
" setting default ciphers.");
ENGINE_set_default(e, ENGINE_METHOD_ALL);
}
/* Log, if available, the intersection of the set of algorithms
used by Tor and the set of algorithms available in the engine */
log_engine("RSA", ENGINE_get_default_RSA());
log_engine("DH", ENGINE_get_default_DH());
#ifdef OPENSSL_1_1_API
log_engine("EC", ENGINE_get_default_EC());
#else
log_engine("ECDH", ENGINE_get_default_ECDH());
log_engine("ECDSA", ENGINE_get_default_ECDSA());
#endif /* defined(OPENSSL_1_1_API) */
log_engine("RAND", ENGINE_get_default_RAND());
log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
#ifdef NID_aes_128_ctr
log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
#endif
#ifdef NID_aes_128_gcm
log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
#endif
log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
#ifdef NID_aes_256_gcm
log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
#endif
#endif /* defined(DISABLE_ENGINES) */
} else {
log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
}
if (crypto_force_rand_ssleay()) {
if (crypto_seed_rng() < 0)
return -1;
}
evaluate_evp_for_aes(-1);
evaluate_ctr_for_aes();
}
return 0;
}
/** Free crypto resources held by this thread. */
void
crypto_thread_cleanup(void)
{
#ifndef NEW_THREAD_API
ERR_remove_thread_state(NULL);
#endif
}
/** Allocate and return a new symmetric cipher using the provided key and iv.
* The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
* must be provided. Key length must be 128, 192, or 256 */
......@@ -335,26 +78,6 @@ crypto_cipher_free_(crypto_cipher_t *env)
aes_cipher_free(env);
}
/** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
* every four characters. */
void
crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
{
int n = 0;
char *end = out+outlen;
tor_assert(outlen < SIZE_T_CEILING);
while (*in && out<end) {
*out++ = *in++;
if (++n == 4 && *in && out<end) {
n = 0;
*out++ = ' ';