Merge branch 'nss_dh_squashed' into nss_dh_squashed_merged

This commit is contained in:
Nick Mathewson 2018-07-31 19:56:23 -04:00
commit fdaa483098
60 changed files with 2208 additions and 1107 deletions

View File

@ -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

3
changes/feature26815 Normal file
View File

@ -0,0 +1,3 @@
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.

11
changes/feature26816 Normal file
View File

@ -0,0 +1,11 @@
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.

View File

@ -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@

View 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?

View File

@ -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@

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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];

View File

@ -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>

View File

@ -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

View File

@ -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"

106
src/lib/crypt_ops/aes_nss.c Normal file
View File

@ -0,0 +1,106 @@
/* 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;
}

View File

@ -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"

View File

@ -1,509 +0,0 @@
/* 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 crypto.c
* \brief Wrapper functions to present a consistent interface to
* public-key and symmetric cryptography operations from OpenSSL and
* other places.
**/
#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_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 */
crypto_cipher_t *
crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
const uint8_t *iv,
int bits)
{
tor_assert(key);
tor_assert(iv);
return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
}
/** Allocate and return a new symmetric cipher using the provided key and iv.
* The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
* must be provided.
*/
crypto_cipher_t *
crypto_cipher_new_with_iv(const char *key, const char *iv)
{
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
128);
}
/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
* zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
* 256. */
crypto_cipher_t *
crypto_cipher_new_with_bits(const char *key, int bits)
{
char zeroiv[CIPHER_IV_LEN];
memset(zeroiv, 0, sizeof(zeroiv));
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
bits);
}
/** Return a new crypto_cipher_t with the provided <b>key</b> (of
* CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
crypto_cipher_t *
crypto_cipher_new(const char *key)
{
return crypto_cipher_new_with_bits(key, 128);
}
/** Free a symmetric cipher.
*/
void
crypto_cipher_free_(crypto_cipher_t *env)
{
if (!env)
return;
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++ = ' ';
}
}
tor_assert(out<end);
*out = '\0';
}
/* symmetric crypto */
/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
* Does not check for failure.
*/
int
crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
const char *from, size_t fromlen)
{
tor_assert(env);
tor_assert(env);
tor_assert(from);
tor_assert(fromlen);
tor_assert(to);
tor_assert(fromlen < SIZE_T_CEILING);
memcpy(to, from, fromlen);
aes_crypt_inplace(env, to, fromlen);
return 0;
}
/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
* Does not check for failure.
*/
int
crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
const char *from, size_t fromlen)
{
tor_assert(env);
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < SIZE_T_CEILING);
memcpy(to, from, fromlen);
aes_crypt_inplace(env, to, fromlen);
return 0;
}
/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
* on success. Does not check for failure.
*/
void
crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
{
tor_assert(len < SIZE_T_CEILING);
aes_crypt_inplace(env, buf, len);
}
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
* <b>key</b> to the buffer in <b>to</b> of length
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
* number of bytes written, on failure, return -1.
*/
int
crypto_cipher_encrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen)
{
crypto_cipher_t *cipher;
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < INT_MAX);
if (fromlen < 1)
return -1;
if (tolen < fromlen + CIPHER_IV_LEN)
return -1;
char iv[CIPHER_IV_LEN];
crypto_rand(iv, sizeof(iv));
cipher = crypto_cipher_new_with_iv(key, iv);
memcpy(to, iv, CIPHER_IV_LEN);
crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
crypto_cipher_free(cipher);
memwipe(iv, 0, sizeof(iv));
return (int)(fromlen + CIPHER_IV_LEN);
}
/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
* with the key in <b>key</b> to the buffer in <b>to</b> of length
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
* number of bytes written, on failure, return -1.
*/
int
crypto_cipher_decrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen)
{
crypto_cipher_t *cipher;
tor_assert(key);
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < INT_MAX);
if (fromlen <= CIPHER_IV_LEN)
return -1;
if (tolen < fromlen - CIPHER_IV_LEN)
return -1;
cipher = crypto_cipher_new_with_iv(key, from);
crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
crypto_cipher_free(cipher);
return (int)(fromlen - CIPHER_IV_LEN);
}
/** @{ */
/** Uninitialize the crypto library. Return 0 on success. Does not detect
* failure.
*/
int
crypto_global_cleanup(void)
{
#ifndef OPENSSL_1_1_API
EVP_cleanup();
#endif
#ifndef NEW_THREAD_API
ERR_remove_thread_state(NULL);
#endif
#ifndef OPENSSL_1_1_API
ERR_free_strings();
#endif
crypto_dh_free_all();
#ifndef DISABLE_ENGINES
#ifndef OPENSSL_1_1_API
ENGINE_cleanup();
#endif
#endif
CONF_modules_unload(1);
#ifndef OPENSSL_1_1_API
CRYPTO_cleanup_all_ex_data();
#endif
crypto_openssl_free_all();
crypto_early_initialized_ = 0;
crypto_global_initialized_ = 0;
have_seeded_siphash = 0;
siphash_unset_global_key();
return 0;
}
/** @} */

View File

@ -0,0 +1,190 @@
/* 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 crypto_cipher.c
* \brief Symmetric cryptography (low-level) with AES.
**/
#include "orconfig.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/cc/torint.h"
#include "lib/crypt_ops/aes.h"
#include <string.h>
/** 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 */
crypto_cipher_t *
crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
const uint8_t *iv,
int bits)
{
tor_assert(key);
tor_assert(iv);
return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
}
/** Allocate and return a new symmetric cipher using the provided key and iv.
* The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
* must be provided.
*/
crypto_cipher_t *
crypto_cipher_new_with_iv(const char *key, const char *iv)
{
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
128);
}
/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
* zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
* 256. */
crypto_cipher_t *
crypto_cipher_new_with_bits(const char *key, int bits)
{
char zeroiv[CIPHER_IV_LEN];
memset(zeroiv, 0, sizeof(zeroiv));
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
bits);
}
/** Return a new crypto_cipher_t with the provided <b>key</b> (of
* CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
crypto_cipher_t *
crypto_cipher_new(const char *key)
{
return crypto_cipher_new_with_bits(key, 128);
}
/** Free a symmetric cipher.
*/
void
crypto_cipher_free_(crypto_cipher_t *env)
{
if (!env)
return;
aes_cipher_free(env);
}
/* symmetric crypto */
/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
* Does not check for failure.
*/
int
crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
const char *from, size_t fromlen)
{
tor_assert(env);
tor_assert(env);
tor_assert(from);
tor_assert(fromlen);
tor_assert(to);
tor_assert(fromlen < SIZE_T_CEILING);
memcpy(to, from, fromlen);
aes_crypt_inplace(env, to, fromlen);
return 0;
}
/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
* Does not check for failure.
*/
int
crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
const char *from, size_t fromlen)
{
tor_assert(env);
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < SIZE_T_CEILING);
memcpy(to, from, fromlen);
aes_crypt_inplace(env, to, fromlen);
return 0;
}
/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
* on success. Does not check for failure.
*/
void
crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
{
tor_assert(len < SIZE_T_CEILING);
aes_crypt_inplace(env, buf, len);
}
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
* <b>key</b> to the buffer in <b>to</b> of length
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
* number of bytes written, on failure, return -1.
*/
int
crypto_cipher_encrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen)
{
crypto_cipher_t *cipher;
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < INT_MAX);
if (fromlen < 1)
return -1;
if (tolen < fromlen + CIPHER_IV_LEN)
return -1;
char iv[CIPHER_IV_LEN];
crypto_rand(iv, sizeof(iv));
cipher = crypto_cipher_new_with_iv(key, iv);
memcpy(to, iv, CIPHER_IV_LEN);
crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
crypto_cipher_free(cipher);
memwipe(iv, 0, sizeof(iv));
return (int)(fromlen + CIPHER_IV_LEN);
}
/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
* with the key in <b>key</b> to the buffer in <b>to</b> of length
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
* number of bytes written, on failure, return -1.
*/
int
crypto_cipher_decrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen)
{
crypto_cipher_t *cipher;
tor_assert(key);
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < INT_MAX);
if (fromlen <= CIPHER_IV_LEN)
return -1;
if (tolen < fromlen - CIPHER_IV_LEN)
return -1;
cipher = crypto_cipher_new_with_iv(key, from);
crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
crypto_cipher_free(cipher);
return (int)(fromlen - CIPHER_IV_LEN);
}

View File

@ -5,19 +5,18 @@
/* See LICENSE for licensing information */
/**
* \file crypto.h
* \file crypto_cipher.h
*
* \brief Headers for crypto.c
* \brief Headers for crypto_cipher.c
**/
#ifndef TOR_CRYPTO_H
#define TOR_CRYPTO_H
#ifndef TOR_CRYPTO_CIPHER_H
#define TOR_CRYPTO_CIPHER_H
#include "orconfig.h"
#include <stdio.h>
#include "lib/cc/torint.h"
#include "lib/crypt_ops/crypto_rsa.h"
/** Length of our symmetric cipher's keys of 128-bit. */
#define CIPHER_KEY_LEN 16
@ -26,22 +25,8 @@
/** Length of our symmetric cipher's keys of 256-bit. */
#define CIPHER256_KEY_LEN 32
/** Length of encoded public key fingerprints, including space; but not
* including terminating NUL. */
#define FINGERPRINT_LEN 49
typedef struct aes_cnt_cipher crypto_cipher_t;
/* global state */
int crypto_init_siphash_key(void);
int crypto_early_init(void) ATTR_WUR;
int crypto_global_init(int hardwareAccel,
const char *accelName,
const char *accelPath) ATTR_WUR;
void crypto_thread_cleanup(void);
int crypto_global_cleanup(void);
/* environment setup */
crypto_cipher_t *crypto_cipher_new(const char *key);
crypto_cipher_t *crypto_cipher_new_with_bits(const char *key, int bits);
@ -69,6 +54,4 @@ int crypto_cipher_decrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen);
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
#endif /* !defined(TOR_CRYPTO_H) */

View File

@ -7,6 +7,8 @@
/**
* \file crypto_dh.c
* \brief Block of functions related with DH utilities and operations.
* over Z_p. We aren't using this for any new crypto -- EC is more
* efficient.
**/
#include "lib/crypt_ops/compat_openssl.h"
@ -17,411 +19,50 @@
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/dh.h>
ENABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <string.h>
/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
* while we're waiting for the second.*/
struct crypto_dh_t {
DH *dh; /**< The openssl DH object */
};
static int tor_check_dh_key(int severity, const BIGNUM *bn);
/** Used by tortls.c: Get the DH* from a crypto_dh_t.
*/
DH *
crypto_dh_get_dh_(crypto_dh_t *dh)
{
return dh->dh;
}
/** Our DH 'g' parameter */
#define DH_GENERATOR 2
/** Shared P parameter for our circuit-crypto DH key exchanges. */
static BIGNUM *dh_param_p = NULL;
/** Shared P parameter for our TLS DH key exchanges. */
static BIGNUM *dh_param_p_tls = NULL;
/** Shared G parameter for our DH key exchanges. */
static BIGNUM *dh_param_g = NULL;
/** Validate a given set of Diffie-Hellman parameters. This is moderately
* computationally expensive (milliseconds), so should only be called when
* the DH parameters change. Returns 0 on success, * -1 on failure.
const unsigned DH_GENERATOR = 2;
/** This is the 1024-bit safe prime that Apache uses for its DH stuff; see
* modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
* prime.
*/
static int
crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
{
DH *dh = NULL;
int ret = -1;
/* Copy into a temporary DH object, just so that DH_check() can be called. */
if (!(dh = DH_new()))
goto out;
#ifdef OPENSSL_1_1_API
BIGNUM *dh_p, *dh_g;
if (!(dh_p = BN_dup(p)))
goto out;
if (!(dh_g = BN_dup(g)))
goto out;
if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
goto out;
#else /* !(defined(OPENSSL_1_1_API)) */
if (!(dh->p = BN_dup(p)))
goto out;
if (!(dh->g = BN_dup(g)))
goto out;
#endif /* defined(OPENSSL_1_1_API) */
/* Perform the validation. */
int codes = 0;
if (!DH_check(dh, &codes))
goto out;
if (BN_is_word(g, DH_GENERATOR_2)) {
/* Per https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
*
* OpenSSL checks the prime is congruent to 11 when g = 2; while the
* IETF's primes are congruent to 23 when g = 2.
*/
BN_ULONG residue = BN_mod_word(p, 24);
if (residue == 11 || residue == 23)
codes &= ~DH_NOT_SUITABLE_GENERATOR;
}
if (codes != 0) /* Specifics on why the params suck is irrelevant. */
goto out;
/* Things are probably not evil. */
ret = 0;
out:
if (dh)
DH_free(dh);
return ret;
}
/** Set the global Diffie-Hellman generator, used for both TLS and internal
* DH stuff.
const char TLS_DH_PRIME[] =
"D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
"BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
"467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
"DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
"B0E7393E0F24218EB3";
/**
* This is from rfc2409, section 6.2. It's a safe prime, and
* supposedly it equals:
* 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
*/
static void
crypto_set_dh_generator(void)
{
BIGNUM *generator;
int r;
const char OAKLEY_PRIME_2[] =
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF";
if (dh_param_g)
return;
generator = BN_new();
tor_assert(generator);
r = BN_set_word(generator, DH_GENERATOR);
tor_assert(r);
dh_param_g = generator;
}
/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
* modulus. */
void
crypto_set_tls_dh_prime(void)
crypto_dh_init(void)
{
BIGNUM *tls_prime = NULL;
int r;
/* If the space is occupied, free the previous TLS DH prime */
if (BUG(dh_param_p_tls)) {
/* LCOV_EXCL_START
*
* We shouldn't be calling this twice.
*/
BN_clear_free(dh_param_p_tls);
dh_param_p_tls = NULL;
/* LCOV_EXCL_STOP */
}
tls_prime = BN_new();
tor_assert(tls_prime);
/* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
* modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
* prime.
*/
r = BN_hex2bn(&tls_prime,
"D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
"BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
"467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
"DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
"B0E7393E0F24218EB3");
tor_assert(r);
tor_assert(tls_prime);
dh_param_p_tls = tls_prime;
crypto_set_dh_generator();
tor_assert(0 == crypto_validate_dh_params(dh_param_p_tls, dh_param_g));
}
/** Initialize dh_param_p and dh_param_g if they are not already
* set. */
static void
init_dh_param(void)
{
BIGNUM *circuit_dh_prime;
int r;
if (BUG(dh_param_p && dh_param_g))
return; // LCOV_EXCL_LINE This function isn't supposed to be called twice.
circuit_dh_prime = BN_new();
tor_assert(circuit_dh_prime);
/* This is from rfc2409, section 6.2. It's a safe prime, and
supposedly it equals:
2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
*/
r = BN_hex2bn(&circuit_dh_prime,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF");
tor_assert(r);
/* Set the new values as the global DH parameters. */
dh_param_p = circuit_dh_prime;
crypto_set_dh_generator();
tor_assert(0 == crypto_validate_dh_params(dh_param_p, dh_param_g));
if (!dh_param_p_tls) {
crypto_set_tls_dh_prime();
}
}
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
* handshake. Since we exponentiate by this value, choosing a smaller one
* lets our handhake go faster.
*/
#define DH_PRIVATE_KEY_BITS 320
/** Allocate and return a new DH object for a key exchange. Returns NULL on
* failure.
*/
crypto_dh_t *
crypto_dh_new(int dh_type)
{
crypto_dh_t *res = tor_malloc_zero(sizeof(crypto_dh_t));
tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
dh_type == DH_TYPE_REND);
if (!dh_param_p)
init_dh_param();
if (!(res->dh = DH_new()))
goto err;
#ifdef OPENSSL_1_1_API
BIGNUM *dh_p = NULL, *dh_g = NULL;
if (dh_type == DH_TYPE_TLS) {
dh_p = BN_dup(dh_param_p_tls);
} else {
dh_p = BN_dup(dh_param_p);
}
if (!dh_p)
goto err;
dh_g = BN_dup(dh_param_g);
if (!dh_g) {
BN_free(dh_p);
goto err;
}
if (!DH_set0_pqg(res->dh, dh_p, NULL, dh_g)) {
goto err;
}
if (!DH_set_length(res->dh, DH_PRIVATE_KEY_BITS))
goto err;
#else /* !(defined(OPENSSL_1_1_API)) */
if (dh_type == DH_TYPE_TLS) {
if (!(res->dh->p = BN_dup(dh_param_p_tls)))
goto err;
} else {
if (!(res->dh->p = BN_dup(dh_param_p)))
goto err;
}
if (!(res->dh->g = BN_dup(dh_param_g)))
goto err;
res->dh->length = DH_PRIVATE_KEY_BITS;
#endif /* defined(OPENSSL_1_1_API) */
return res;
/* LCOV_EXCL_START
* This error condition is only reached when an allocation fails */
err:
crypto_log_errors(LOG_WARN, "creating DH object");
if (res->dh) DH_free(res->dh); /* frees p and g too */
tor_free(res);
return NULL;
/* LCOV_EXCL_STOP */
}
/** Return a copy of <b>dh</b>, sharing its internal state. */
crypto_dh_t *
crypto_dh_dup(const crypto_dh_t *dh)
{
crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t));
tor_assert(dh);
tor_assert(dh->dh);
dh_new->dh = dh->dh;
DH_up_ref(dh->dh);
return dh_new;
}
/** Return the length of the DH key in <b>dh</b>, in bytes.
*/
int
crypto_dh_get_bytes(crypto_dh_t *dh)
{
tor_assert(dh);
return DH_size(dh->dh);
}
/** Generate \<x,g^x\> for our part of the key exchange. Return 0 on
* success, -1 on failure.
*/
int
crypto_dh_generate_public(crypto_dh_t *dh)
{
#ifndef OPENSSL_1_1_API
again:
#ifdef ENABLE_OPENSSL
crypto_dh_init_openssl();
#endif
if (!DH_generate_key(dh->dh)) {
/* LCOV_EXCL_START
* To test this we would need some way to tell openssl to break DH. */
crypto_log_errors(LOG_WARN, "generating DH key");
return -1;
/* LCOV_EXCL_STOP */
}
#ifdef OPENSSL_1_1_API
/* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without
* recreating the DH object. I have no idea what sort of aliasing madness
* can occur here, so do the check, and just bail on failure.
*/
const BIGNUM *pub_key, *priv_key;
DH_get0_key(dh->dh, &pub_key, &priv_key);
if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
"the-universe chances really do happen. Treating as a failure.");
return -1;
}
#else /* !(defined(OPENSSL_1_1_API)) */
if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
/* LCOV_EXCL_START
* If this happens, then openssl's DH implementation is busted. */
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
"the-universe chances really do happen. Trying again.");
/* Free and clear the keys, so OpenSSL will actually try again. */
BN_clear_free(dh->dh->pub_key);
BN_clear_free(dh->dh->priv_key);
dh->dh->pub_key = dh->dh->priv_key = NULL;
goto again;
/* LCOV_EXCL_STOP */
}
#endif /* defined(OPENSSL_1_1_API) */
return 0;
}
/** Generate g^x as necessary, and write the g^x for the key exchange
* as a <b>pubkey_len</b>-byte value into <b>pubkey</b>. Return 0 on
* success, -1 on failure. <b>pubkey_len</b> must be \>= DH1024_KEY_LEN.
*/
int
crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
{
int bytes;
tor_assert(dh);
const BIGNUM *dh_pub;
#ifdef OPENSSL_1_1_API
const BIGNUM *dh_priv;
DH_get0_key(dh->dh, &dh_pub, &dh_priv);
#else
dh_pub = dh->dh->pub_key;
#endif /* defined(OPENSSL_1_1_API) */
if (!dh_pub) {
if (crypto_dh_generate_public(dh)<0)
return -1;
else {
#ifdef OPENSSL_1_1_API
DH_get0_key(dh->dh, &dh_pub, &dh_priv);
#else
dh_pub = dh->dh->pub_key;
#ifdef ENABLE_NSS
crypto_dh_init_nss();
#endif
}
}
tor_assert(dh_pub);
bytes = BN_num_bytes(dh_pub);
tor_assert(bytes >= 0);
if (pubkey_len < (size_t)bytes) {
log_warn(LD_CRYPTO,
"Weird! pubkey_len (%d) was smaller than DH1024_KEY_LEN (%d)",
(int) pubkey_len, bytes);
return -1;
}
memset(pubkey, 0, pubkey_len);
BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
return 0;
}
/** Check for bad Diffie-Hellman public keys (g^x). Return 0 if the key is
* okay (in the subgroup [2,p-2]), or -1 if it's bad.
* See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
*/
static int
tor_check_dh_key(int severity, const BIGNUM *bn)
void
crypto_dh_free_all(void)
{
BIGNUM *x;
char *s;
tor_assert(bn);
x = BN_new();
tor_assert(x);
if (BUG(!dh_param_p))
init_dh_param(); //LCOV_EXCL_LINE we already checked whether we did this.
BN_set_word(x, 1);
if (BN_cmp(bn,x)<=0) {
log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
goto err;
}
BN_copy(x,dh_param_p);
BN_sub_word(x, 1);
if (BN_cmp(bn,x)>=0) {
log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
goto err;
}
BN_clear_free(x);
return 0;
err:
BN_clear_free(x);
s = BN_bn2hex(bn);
log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
OPENSSL_free(s);
return -1;
#ifdef ENABLE_OPENSSL
crypto_dh_free_all_openssl();
#endif
#ifdef ENABLE_NSS
crypto_dh_free_all_nss();
#endif
}
/** Given a DH key exchange object, and our peer's value of g^y (as a
@ -439,31 +80,20 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
char *secret_out, size_t secret_bytes_out)
{
char *secret_tmp = NULL;
BIGNUM *pubkey_bn = NULL;
size_t secret_len=0, secret_tmp_len=0;
int result=0;
tor_assert(dh);
tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
tor_assert(pubkey_len < INT_MAX);
if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
(int)pubkey_len, NULL)))
goto error;
if (tor_check_dh_key(severity, pubkey_bn)<0) {
/* Check for invalid public keys. */
log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
goto error;
}
unsigned char *secret_tmp = NULL;
size_t secret_len=0, secret_tmp_len=0;
secret_tmp_len = crypto_dh_get_bytes(dh);
secret_tmp = tor_malloc(secret_tmp_len);
result = DH_compute_key((unsigned char*)secret_tmp, pubkey_bn, dh->dh);
if (result < 0) {
log_warn(LD_CRYPTO,"DH_compute_key() failed.");
ssize_t result = crypto_dh_handshake(severity, dh, pubkey, pubkey_len,
secret_tmp, secret_tmp_len);
if (result < 0)
goto error;
}
secret_len = result;
if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
if (crypto_expand_key_material_TAP(secret_tmp, secret_len,
(uint8_t*)secret_out, secret_bytes_out)<0)
goto error;
secret_len = secret_bytes_out;
@ -472,9 +102,6 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
error:
result = -1;
done:
crypto_log_errors(LOG_WARN, "completing DH handshake");
if (pubkey_bn)
BN_clear_free(pubkey_bn);
if (secret_tmp) {
memwipe(secret_tmp, 0, secret_tmp_len);
tor_free(secret_tmp);
@ -484,28 +111,3 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
else
return secret_len;
}
/** Free a DH key exchange object.
*/
void
crypto_dh_free_(crypto_dh_t *dh)
{
if (!dh)
return;
tor_assert(dh->dh);
DH_free(dh->dh);
tor_free(dh);
}
void
crypto_dh_free_all(void)
{
if (dh_param_p)
BN_clear_free(dh_param_p);
if (dh_param_p_tls)
BN_clear_free(dh_param_p_tls);
if (dh_param_g)
BN_clear_free(dh_param_g);
dh_param_p = dh_param_p_tls = dh_param_g = NULL;
}

View File

@ -19,11 +19,15 @@
typedef struct crypto_dh_t crypto_dh_t;
extern const unsigned DH_GENERATOR;
extern const char TLS_DH_PRIME[];
extern const char OAKLEY_PRIME_2[];
/* Key negotiation */
#define DH_TYPE_CIRCUIT 1
#define DH_TYPE_REND 2
#define DH_TYPE_TLS 3
void crypto_set_tls_dh_prime(void);
void crypto_dh_init(void);
crypto_dh_t *crypto_dh_new(int dh_type);
crypto_dh_t *crypto_dh_dup(const crypto_dh_t *dh);
int crypto_dh_get_bytes(crypto_dh_t *dh);
@ -36,12 +40,25 @@ ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
void crypto_dh_free_(crypto_dh_t *dh);
#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
/* Crypto DH free */
ssize_t crypto_dh_handshake(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
unsigned char *secret_out,
size_t secret_bytes_out);
void crypto_dh_free_all(void);
/* Prototypes for private functions only used by tortls.c, crypto.c, and the
* unit tests. */
struct dh_st;
struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
struct dh_st *crypto_dh_new_openssl_tls(void);
#ifdef ENABLE_OPENSSL
void crypto_dh_init_openssl(void);
void crypto_dh_free_all_openssl(void);
#endif
#ifdef ENABLE_OPENSSL
void crypto_dh_init_nss(void);
void crypto_dh_free_all_nss(void);
#endif
#endif /* !defined(TOR_CRYPTO_DH_H) */

View File

@ -0,0 +1,207 @@
/* 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 crypto_dh_nss.h
*
* \brief NSS implementation of Diffie-Hellman over Z_p.
**/
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/encoding/binascii.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
#include <cryptohi.h>
#include <keyhi.h>
#include <pk11pub.h>
static int dh_initialized = 0;
static SECKEYDHParams tls_dh_param, circuit_dh_param;
static unsigned char tls_dh_prime_data[DH1024_KEY_LEN];
static unsigned char circuit_dh_prime_data[DH1024_KEY_LEN];
static unsigned char dh_generator_data[1];
void
crypto_dh_init_nss(void)
{
if (dh_initialized)
return;
int r;
r = base16_decode((char*)tls_dh_prime_data,
sizeof(tls_dh_prime_data),
TLS_DH_PRIME, strlen(TLS_DH_PRIME));
tor_assert(r == DH1024_KEY_LEN);
r = base16_decode((char*)circuit_dh_prime_data,
sizeof(circuit_dh_prime_data),
OAKLEY_PRIME_2, strlen(OAKLEY_PRIME_2));
tor_assert(r == DH1024_KEY_LEN);
dh_generator_data[0] = DH_GENERATOR;
tls_dh_param.prime.data = tls_dh_prime_data;
tls_dh_param.prime.len = DH1024_KEY_LEN;
tls_dh_param.base.data = dh_generator_data;
tls_dh_param.base.len = 1;
circuit_dh_param.prime.data = circuit_dh_prime_data;
circuit_dh_param.prime.len = DH1024_KEY_LEN;
circuit_dh_param.base.data = dh_generator_data;
circuit_dh_param.base.len = 1;
}
void
crypto_dh_free_all_nss(void)
{
dh_initialized = 0;
}
struct crypto_dh_t {
int dh_type; // XXXX let's remove this later on.
SECKEYPrivateKey *seckey;
SECKEYPublicKey *pubkey;
};
crypto_dh_t *
crypto_dh_new(int dh_type)
{
crypto_dh_t *r = tor_malloc_zero(sizeof(crypto_dh_t));
r->dh_type = dh_type;
return r;
}
crypto_dh_t *
crypto_dh_dup(const crypto_dh_t *dh)
{
tor_assert(dh);
crypto_dh_t *r = crypto_dh_new(dh->dh_type);
if (dh->seckey)
r->seckey = SECKEY_CopyPrivateKey(dh->seckey);
if (dh->pubkey)
r->pubkey = SECKEY_CopyPublicKey(dh->pubkey);
return r;
}
int
crypto_dh_get_bytes(crypto_dh_t *dh)
{
(void)dh;
return DH1024_KEY_LEN;
}
int
crypto_dh_generate_public(crypto_dh_t *dh)
{
tor_assert(dh);
SECKEYDHParams *p;
if (dh->dh_type == DH_TYPE_TLS)
p = &tls_dh_param;
else
p = &circuit_dh_param;
dh->seckey = SECKEY_CreateDHPrivateKey(p, &dh->pubkey, NULL);
if (!dh->seckey || !dh->pubkey)
return -1;
else
return 0;
}
int
crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
size_t pubkey_out_len)
{
tor_assert(dh);
tor_assert(pubkey_out);
if (!dh->pubkey) {
if (crypto_dh_generate_public(dh) < 0)
return -1;
}
const SECItem *item = &dh->pubkey->u.dh.publicValue;
if (item->len > pubkey_out_len)
return -1;
/* Left-pad the result with 0s. */
memset(pubkey_out, 0, pubkey_out_len);
memcpy(pubkey_out + pubkey_out_len - item->len,
item->data,
item->len);
return 0;
}
void
crypto_dh_free_(crypto_dh_t *dh)
{
if (!dh)
return;
if (dh->seckey)
SECKEY_DestroyPrivateKey(dh->seckey);
if (dh->pubkey)
SECKEY_DestroyPublicKey(dh->pubkey);
tor_free(dh);
}
ssize_t
crypto_dh_handshake(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
unsigned char *secret_out,
size_t secret_bytes_out)
{
tor_assert(dh);
if (pubkey_len > DH1024_KEY_LEN)
return -1;
if (!dh->pubkey || !dh->seckey)
return -1;
if (secret_bytes_out < DH1024_KEY_LEN)
return -1;
SECKEYPublicKey peer_key;
memset(&peer_key, 0, sizeof(peer_key));
peer_key.keyType = dhKey;
peer_key.pkcs11ID = CK_INVALID_HANDLE;
if (dh->dh_type == DH_TYPE_TLS)
peer_key.u.dh.prime.data = tls_dh_prime_data; // should never use this code
else
peer_key.u.dh.prime.data = circuit_dh_prime_data;
peer_key.u.dh.prime.len = DH1024_KEY_LEN;
peer_key.u.dh.base.data = dh_generator_data;
peer_key.u.dh.base.len = 1;
peer_key.u.dh.publicValue.data = (unsigned char *)pubkey;
peer_key.u.dh.publicValue.len = pubkey_len;
PK11SymKey *sym = PK11_PubDerive(dh->seckey, &peer_key,
PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE,
CKM_GENERIC_SECRET_KEY_GEN /* ??? */,
CKA_DERIVE, 0, NULL);
if (! sym) {
crypto_nss_log_errors(severity, "deriving a DH shared secret");
return -1;
}
SECStatus s = PK11_ExtractKeyValue(sym);
if (s != SECSuccess) {
crypto_nss_log_errors(severity, "extracting a DH shared secret");
PK11_FreeSymKey(sym);
return -1;
}
SECItem *result = PK11_GetKeyData(sym);
tor_assert(result); // This cannot fail.
if (BUG(result->len > secret_bytes_out)) {
PK11_FreeSymKey(sym);
return -1;
}
ssize_t len = result->len;
memcpy(secret_out, result->data, len);
PK11_FreeSymKey(sym);
return len;
}

View File

@ -0,0 +1,471 @@
/* 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 crypto_dh_openssl.c
* \brief Implement Tor's Z_p diffie-hellman stuff for OpenSSL.
**/
#include "lib/crypt_ops/compat_openssl.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_hkdf.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/dh.h>
ENABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <string.h>
#ifndef ENABLE_NSS
static int tor_check_dh_key(int severity, const BIGNUM *bn);
/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
* while we're waiting for the second.*/
struct crypto_dh_t {
DH *dh; /**< The openssl DH object */
};
#endif
static DH *new_openssl_dh_from_params(BIGNUM *p, BIGNUM *g);
/** Shared P parameter for our circuit-crypto DH key exchanges. */
static BIGNUM *dh_param_p = NULL;
/** Shared P parameter for our TLS DH key exchanges. */
static BIGNUM *dh_param_p_tls = NULL;
/** Shared G parameter for our DH key exchanges. */
static BIGNUM *dh_param_g = NULL;
/** Validate a given set of Diffie-Hellman parameters. This is moderately
* computationally expensive (milliseconds), so should only be called when
* the DH parameters change. Returns 0 on success, * -1 on failure.
*/
static int
crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
{
DH *dh = NULL;
int ret = -1;
/* Copy into a temporary DH object, just so that DH_check() can be called. */
if (!(dh = DH_new()))
goto out;
#ifdef OPENSSL_1_1_API
BIGNUM *dh_p, *dh_g;
if (!(dh_p = BN_dup(p)))
goto out;
if (!(dh_g = BN_dup(g)))
goto out;
if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
goto out;
#else /* !(defined(OPENSSL_1_1_API)) */
if (!(dh->p = BN_dup(p)))
goto out;
if (!(dh->g = BN_dup(g)))
goto out;
#endif /* defined(OPENSSL_1_1_API) */
/* Perform the validation. */
int codes = 0;
if (!DH_check(dh, &codes))
goto out;
if (BN_is_word(g, DH_GENERATOR_2)) {
/* Per https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
*
* OpenSSL checks the prime is congruent to 11 when g = 2; while the
* IETF's primes are congruent to 23 when g = 2.
*/
BN_ULONG residue = BN_mod_word(p, 24);
if (residue == 11 || residue == 23)
codes &= ~DH_NOT_SUITABLE_GENERATOR;
}
if (codes != 0) /* Specifics on why the params suck is irrelevant. */
goto out;
/* Things are probably not evil. */
ret = 0;
out:
if (dh)
DH_free(dh);
return ret;
}
/**
* Helper: convert <b>hex<b> to a bignum, and return it. Assert that the
* operation was successful.
*/
static BIGNUM *
bignum_from_hex(const char *hex)
{
BIGNUM *result = BN_new();
tor_assert(result);
int r = BN_hex2bn(&result, hex);
tor_assert(r);
tor_assert(result);
return result;
}
/** Set the global Diffie-Hellman generator, used for both TLS and internal
* DH stuff.
*/
static void
crypto_set_dh_generator(void)
{
BIGNUM *generator;
int r;
if (dh_param_g)
return;
generator = BN_new();
tor_assert(generator);
r = BN_set_word(generator, DH_GENERATOR);
tor_assert(r);
dh_param_g = generator;
}
/** Initialize our DH parameters. Idempotent. */
void
crypto_dh_init_openssl(void)
{
if (dh_param_p && dh_param_g && dh_param_p_tls)
return;
tor_assert(dh_param_g == NULL);
tor_assert(dh_param_p == NULL);
tor_assert(dh_param_p_tls == NULL);
crypto_set_dh_generator();
dh_param_p = bignum_from_hex(OAKLEY_PRIME_2);
dh_param_p_tls = bignum_from_hex(TLS_DH_PRIME);
tor_assert(0 == crypto_validate_dh_params(dh_param_p, dh_param_g));
tor_assert(0 == crypto_validate_dh_params(dh_param_p_tls, dh_param_g));
}
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
* handshake. Since we exponentiate by this value, choosing a smaller one
* lets our handhake go faster.
*/
#define DH_PRIVATE_KEY_BITS 320
/** Used by tortls.c: Get the DH* for use with TLS.
*/
DH *
crypto_dh_new_openssl_tls(void)
{
return new_openssl_dh_from_params(dh_param_p_tls, dh_param_g);
}
#ifndef ENABLE_NSS
/** Allocate and return a new DH object for a key exchange. Returns NULL on
* failure.
*/
crypto_dh_t *
crypto_dh_new(int dh_type)
{
crypto_dh_t *res = tor_malloc_zero(sizeof(crypto_dh_t));
tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
dh_type == DH_TYPE_REND);
if (!dh_param_p)
crypto_dh_init();
BIGNUM *dh_p = NULL;
if (dh_type == DH_TYPE_TLS) {
dh_p = dh_param_p_tls;
} else {
dh_p = dh_param_p;
}
res->dh = new_openssl_dh_from_params(dh_p, dh_param_g);
if (res->dh == NULL)
tor_free(res); // sets res to NULL.
return res;
}
#endif
/** Create and return a new openssl DH from a given prime and generator. */
static DH *
new_openssl_dh_from_params(BIGNUM *p, BIGNUM *g)
{
DH *res_dh;
if (!(res_dh = DH_new()))
goto err;
BIGNUM *dh_p = NULL, *dh_g = NULL;
dh_p = BN_dup(p);
if (!dh_p)
goto err;
dh_g = BN_dup(g);
if (!dh_g) {
BN_free(dh_p);
goto err;
}
#ifdef OPENSSL_1_1_API
if (!DH_set0_pqg(res_dh, dh_p, NULL, dh_g)) {
goto err;
}
if (!DH_set_length(res_dh, DH_PRIVATE_KEY_BITS))
goto err;
#else /* !(defined(OPENSSL_1_1_API)) */
res_dh->p = dh_p;
res_dh->g = dh_g;
res_dh->length = DH_PRIVATE_KEY_BITS;
#endif /* defined(OPENSSL_1_1_API) */
return res_dh;
/* LCOV_EXCL_START
* This error condition is only reached when an allocation fails */
err:
crypto_openssl_log_errors(LOG_WARN, "creating DH object");
if (res_dh) DH_free(res_dh); /* frees p and g too */
return NULL;
/* LCOV_EXCL_STOP */
}
#ifndef ENABLE_NSS
/** Return a copy of <b>dh</b>, sharing its internal state. */
crypto_dh_t *
crypto_dh_dup(const crypto_dh_t *dh)
{
crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t));
tor_assert(dh);
tor_assert(dh->dh);
dh_new->dh = dh->dh;
DH_up_ref(dh->dh);
return dh_new;
}
/** Return the length of the DH key in <b>dh</b>, in bytes.
*/
int
crypto_dh_get_bytes(crypto_dh_t *dh)
{
tor_assert(dh);
return DH_size(dh->dh);
}
/** Generate \<x,g^x\> for our part of the key exchange. Return 0 on
* success, -1 on failure.
*/
int
crypto_dh_generate_public(crypto_dh_t *dh)
{
#ifndef OPENSSL_1_1_API
again:
#endif
if (!DH_generate_key(dh->dh)) {
/* LCOV_EXCL_START
* To test this we would need some way to tell openssl to break DH. */
crypto_openssl_log_errors(LOG_WARN, "generating DH key");
return -1;
/* LCOV_EXCL_STOP */
}
#ifdef OPENSSL_1_1_API
/* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without
* recreating the DH object. I have no idea what sort of aliasing madness
* can occur here, so do the check, and just bail on failure.
*/
const BIGNUM *pub_key, *priv_key;
DH_get0_key(dh->dh, &pub_key, &priv_key);
if (tor_check_dh_key(LOG_WARN, pub_key)<0) {
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
"the-universe chances really do happen. Treating as a failure.");
return -1;
}
#else /* !(defined(OPENSSL_1_1_API)) */
if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
/* LCOV_EXCL_START
* If this happens, then openssl's DH implementation is busted. */
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
"the-universe chances really do happen. Trying again.");
/* Free and clear the keys, so OpenSSL will actually try again. */
BN_clear_free(dh->dh->pub_key);
BN_clear_free(dh->dh->priv_key);
dh->dh->pub_key = dh->dh->priv_key = NULL;
goto again;
/* LCOV_EXCL_STOP */
}
#endif /* defined(OPENSSL_1_1_API) */
return 0;
}
/** Generate g^x as necessary, and write the g^x for the key exchange
* as a <b>pubkey_len</b>-byte value into <b>pubkey</b>. Return 0 on
* success, -1 on failure. <b>pubkey_len</b> must be \>= DH1024_KEY_LEN.
*/
int
crypto_dh_get_public(crypto_dh_t *dh, char *pubkey, size_t pubkey_len)
{
int bytes;
tor_assert(dh);
const BIGNUM *dh_pub;
#ifdef OPENSSL_1_1_API
const BIGNUM *dh_priv;
DH_get0_key(dh->dh, &dh_pub, &dh_priv);
#else
dh_pub = dh->dh->pub_key;
#endif /* defined(OPENSSL_1_1_API) */
if (!dh_pub) {
if (crypto_dh_generate_public(dh)<0)
return -1;
else {
#ifdef OPENSSL_1_1_API
DH_get0_key(dh->dh, &dh_pub, &dh_priv);
#else
dh_pub = dh->dh->pub_key;
#endif
}
}
tor_assert(dh_pub);
bytes = BN_num_bytes(dh_pub);
tor_assert(bytes >= 0);
if (pubkey_len < (size_t)bytes) {
log_warn(LD_CRYPTO,
"Weird! pubkey_len (%d) was smaller than DH1024_KEY_LEN (%d)",
(int) pubkey_len, bytes);
return -1;
}
memset(pubkey, 0, pubkey_len);
BN_bn2bin(dh_pub, (unsigned char*)(pubkey+(pubkey_len-bytes)));
return 0;
}
/** Check for bad Diffie-Hellman public keys (g^x). Return 0 if the key is
* okay (in the subgroup [2,p-2]), or -1 if it's bad.
* See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
*/
static int
tor_check_dh_key(int severity, const BIGNUM *bn)
{
BIGNUM *x;
char *s;
tor_assert(bn);
x = BN_new();
tor_assert(x);
if (BUG(!dh_param_p))
crypto_dh_init(); //LCOV_EXCL_LINE we already checked whether we did this.
BN_set_word(x, 1);
if (BN_cmp(bn,x)<=0) {
log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
goto err;
}
BN_copy(x,dh_param_p);
BN_sub_word(x, 1);
if (BN_cmp(bn,x)>=0) {
log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
goto err;
}
BN_clear_free(x);
return 0;
err:
BN_clear_free(x);
s = BN_bn2hex(bn);
log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
OPENSSL_free(s);
return -1;
}
/** Given a DH key exchange object, and our peer's value of g^y (as a
* <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
* g^xy as a big-endian integer in <b>secret_out</b>.
* Return the number of bytes generated on success,
* or -1 on failure.
*
* This function MUST validate that g^y is actually in the group.
*/
ssize_t
crypto_dh_handshake(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
unsigned char *secret_out, size_t secret_bytes_out)
{
BIGNUM *pubkey_bn = NULL;
size_t secret_len=0;
int result=0;
tor_assert(dh);
tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
tor_assert(pubkey_len < INT_MAX);
if (BUG(crypto_dh_get_bytes(dh) > (int)secret_bytes_out)) {
goto error;
}
if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
(int)pubkey_len, NULL)))
goto error;
if (tor_check_dh_key(severity, pubkey_bn)<0) {
/* Check for invalid public keys. */
log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
goto error;
}
result = DH_compute_key(secret_out, pubkey_bn, dh->dh);
if (result < 0) {
log_warn(LD_CRYPTO,"DH_compute_key() failed.");
goto error;
}
secret_len = result;
goto done;
error:
result = -1;
done:
crypto_openssl_log_errors(LOG_WARN, "completing DH handshake");
if (pubkey_bn)
BN_clear_free(pubkey_bn);
if (result < 0)
return result;
else
return secret_len;
}
/** Free a DH key exchange object.
*/
void
crypto_dh_free_(crypto_dh_t *dh)
{
if (!dh)
return;
tor_assert(dh->dh);
DH_free(dh->dh);
tor_free(dh);
}
#endif
void
crypto_dh_free_all_openssl(void)
{
if (dh_param_p)
BN_clear_free(dh_param_p);
if (dh_param_p_tls)
BN_clear_free(dh_param_p_tls);
if (dh_param_g)
BN_clear_free(dh_param_g);
dh_param_p = dh_param_p_tls = dh_param_g = NULL;
}

View File

@ -12,7 +12,6 @@
#include "lib/container/smartlist.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_openssl_mgt.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
@ -24,12 +23,92 @@
#include "lib/arch/bytes.h"
#ifdef ENABLE_NSS
DISABLE_GCC_WARNING(strict-prototypes)
#include <pk11pub.h>
ENABLE_GCC_WARNING(strict-prototypes)
#else
#include "lib/crypt_ops/crypto_openssl_mgt.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/hmac.h>
#include <openssl/sha.h>
ENABLE_GCC_WARNING(redundant-decls)
#endif
#ifdef ENABLE_NSS
/**
* Convert a digest_algorithm_t (used by tor) to a HashType (used by NSS).
* On failure, return SEC_OID_UNKNOWN. */
static SECOidTag
digest_alg_to_nss_oid(digest_algorithm_t alg)
{
switch (alg) {
case DIGEST_SHA1: return SEC_OID_SHA1;
case DIGEST_SHA256: return SEC_OID_SHA256;
case DIGEST_SHA512: return SEC_OID_SHA512;
case DIGEST_SHA3_256: /* Fall through */
case DIGEST_SHA3_512: /* Fall through */
default:
return SEC_OID_UNKNOWN;
}
}
/* Helper: get an unkeyed digest via pk11wrap */
static int
digest_nss_internal(SECOidTag alg,
char *digest, unsigned len_out,
const char *msg, size_t msg_len)
{
if (alg == SEC_OID_UNKNOWN)
return -1;
tor_assert(msg_len <= UINT_MAX);
int rv = -1;
SECStatus s;
PK11Context *ctx = PK11_CreateDigestContext(alg);
if (!ctx)
return -1;
s = PK11_DigestBegin(ctx);
if (s != SECSuccess)
goto done;
s = PK11_DigestOp(ctx, (const unsigned char *)msg, (unsigned int)msg_len);
if (s != SECSuccess)
goto done;
unsigned int len = 0;
s = PK11_DigestFinal(ctx, (unsigned char *)digest, &len, len_out);
if (s != SECSuccess)
goto done;
rv = 0;
done:
PK11_DestroyContext(ctx, PR_TRUE);
return rv;
}
/** True iff alg is implemented in our crypto library, and we want to use that
* implementation */
static bool
library_supports_digest(digest_algorithm_t alg)
{
switch (alg) {
case DIGEST_SHA1: /* Fall through */
case DIGEST_SHA256: /* Fall through */
case DIGEST_SHA512: /* Fall through */
return true;
case DIGEST_SHA3_256: /* Fall through */
case DIGEST_SHA3_512: /* Fall through */
default:
return false;
}
}
#endif
/* Crypto digest functions */
@ -42,8 +121,13 @@ crypto_digest(char *digest, const char *m, size_t len)
{
tor_assert(m);
tor_assert(digest);
if (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL)
#ifdef ENABLE_NSS
return digest_nss_internal(SEC_OID_SHA1, digest, DIGEST_LEN, m, len);
#else
if (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL) {
return -1;
}
#endif
return 0;
}
@ -59,11 +143,16 @@ crypto_digest256(char *digest, const char *m, size_t len,
tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
int ret = 0;
if (algorithm == DIGEST_SHA256)
if (algorithm == DIGEST_SHA256) {
#ifdef ENABLE_NSS
return digest_nss_internal(SEC_OID_SHA256, digest, DIGEST256_LEN, m, len);
#else
ret = (SHA256((const uint8_t*)m,len,(uint8_t*)digest) != NULL);
else
#endif
} else {
ret = (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
> -1);
}
if (!ret)
return -1;
@ -82,12 +171,17 @@ crypto_digest512(char *digest, const char *m, size_t len,
tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
int ret = 0;
if (algorithm == DIGEST_SHA512)
if (algorithm == DIGEST_SHA512) {
#ifdef ENABLE_NSS
return digest_nss_internal(SEC_OID_SHA512, digest, DIGEST512_LEN, m, len);
#else
ret = (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
!= NULL);
else
#endif
} else {
ret = (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
> -1);
}
if (!ret)
return -1;
@ -181,9 +275,13 @@ struct crypto_digest_t {
* that space for other members might not even be allocated!
*/
union {
#ifdef ENABLE_NSS
PK11Context *ctx;
#else
SHA_CTX sha1; /**< state for SHA1 */
SHA256_CTX sha2; /**< state for SHA256 */
SHA512_CTX sha512; /**< state for SHA512 */
#endif
keccak_state sha3; /**< state for SHA3-[256,512] */
} d;
};
@ -214,12 +312,19 @@ crypto_digest_alloc_bytes(digest_algorithm_t alg)
#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
#ifdef ENABLE_NSS
case DIGEST_SHA1: /* Fall through */
case DIGEST_SHA256: /* Fall through */
case DIGEST_SHA512:
return END_OF_FIELD(d.ctx);
#else
case DIGEST_SHA1:
return END_OF_FIELD(d.sha1);
case DIGEST_SHA256:
return END_OF_FIELD(d.sha2);
case DIGEST_SHA512:
return END_OF_FIELD(d.sha512);
#endif
case DIGEST_SHA3_256:
case DIGEST_SHA3_512:
return END_OF_FIELD(d.sha3);
@ -243,6 +348,21 @@ crypto_digest_new_internal(digest_algorithm_t algorithm)
switch (algorithm)
{
#ifdef ENABLE_NSS
case DIGEST_SHA1: /* fall through */
case DIGEST_SHA256: /* fall through */
case DIGEST_SHA512:
r->d.ctx = PK11_CreateDigestContext(digest_alg_to_nss_oid(algorithm));
if (BUG(!r->d.ctx)) {
tor_free(r);
return NULL;
}
if (BUG(SECSuccess != PK11_DigestBegin(r->d.ctx))) {
crypto_digest_free(r);
return NULL;
}
break;
#else
case DIGEST_SHA1:
SHA1_Init(&r->d.sha1);
break;
@ -252,6 +372,7 @@ crypto_digest_new_internal(digest_algorithm_t algorithm)
case DIGEST_SHA512:
SHA512_Init(&r->d.sha512);
break;
#endif
case DIGEST_SHA3_256:
keccak_digest_init(&r->d.sha3, 256);
break;
@ -302,6 +423,11 @@ crypto_digest_free_(crypto_digest_t *digest)
{
if (!digest)
return;
#ifdef ENABLE_NSS
if (library_supports_digest(digest->algorithm)) {
PK11_DestroyContext(digest->d.ctx, PR_TRUE);
}
#endif
size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
memwipe(digest, 0, bytes);
tor_free(digest);
@ -324,6 +450,17 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
* just doing it ourselves. Hashes are fast.
*/
switch (digest->algorithm) {
#ifdef ENABLE_NSS
case DIGEST_SHA1: /* fall through */
case DIGEST_SHA256: /* fall through */
case DIGEST_SHA512:
tor_assert(len <= UINT_MAX);
SECStatus s = PK11_DigestOp(digest->d.ctx,
(const unsigned char *)data,
(unsigned int)len);
tor_assert(s == SECSuccess);
break;
#else
case DIGEST_SHA1:
SHA1_Update(&digest->d.sha1, (void*)data, len);
break;
@ -333,6 +470,7 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
case DIGEST_SHA512:
SHA512_Update(&digest->d.sha512, (void*)data, len);
break;
#endif
case DIGEST_SHA3_256: /* FALLSTHROUGH */
case DIGEST_SHA3_512:
keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
@ -357,7 +495,6 @@ crypto_digest_get_digest(crypto_digest_t *digest,
char *out, size_t out_len)
{
unsigned char r[DIGEST512_LEN];
crypto_digest_t tmpenv;
tor_assert(digest);
tor_assert(out);
tor_assert(out_len <= crypto_digest_algorithm_get_length(digest->algorithm));
@ -370,7 +507,26 @@ crypto_digest_get_digest(crypto_digest_t *digest,
return;
}
#ifdef ENABLE_NSS
/* Copy into a temporary buffer since DigestFinal (alters) the context */
unsigned char buf[1024];
unsigned int saved_len = 0;
unsigned rlen;
unsigned char *saved = PK11_SaveContextAlloc(digest->d.ctx,
buf, sizeof(buf),
&saved_len);
tor_assert(saved);
SECStatus s = PK11_DigestFinal(digest->d.ctx, r, &rlen, sizeof(r));
tor_assert(s == SECSuccess);
tor_assert(rlen >= out_len);
s = PK11_RestoreContext(digest->d.ctx, saved, saved_len);
tor_assert(s == SECSuccess);
if (saved != buf) {
PORT_ZFree(saved, saved_len);
}
#else
const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
crypto_digest_t tmpenv;
/* memcpy into a temporary ctx, since SHA*_Final clears the context */
memcpy(&tmpenv, digest, alloc_bytes);
switch (digest->algorithm) {
@ -393,6 +549,7 @@ crypto_digest_get_digest(crypto_digest_t *digest,
break;
//LCOV_EXCL_STOP
}
#endif
memcpy(out, r, out_len);
memwipe(r, 0, sizeof(r));
}
@ -408,7 +565,13 @@ crypto_digest_dup(const crypto_digest_t *digest)
{
tor_assert(digest);
const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
return tor_memdup(digest, alloc_bytes);
crypto_digest_t *result = tor_memdup(digest, alloc_bytes);
#ifdef ENABLE_NSS
if (library_supports_digest(digest->algorithm)) {
result->d.ctx = PK11_CloneContext(digest->d.ctx);
}
#endif
return result;
}
/** Temporarily save the state of <b>digest</b> in <b>checkpoint</b>.
@ -420,6 +583,18 @@ crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
{
const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
tor_assert(bytes <= sizeof(checkpoint->mem));
#ifdef ENABLE_NSS
if (library_supports_digest(digest->algorithm)) {
unsigned char *allocated;
allocated = PK11_SaveContextAlloc(digest->d.ctx,
(unsigned char *)checkpoint->mem,
sizeof(checkpoint->mem),
&checkpoint->bytes_used);
/* No allocation is allowed here. */
tor_assert(allocated == checkpoint->mem);
return;
}
#endif
memcpy(checkpoint->mem, digest, bytes);
}
@ -431,6 +606,15 @@ crypto_digest_restore(crypto_digest_t *digest,
const crypto_digest_checkpoint_t *checkpoint)
{
const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
#ifdef ENABLE_NSS
if (library_supports_digest(digest->algorithm)) {
SECStatus s = PK11_RestoreContext(digest->d.ctx,
(unsigned char *)checkpoint->mem,
checkpoint->bytes_used);
tor_assert(s == SECSuccess);
return;
}
#endif
memcpy(digest, checkpoint->mem, bytes);
}
@ -446,6 +630,13 @@ crypto_digest_assign(crypto_digest_t *into,
tor_assert(from);
tor_assert(into->algorithm == from->algorithm);
const size_t alloc_bytes = crypto_digest_alloc_bytes(from->algorithm);
#ifdef ENABLE_NSS
if (library_supports_digest(from->algorithm)) {
PK11_DestroyContext(into->d.ctx, PR_TRUE);
into->d.ctx = PK11_CloneContext(from->d.ctx);
return;
}
#endif
memcpy(into,from,alloc_bytes);
}
@ -496,14 +687,63 @@ crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len)
{
unsigned char *rv = NULL;
/* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */
tor_assert(key_len < INT_MAX);
tor_assert(msg_len < INT_MAX);
tor_assert(hmac_out);
#ifdef ENABLE_NSS
PK11SlotInfo *slot = NULL;
PK11SymKey *symKey = NULL;
PK11Context *hmac = NULL;
int ok = 0;
SECStatus s;
SECItem keyItem, paramItem;
keyItem.data = (unsigned char *)key;
keyItem.len = (unsigned)key_len;
paramItem.type = siBuffer;
paramItem.data = NULL;
paramItem.len = 0;
slot = PK11_GetBestSlot(CKM_SHA256_HMAC, NULL);
if (!slot)
goto done;
symKey = PK11_ImportSymKey(slot, CKM_SHA256_HMAC,
PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL);
if (!symKey)
goto done;
hmac = PK11_CreateContextBySymKey(CKM_SHA256_HMAC, CKA_SIGN, symKey,
&paramItem);
if (!hmac)
goto done;
s = PK11_DigestBegin(hmac);
if (s != SECSuccess)
goto done;
s = PK11_DigestOp(hmac, (const unsigned char *)msg, (unsigned int)msg_len);
if (s != SECSuccess)
goto done;
unsigned int len=0;
s = PK11_DigestFinal(hmac, (unsigned char *)hmac_out, &len, DIGEST256_LEN);
if (s != SECSuccess || len != DIGEST256_LEN)
goto done;
ok = 1;
done:
if (hmac)
PK11_DestroyContext(hmac, PR_TRUE);
if (symKey)
PK11_FreeSymKey(symKey);
if (slot)
PK11_FreeSlot(slot);
tor_assert(ok);
#else
unsigned char *rv = NULL;
rv = HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
(unsigned char*)hmac_out, NULL);
tor_assert(rv);
#endif
}
/** Compute a MAC using SHA3-256 of <b>msg_len</b> bytes in <b>msg</b> using a

View File

@ -51,6 +51,9 @@ typedef enum {
/** Structure used to temporarily save the a digest object. Only implemented
* for SHA1 digest for now. */
typedef struct crypto_digest_checkpoint_t {
#ifdef ENABLE_NSS
unsigned int bytes_used;
#endif
uint8_t mem[DIGEST_CHECKPOINT_BYTES];
} crypto_digest_checkpoint_t;

View File

@ -0,0 +1,141 @@
/* 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 crypto_init.c
*
* \brief Initialize and shut down Tor's crypto library and subsystem.
**/
#include "orconfig.h"
#include "lib/crypt_ops/crypto_init.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_openssl_mgt.h"
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "siphash.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;
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 ENABLE_OPENSSL
crypto_openssl_early_init();
#endif
#ifdef ENABLE_NSS
crypto_nss_early_init();
#endif
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;
crypto_dh_init();
#ifdef ENABLE_OPENSSL
if (crypto_openssl_late_init(useAccel, accelName, accelDir) < 0)
return -1;
#endif
#ifdef ENABLE_NSS
if (crypto_nss_late_init() < 0)
return -1;
#endif
}
return 0;
}
/** Free crypto resources held by this thread. */
void
crypto_thread_cleanup(void)
{
#ifdef ENABLE_OPENSSL
crypto_openssl_thread_cleanup();
#endif
}
/**
* Uninitialize the crypto library. Return 0 on success. Does not detect
* failure.
*/
int
crypto_global_cleanup(void)
{
crypto_dh_free_all();
#ifdef ENABLE_OPENSSL
crypto_openssl_global_cleanup();
#endif
#ifdef ENABLE_NSS
crypto_nss_global_cleanup();
#endif
crypto_early_initialized_ = 0;
crypto_global_initialized_ = 0;
have_seeded_siphash = 0;
siphash_unset_global_key();
return 0;
}
/** Run operations that the crypto library requires to be happy again
* after forking. */
void
crypto_postfork(void)
{
#ifdef ENABLE_NSS
crypto_nss_postfork();
#endif
}

View File

@ -0,0 +1,29 @@
/* 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 crypto_init.h
*
* \brief Headers for crypto_init.c
**/
#ifndef TOR_CRYPTO_INIT_H
#define TOR_CRYPTO_INIT_H
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
int crypto_init_siphash_key(void);
int crypto_early_init(void) ATTR_WUR;
int crypto_global_init(int hardwareAccel,
const char *accelName,
const char *accelPath) ATTR_WUR;
void crypto_thread_cleanup(void);
int crypto_global_cleanup(void);
void crypto_postfork(void);
#endif /* !defined(TOR_CRYPTO_H) */

View File

@ -0,0 +1,102 @@
/* 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 crypto_nss_mgt.c
*
* \brief Manage the NSS library (if used)
**/
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <nss.h>
#include <pk11func.h>
#include <ssl.h>
#include <prerror.h>
#include <prtypes.h>
#include <prinit.h>
const char *
crypto_nss_get_version_str(void)
{
return NSS_GetVersion();
}
const char *
crypto_nss_get_header_version_str(void)
{
return NSS_VERSION;
}
/** A password function that always returns NULL. */
static char *
nss_password_func_always_fail(PK11SlotInfo *slot,
PRBool retry,
void *arg)
{
(void) slot;
(void) retry;
(void) arg;
return NULL;
}
void
crypto_nss_early_init(void)
{
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
PK11_SetPasswordFunc(nss_password_func_always_fail);
/* Eventually we should use NSS_Init() instead -- but that wants a
directory. The documentation says that we can't use this if we want
to use OpenSSL. */
if (NSS_NoDB_Init(NULL) == SECFailure) {
log_err(LD_CRYPTO, "Unable to initialize NSS.");
crypto_nss_log_errors(LOG_ERR, "initializing NSS");
tor_assert_unreached();
}
if (NSS_SetDomesticPolicy() == SECFailure) {
log_err(LD_CRYPTO, "Unable to set NSS cipher policy.");
crypto_nss_log_errors(LOG_ERR, "setting cipher policy");
tor_assert_unreached();
}
}
void
crypto_nss_log_errors(int severity, const char *doing)
{
PRErrorCode code = PR_GetError();
/* XXXX how do I convert errors to strings? */
if (doing) {
tor_log(severity, LD_CRYPTO, "NSS error %u while %s", code, doing);
} else {
tor_log(severity, LD_CRYPTO, "NSS error %u", code);
}
}
int
crypto_nss_late_init(void)
{
/* Possibly, SSL_OptionSetDefault? */
return 0;
}
void
crypto_nss_global_cleanup(void)
{
NSS_Shutdown();
}
void
crypto_nss_postfork(void)
{
crypto_nss_global_cleanup();
crypto_nss_early_init();
}

View File

@ -0,0 +1,33 @@
/* 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 crypto_nss_mgt.h
*
* \brief Headers for crypto_nss_mgt.c
**/
#ifndef TOR_CRYPTO_NSS_MGT_H
#define TOR_CRYPTO_NSS_MGT_H
#include "orconfig.h"
#ifdef ENABLE_NSS
/* global nss state */
const char *crypto_nss_get_version_str(void);
const char *crypto_nss_get_header_version_str(void);
void crypto_nss_log_errors(int severity, const char *doing);
void crypto_nss_early_init(void);
int crypto_nss_late_init(void);
void crypto_nss_global_cleanup(void);
void crypto_nss_postfork(void);
#endif
#endif /* !defined(TOR_CRYPTO_NSS_H) */

View File

@ -12,8 +12,12 @@
#include "lib/crypt_ops/compat_openssl.h"
#include "lib/crypt_ops/crypto_openssl_mgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/aes.h"
#include "lib/string/util_string.h"
#include "lib/lock/compat_mutex.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/testsupport/testsupport.h"
#include "lib/thread/threads.h"
@ -30,6 +34,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/conf.h>
#include <openssl/hmac.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
ENABLE_GCC_WARNING(redundant-decls)
@ -49,6 +54,27 @@ 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
/** Log all pending crypto errors at level <b>severity</b>. Use
* <b>doing</b> to describe our current activities.
*/
void
crypto_openssl_log_errors(int severity, const char *doing)
{
unsigned long err;
const char *msg, *lib, *func;
while ((err = ERR_get_error()) != 0) {
msg = (const char*)ERR_reason_error_string(err);
lib = (const char*)ERR_lib_error_string(err);
func = (const char*)ERR_func_error_string(err);
if (!msg) msg = "(null)";
if (!lib) lib = "(null)";
if (!func) func = "(null)";
if (BUG(!doing)) doing = "(null)";
tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
doing, msg, lib, func);
}
}
/* 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' */
@ -127,7 +153,7 @@ tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
* multithreaded. Returns 0. */
int
static int
setup_openssl_threading(void)
{
#ifndef NEW_THREAD_API
@ -144,7 +170,7 @@ setup_openssl_threading(void)
}
/** free OpenSSL variables */
void
static void
crypto_openssl_free_all(void)
{
tor_free(crypto_openssl_version_str);
@ -164,3 +190,201 @@ crypto_openssl_free_all(void)
}
#endif /* !defined(NEW_THREAD_API) */
}
/** Perform early (pre-configuration) initialization tasks for OpenSSL. */
void
crypto_openssl_early_init(void)
{
#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();
}
#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) */
#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) */
/** Initialize engines for openssl (if enabled). */
static void
crypto_openssl_init_engines(const char *accelName,
const char *accelDir)
{
#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) */
}
/** Perform late (post-init) initialization tasks for OpenSSL */
int
crypto_openssl_late_init(int useAccel, const char *accelName,
const char *accelDir)
{
if (useAccel > 0) {
crypto_openssl_init_engines(accelName, accelDir);
} 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_openssl_thread_cleanup(void)
{
#ifndef NEW_THREAD_API
ERR_remove_thread_state(NULL);
#endif
}
/** Clean up global resources held by openssl. */
void
crypto_openssl_global_cleanup(void)
{
#ifndef OPENSSL_1_1_API
EVP_cleanup();
#endif
#ifndef NEW_THREAD_API
ERR_remove_thread_state(NULL);
#endif
#ifndef OPENSSL_1_1_API
ERR_free_strings();
#endif
#ifndef DISABLE_ENGINES
#ifndef OPENSSL_1_1_API
ENGINE_cleanup();
#endif
#endif
CONF_modules_unload(1);
#ifndef OPENSSL_1_1_API
CRYPTO_cleanup_all_ex_data();
#endif
crypto_openssl_free_all();
}

View File

@ -14,6 +14,8 @@
#define TOR_CRYPTO_OPENSSL_H
#include "orconfig.h"
#ifdef ENABLE_OPENSSL
#include <openssl/engine.h>
/*
@ -69,14 +71,19 @@
#define NEW_THREAD_API
#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */
void crypto_openssl_log_errors(int severity, const char *doing);
/* 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);
void crypto_openssl_early_init(void);
int crypto_openssl_late_init(int useAccel, const char *accelName,
const char *accelDir);
/* Tor OpenSSL utility functions */
void crypto_openssl_free_all(void);
void crypto_openssl_thread_cleanup(void);
void crypto_openssl_global_cleanup(void);
#endif /* ENABLE_OPENSSL */
#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */

View File

@ -11,7 +11,7 @@
#include <string.h>
#include "lib/arch/bytes.h"
#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_pwbox.h"
#include "lib/crypt_ops/crypto_rand.h"

View File

@ -35,9 +35,22 @@
#include "lib/testsupport/testsupport.h"
#include "lib/fs/files.h"
#ifdef ENABLE_NSS
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/crypt_ops/crypto_digest.h"
#endif
#ifdef ENABLE_OPENSSL
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/rand.h>
ENABLE_GCC_WARNING(redundant-decls)
#endif
#ifdef ENABLE_NSS
#include <pk11pub.h>
#include <secerr.h>
#include <prerror.h>
#endif
#if __GNUC__ && GCC_VERSION >= 402
#if GCC_VERSION >= 406
@ -324,14 +337,21 @@ crypto_strongest_rand(uint8_t *out, size_t out_len)
{
#define DLEN SHA512_DIGEST_LENGTH
/* We're going to hash DLEN bytes from the system RNG together with some
* bytes from the openssl PRNG, in order to yield DLEN bytes.
* bytes from the PRNGs from our crypto librar(y/ies), in order to yield
* DLEN bytes.
*/
uint8_t inp[DLEN*2];
uint8_t inp[DLEN*3];
uint8_t tmp[DLEN];
tor_assert(out);
while (out_len) {
crypto_rand((char*) inp, DLEN);
if (crypto_strongest_rand_raw(inp+DLEN, DLEN) < 0) {
memset(inp, 0, sizeof(inp));
#ifdef ENABLE_OPENSSL
RAND_bytes(inp, DLEN);
#endif
#ifdef ENABLE_NSS
PK11_GenerateRandom(inp+DLEN, DLEN);
#endif
if (crypto_strongest_rand_raw(inp+DLEN*2, DLEN) < 0) {
// LCOV_EXCL_START
log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
"important key. Exiting.");
@ -354,12 +374,13 @@ crypto_strongest_rand(uint8_t *out, size_t out_len)
#undef DLEN
}
#ifdef ENABLE_OPENSSL
/**
* Seed OpenSSL's random number generator with bytes from the operating
* system. Return 0 on success, -1 on failure.
**/
int
crypto_seed_rng(void)
static int
crypto_seed_openssl_rng(void)
{
int rand_poll_ok = 0, load_entropy_ok = 0;
uint8_t buf[ADD_ENTROPY];
@ -383,6 +404,52 @@ crypto_seed_rng(void)
else
return -1;
}
#endif
#ifdef ENABLE_NSS
/**
* Seed OpenSSL's random number generator with bytes from the operating
* system. Return 0 on success, -1 on failure.
**/
static int
crypto_seed_nss_rng(void)
{
uint8_t buf[ADD_ENTROPY];
int load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
if (load_entropy_ok) {
if (PK11_RandomUpdate(buf, sizeof(buf)) != SECSuccess) {
load_entropy_ok = 0;
}
}
memwipe(buf, 0, sizeof(buf));
return load_entropy_ok ? 0 : -1;
}
#endif
/**
* Seed the RNG for any and all crypto libraries that we're using with bytes
* from the operating system. Return 0 on success, -1 on failure.
*/
int
crypto_seed_rng(void)
{
int seeded = 0;
#ifdef ENABLE_NSS
if (crypto_seed_nss_rng() < 0)
return -1;
++seeded;
#endif
#ifdef ENABLE_OPENSSL
if (crypto_seed_openssl_rng() < 0)
return -1;
++seeded;
#endif
tor_assert(seeded);
return 0;
}
/**
* Write <b>n</b> bytes of strong random data to <b>to</b>. Supports mocking
@ -407,17 +474,44 @@ crypto_rand, (char *to, size_t n))
void
crypto_rand_unmocked(char *to, size_t n)
{
int r;
if (n == 0)
return;
tor_assert(n < INT_MAX);
tor_assert(to);
r = RAND_bytes((unsigned char*)to, (int)n);
#ifdef ENABLE_NSS
SECStatus s = PK11_GenerateRandom((unsigned char*)to, (int)n);
if (s != SECSuccess) {
/* NSS rather sensibly might refuse to generate huge amounts of random
* data at once. Unfortunately, our unit test do this in a couple of
* places. To solve this issue, we use our XOF to stretch a shorter
* output when a longer one is needed.
*
* Yes, this is secure. */
/* This is longer than it needs to be; 1600 bits == 200 bytes is the
* state-size of SHA3. */
#define BUFLEN 512
tor_assert(PR_GetError() == SEC_ERROR_INVALID_ARGS && n > BUFLEN);
unsigned char buf[BUFLEN];
s = PK11_GenerateRandom(buf, BUFLEN);
tor_assert(s == SECSuccess);
crypto_xof_t *xof = crypto_xof_new();
crypto_xof_add_bytes(xof, buf, BUFLEN);
crypto_xof_squeeze_bytes(xof, (unsigned char *)to, n);
crypto_xof_free(xof);
memwipe(buf, 0, BUFLEN);
#undef BUFLEN
}
#else
int r = RAND_bytes((unsigned char*)to, (int)n);
/* We consider a PRNG failure non-survivable. Let's assert so that we get a
* stack trace about where it happened.
*/
tor_assert(r >= 0);
#endif
}
/**

View File

@ -9,7 +9,7 @@
* \brief Block of functions related with RSA utilities and operations.
**/
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_format.h"
@ -207,7 +207,7 @@ crypto_pk_generate_key_with_bits,(crypto_pk_t *env, int bits))
}
if (!env->key) {
crypto_log_errors(LOG_WARN, "generating RSA key");
crypto_openssl_log_errors(LOG_WARN, "generating RSA key");
return -1;
}
@ -252,7 +252,7 @@ crypto_pk_read_private_key_from_string(crypto_pk_t *env,
BIO_free(b);
if (!env->key) {
crypto_log_errors(LOG_WARN, "Error parsing private key");
crypto_openssl_log_errors(LOG_WARN, "Error parsing private key");
return -1;
}
return 0;
@ -316,7 +316,7 @@ crypto_pk_write_key_to_string_impl(crypto_pk_t *env, char **dest,
r = PEM_write_bio_RSAPrivateKey(b, env->key, NULL,NULL,0,NULL,NULL);
if (!r) {
crypto_log_errors(LOG_WARN, "writing RSA key to string");
crypto_openssl_log_errors(LOG_WARN, "writing RSA key to string");
BIO_free(b);
return -1;
}
@ -382,7 +382,7 @@ crypto_pk_read_public_key_from_string(crypto_pk_t *env, const char *src,
env->key = PEM_read_bio_RSAPublicKey(b, NULL, pem_no_password_cb, NULL);
BIO_free(b);
if (!env->key) {
crypto_log_errors(LOG_WARN, "reading public key from string");
crypto_openssl_log_errors(LOG_WARN, "reading public key from string");
return -1;
}
@ -408,7 +408,7 @@ crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
return -1;
if (PEM_write_bio_RSAPrivateKey(bio, env->key, NULL,NULL,0,NULL,NULL)
== 0) {
crypto_log_errors(LOG_WARN, "writing private key");
crypto_openssl_log_errors(LOG_WARN, "writing private key");
BIO_free(bio);
return -1;
}
@ -434,7 +434,7 @@ crypto_pk_check_key(crypto_pk_t *env)
r = RSA_check_key(env->key);
if (r <= 0)
crypto_log_errors(LOG_WARN,"checking RSA key");
crypto_openssl_log_errors(LOG_WARN,"checking RSA key");
return r;
}
@ -601,7 +601,7 @@ crypto_pk_copy_full(crypto_pk_t *env)
*/
log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.",
privatekey?"private":"public");
crypto_log_errors(LOG_ERR,
crypto_openssl_log_errors(LOG_ERR,
privatekey ? "Duplicating a private key" :
"Duplicating a public key");
tor_fragile_assert();
@ -777,7 +777,7 @@ crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
(unsigned char*)from, (unsigned char*)to,
env->key, crypto_get_rsa_padding(padding));
if (r<0) {
crypto_log_errors(LOG_WARN, "performing RSA encryption");
crypto_openssl_log_errors(LOG_WARN, "performing RSA encryption");
return -1;
}
return r;
@ -813,7 +813,7 @@ crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
env->key, crypto_get_rsa_padding(padding));
if (r<0) {
crypto_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,
crypto_openssl_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,
"performing RSA decryption");
return -1;
}
@ -844,7 +844,7 @@ crypto_pk_public_checksig,(const crypto_pk_t *env, char *to,
env->key, RSA_PKCS1_PADDING);
if (r<0) {
crypto_log_errors(LOG_INFO, "checking RSA signature");
crypto_openssl_log_errors(LOG_INFO, "checking RSA signature");
return -1;
}
return r;
@ -876,7 +876,7 @@ crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
(unsigned char*)from, (unsigned char*)to,
(RSA*)env->key, RSA_PKCS1_PADDING);
if (r<0) {
crypto_log_errors(LOG_WARN, "generating RSA signature");
crypto_openssl_log_errors(LOG_WARN, "generating RSA signature");
return -1;
}
return r;
@ -921,7 +921,7 @@ crypto_pk_asn1_decode(const char *str, size_t len)
rsa = d2i_RSAPublicKey(NULL, &cp, len);
tor_free(buf);
if (!rsa) {
crypto_log_errors(LOG_WARN,"decoding public key");
crypto_openssl_log_errors(LOG_WARN,"decoding public key");
return NULL;
}
return crypto_new_pk_from_rsa_(rsa);
@ -976,6 +976,26 @@ crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
return 0;
}
/** 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++ = ' ';
}
}
tor_assert(out<end);
*out = '\0';
}
/** Check a siglen-byte long signature at <b>sig</b> against
* <b>datalen</b> bytes of data at <b>data</b>, using the public key
* in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
@ -1145,7 +1165,7 @@ crypto_pk_base64_decode(const char *str, size_t len)
const unsigned char *dp = (unsigned char*)der; /* Shut the compiler up. */
RSA *rsa = d2i_RSAPrivateKey(NULL, &dp, der_len);
if (!rsa) {
crypto_log_errors(LOG_WARN, "decoding private key");
crypto_openssl_log_errors(LOG_WARN, "decoding private key");
goto out;
}

View File

@ -29,6 +29,10 @@
/** Number of bytes added for PKCS1-OAEP padding. */
#define PKCS1_OAEP_PADDING_OVERHEAD 42
/** Length of encoded public key fingerprints, including space; but not
* including terminating NUL. */
#define FINGERPRINT_LEN 49
/** A public key, or a public/private key-pair. */
typedef struct crypto_pk_t crypto_pk_t;
@ -88,6 +92,7 @@ int crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len);
crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out);
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env,
const char *data, size_t datalen, const char *sig, size_t siglen));

View File

@ -12,7 +12,7 @@
#define CRYPTO_S2K_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_rand.h"

View File

@ -10,7 +10,6 @@
* \brief Common cryptographic utilities.
**/
#ifndef CRYPTO_UTIL_PRIVATE
#define CRYPTO_UTIL_PRIVATE
#include "lib/crypt_ops/crypto_util.h"
@ -105,25 +104,3 @@ memwipe(void *mem, uint8_t byte, size_t sz)
**/
memset(mem, byte, sz);
}
/** Log all pending crypto errors at level <b>severity</b>. Use
* <b>doing</b> to describe our current activities.
*/
void
crypto_log_errors(int severity, const char *doing)
{
unsigned long err;
const char *msg, *lib, *func;
while ((err = ERR_get_error()) != 0) {
msg = (const char*)ERR_reason_error_string(err);
lib = (const char*)ERR_lib_error_string(err);
func = (const char*)ERR_func_error_string(err);
if (!msg) msg = "(null)";
if (!lib) lib = "(null)";
if (!func) func = "(null)";
if (BUG(!doing)) doing = "(null)";
tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
doing, msg, lib, func);
}
}
#endif /* !defined(CRYPTO_UTIL_PRIVATE) */

View File

@ -18,13 +18,4 @@
/** OpenSSL-based utility functions. */
void memwipe(void *mem, uint8_t byte, size_t sz);
/** Log utility function */
void crypto_log_errors(int severity, const char *doing);
#ifdef CRYPTO_UTIL_PRIVATE
#ifdef TOR_UNIT_TESTS
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(CRYPTO_UTIL_PRIVATE) */
#endif /* !defined(TOR_CRYPTO_UTIL_H) */

View File

@ -6,14 +6,15 @@ noinst_LIBRARIES += src/lib/libtor-crypt-ops-testing.a
endif
src_lib_libtor_crypt_ops_a_SOURCES = \
src/lib/crypt_ops/aes.c \
src/lib/crypt_ops/crypto.c \
src/lib/crypt_ops/crypto_cipher.c \
src/lib/crypt_ops/crypto_curve25519.c \
src/lib/crypt_ops/crypto_dh.c \
src/lib/crypt_ops/crypto_dh_openssl.c \
src/lib/crypt_ops/crypto_digest.c \
src/lib/crypt_ops/crypto_ed25519.c \
src/lib/crypt_ops/crypto_format.c \
src/lib/crypt_ops/crypto_hkdf.c \
src/lib/crypt_ops/crypto_init.c \
src/lib/crypt_ops/crypto_ope.c \
src/lib/crypt_ops/crypto_openssl_mgt.c \
src/lib/crypt_ops/crypto_pwbox.c \
@ -23,10 +24,28 @@ src_lib_libtor_crypt_ops_a_SOURCES = \
src/lib/crypt_ops/crypto_util.c \
src/lib/crypt_ops/digestset.c
if USE_NSS
src_lib_libtor_crypt_ops_a_SOURCES += \
src/lib/crypt_ops/aes_nss.c \
src/lib/crypt_ops/crypto_dh_nss.c \
src/lib/crypt_ops/crypto_nss_mgt.c
else
src_lib_libtor_crypt_ops_a_SOURCES += \
src/lib/crypt_ops/aes_openssl.c
endif
if USE_OPENSSL
src_lib_libtor_crypt_ops_a_SOURCES += \
src/lib/crypt_ops/crypto_openssl_mgt.c
endif
src_lib_libtor_crypt_ops_a_CFLAGS = $(AM_CFLAGS) $(TOR_CFLAGS_CRYPTLIB)
src_lib_libtor_crypt_ops_testing_a_SOURCES = \
$(src_lib_libtor_crypt_ops_a_SOURCES)
src_lib_libtor_crypt_ops_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_lib_libtor_crypt_ops_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_lib_libtor_crypt_ops_testing_a_CFLAGS = \
$(AM_CFLAGS) $(TOR_CFLAGS_CRYPTLIB) $(TEST_CFLAGS)
noinst_HEADERS += \
src/lib/crypt_ops/aes.h \
@ -36,8 +55,10 @@ noinst_HEADERS += \
src/lib/crypt_ops/crypto_digest.h \
src/lib/crypt_ops/crypto_ed25519.h \
src/lib/crypt_ops/crypto_format.h \
src/lib/crypt_ops/crypto.h \
src/lib/crypt_ops/crypto_cipher.h \
src/lib/crypt_ops/crypto_hkdf.h \
src/lib/crypt_ops/crypto_init.h \
src/lib/crypt_ops/crypto_nss_mgt.h \
src/lib/crypt_ops/crypto_openssl_mgt.h \
src/lib/crypt_ops/crypto_ope.h \
src/lib/crypt_ops/crypto_pwbox.h \

View File

@ -1,4 +1,4 @@
src_lib_libcurve25519_donna_a_CFLAGS=
src_lib_libcurve25519_donna_a_CFLAGS=$(TOR_CFLAGS_CRYPTO)
if BUILD_CURVE25519_DONNA
src_lib_libcurve25519_donna_a_SOURCES=\

View File

@ -9,10 +9,13 @@ src_lib_libtor_tls_a_SOURCES = \
src/lib/tls/buffers_tls.c \
src/lib/tls/tortls.c
src_lib_libtor_tls_a_CFLAGS = $(AM_CFLAGS) $(TOR_CFLAGS_CRYPTLIB)
src_lib_libtor_tls_testing_a_SOURCES = \
$(src_lib_libtor_tls_a_SOURCES)
src_lib_libtor_tls_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_lib_libtor_tls_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_lib_libtor_tls_testing_a_CFLAGS = \
$(AM_CFLAGS) $(TOR_CFLAGS_CRYPTLIB) $(TEST_CFLAGS)
noinst_HEADERS += \
src/lib/tls/ciphers.inc \

View File

@ -24,7 +24,7 @@
#include <ws2tcpip.h>
#endif
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_util.h"
@ -1280,10 +1280,10 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
goto error;
}
{
crypto_dh_t *dh = crypto_dh_new(DH_TYPE_TLS);
DH *dh = crypto_dh_new_openssl_tls();
tor_assert(dh);
SSL_CTX_set_tmp_dh(result->ctx, crypto_dh_get_dh_(dh));
crypto_dh_free(dh);
SSL_CTX_set_tmp_dh(result->ctx, dh);
DH_free(dh);
}
if (! is_client) {
int nid;

View File

@ -175,6 +175,7 @@ pub fn main() {
cfg.from_cflags("TOR_ZLIB_LIBS");
cfg.from_cflags("TOR_LIB_MATH");
cfg.from_cflags("NSS_LIBS");
cfg.from_cflags("TOR_OPENSSL_LIBS");
cfg.from_cflags("TOR_LIBEVENT_LIBS");
cfg.from_cflags("TOR_LIB_WS32");

View File

@ -33,6 +33,7 @@
#include "core/or/or_circuit_st.h"
#include "lib/crypt_ops/digestset.h"
#include "lib/crypt_ops/crypto_init.h"
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
static uint64_t nanostart;
@ -680,9 +681,9 @@ main(int argc, const char **argv)
tor_threads_init();
tor_compress_init();
init_logging(1);
if (argc == 4 && !strcmp(argv[1], "diff")) {
init_logging(1);
const int N = 200;
char *f1 = read_file_to_str(argv[2], RFTS_BIN, NULL);
char *f2 = read_file_to_str(argv[3], RFTS_BIN, NULL);
@ -718,13 +719,12 @@ main(int argc, const char **argv)
reset_perftime();
if (crypto_seed_rng() < 0) {
if (crypto_global_init(0, NULL, NULL) < 0) {
printf("Couldn't seed RNG; exiting.\n");
return 1;
}
init_protocol_warning_severity_level();
crypto_init_siphash_key();
options = options_new();
init_logging(1);
options->command = CMD_RUN_UNITTESTS;

View File

@ -7,8 +7,8 @@
#include "app/config/config.h"
#include "test/fuzz/fuzzing.h"
#include "lib/compress/compress.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_init.h"
static or_options_t *mock_options = NULL;
static const or_options_t *
@ -96,15 +96,20 @@ global_init(void)
{
tor_threads_init();
tor_compress_init();
{
struct sipkey sipkey = { 1337, 7331 };
siphash_set_global_key(&sipkey);
}
/* Initialise logging first */
init_logging(1);
configure_backtrace_handler(get_version());
if (crypto_global_init(0, NULL, NULL) < 0)
abort();
{
struct sipkey sipkey = { 1337, 7331 };
siphash_unset_global_key();
siphash_set_global_key(&sipkey);
}
/* set up the options. */
mock_options = tor_malloc_zero(sizeof(or_options_t));
MOCK(get_options, mock_get_options);

View File

@ -5,12 +5,12 @@ FUZZING_CPPFLAGS = \
FUZZING_CFLAGS = \
$(AM_CFLAGS) $(TEST_CFLAGS)
FUZZING_LDFLAG = \
@TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
@TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@
FUZZING_LIBS = \
$(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@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@ \

View File

@ -226,13 +226,13 @@ src_test_test_switch_id_LDADD = \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_test_LDADD = \
$(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
$(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@
@ -249,23 +249,23 @@ src_test_test_memwipe_LDADD = $(src_test_test_LDADD)
# successfully with the libraries built with them.
src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) @CFLAGS_BUGTRAP@
src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_bench_LDADD = \
$(TOR_INTERNAL_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
$(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@
src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \
@TOR_LDFLAGS_libevent@
src_test_test_workqueue_LDADD = \
$(TOR_INTERNAL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
$(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
@ -277,7 +277,7 @@ src_test_test_timers_LDADD = \
$(TOR_UTIL_TESTING_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
$(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@
src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
@ -302,22 +302,22 @@ noinst_HEADERS+= \
noinst_PROGRAMS+= src/test/test-ntor-cl
noinst_PROGRAMS+= src/test/test-hs-ntor-cl
src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c
src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_test_test_ntor_cl_LDADD = \
$(TOR_INTERNAL_LIBS) \
$(rust_ldadd) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
$(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \
@CURVE25519_LIBS@ @TOR_LZMA_LIBS@
src_test_test_ntor_cl_AM_CPPFLAGS = \
$(AM_CPPFLAGS)
src_test_test_hs_ntor_cl_SOURCES = src/test/test_hs_ntor_cl.c
src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_test_test_hs_ntor_cl_LDADD = \
$(TOR_INTERNAL_LIBS) \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
$(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
$(AM_CPPFLAGS)

View File

@ -9,6 +9,7 @@
#include "lib/evloop/compat_libevent.h"
#include "lib/evloop/timers.h"
#include "lib/crypt_ops/crypto_init.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/log/util_bug.h"
#include "lib/time/compat_time.h"
@ -62,6 +63,10 @@ main(int argc, char **argv)
memset(&cfg, 0, sizeof(cfg));
tor_libevent_initialize(&cfg);
timers_initialize();
init_logging(1);
if (crypto_global_init(0, NULL, NULL) < 0)
return 1;
int i;
int ret;

View File

@ -16,6 +16,7 @@
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_hkdf.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_init.h"
#include "ed25519_vectors.inc"
#ifdef HAVE_SYS_STAT_H
@ -25,6 +26,13 @@
#include <unistd.h>
#endif
#if defined(ENABLE_OPENSSL)
#include "lib/crypt_ops/compat_openssl.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/dh.h>
ENABLE_GCC_WARNING(redundant-decls)
#endif
/** Run unit tests for Diffie-Hellman functionality. */
static void
test_crypto_dh(void *arg)
@ -37,6 +45,11 @@ test_crypto_dh(void *arg)
char s1[DH1024_KEY_LEN];
char s2[DH1024_KEY_LEN];
ssize_t s1len, s2len;
#ifdef ENABLE_OPENSSL
crypto_dh_t *dh3 = NULL;
DH *dh4 = NULL;
BIGNUM *pubkey_tmp = NULL;
#endif
(void)arg;
tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH1024_KEY_LEN);
@ -91,6 +104,10 @@ test_crypto_dh(void *arg)
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50);
tt_int_op(50, OP_EQ, s1len);
/* 2 a second time is still okay, though weird. */
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50);
tt_int_op(50, OP_EQ, s1len);
const char P[] =
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
@ -157,10 +174,50 @@ test_crypto_dh(void *arg)
tt_int_op(s1len, OP_EQ, -1);
}
#if defined(ENABLE_OPENSSL)
{
/* Make sure that our crypto library can handshake with openssl. */
dh3 = crypto_dh_new(DH_TYPE_TLS);
tt_assert(!crypto_dh_get_public(dh3, p1, DH1024_KEY_LEN));
dh4 = crypto_dh_new_openssl_tls();
tt_assert(DH_generate_key(dh4));
const BIGNUM *pk=NULL;
#ifdef OPENSSL_1_1_API
const BIGNUM *sk=NULL;
DH_get0_key(dh4, &pk, &sk);
#else
pk = dh4->pub_key;
#endif
tt_assert(pk);
tt_int_op(BN_num_bytes(pk), OP_LE, DH1024_KEY_LEN);
tt_int_op(BN_num_bytes(pk), OP_GT, 0);
memset(p2, 0, sizeof(p2));
/* right-pad. */
BN_bn2bin(pk, (unsigned char *)(p2+DH1024_KEY_LEN-BN_num_bytes(pk)));
s1len = crypto_dh_handshake(LOG_WARN, dh3, p2, DH1024_KEY_LEN,
(unsigned char *)s1, sizeof(s1));
pubkey_tmp = BN_bin2bn((unsigned char *)p1, DH1024_KEY_LEN, NULL);
s2len = DH_compute_key((unsigned char *)s2, pubkey_tmp, dh4);
tt_int_op(s1len, OP_EQ, s2len);
tt_int_op(s1len, OP_GT, 0);
tt_mem_op(s1, OP_EQ, s2, s1len);
}
#endif
done:
crypto_dh_free(dh1);
crypto_dh_free(dh2);
crypto_dh_free(dh1_dup);
#ifdef ENABLE_OPENSSL
crypto_dh_free(dh3);
if (dh4)
DH_free(dh4);
if (pubkey_tmp)
BN_free(pubkey_tmp);
#endif
}
static void

View File

@ -21,7 +21,7 @@
#include "test/hs_test_helpers.h"
#include "app/config/config.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "core/or/channeltls.h"
#include "feature/dircache/directory.h"

View File

@ -14,10 +14,11 @@
#define ONION_NTOR_PRIVATE
#include "core/or/or.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_init.h"
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_ntor.h"
@ -240,7 +241,11 @@ main(int argc, char **argv)
return 1;
}
init_logging(1);
curve25519_init();
if (crypto_global_init(0, NULL, NULL) < 0)
return 1;
if (!strcmp(argv[1], "client1")) {
return client1(argc, argv);
} else if (!strcmp(argv[1], "server1")) {

View File

@ -2,7 +2,7 @@
/* See LICENSE for licensing information */
#include "orconfig.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "core/or/or.h"
#include "test/test.h"

View File

@ -7,8 +7,9 @@
#define ONION_NTOR_PRIVATE
#include "core/or/or.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_init.h"
#include "core/crypto/onion_ntor.h"
#define N_ARGS(n) STMT_BEGIN { \
@ -153,7 +154,11 @@ main(int argc, char **argv)
return 1;
}
init_logging(1);
curve25519_init();
if (crypto_global_init(0, NULL, NULL) < 0)
return 1;
if (!strcmp(argv[1], "client1")) {
return client1(argc, argv);
} else if (!strcmp(argv[1], "server1")) {
@ -165,4 +170,3 @@ main(int argc, char **argv)
return 1;
}
}

View File

@ -9,7 +9,7 @@
#include "core/mainloop/main.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/connection_edge.h"

View File

@ -9,7 +9,7 @@
#include "app/config/config.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_format.h"
#include "feature/nodelist/torcert.h"
#include "test/test.h"

View File

@ -6,7 +6,7 @@
#include "orconfig.h"
#define UTIL_PRIVATE
#define SUBPROCESS_PRIVATE
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/log/log.h"
#include "lib/process/subprocess.h"
#include "lib/process/waitpid.h"

View File

@ -12,6 +12,7 @@
#include "lib/net/alertsock.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/intmath/weakrng.h"
#include "lib/crypt_ops/crypto_init.h"
#include <stdio.h>

View File

@ -23,6 +23,7 @@
#include "core/mainloop/main.h"
#include "lib/compress/compress.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/crypt_ops/crypto_init.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@ -222,6 +223,13 @@ an_assertion_failed(void)
tinytest_set_test_failed_();
}
void tinytest_postfork(void);
void
tinytest_postfork(void)
{
crypto_postfork();
}
/** Main entry point for unit test code: parse the command line, and run
* some unit tests. */
int
@ -284,7 +292,6 @@ main(int c, const char **v)
printf("Can't initialize crypto subsystem; exiting.\n");
return 1;
}
crypto_set_tls_dh_prime();
if (crypto_seed_rng() < 0) {
printf("Couldn't seed RNG; exiting.\n");
return 1;

View File

@ -21,12 +21,12 @@ src_tools_tor_cov_resolve_LDADD = \
endif
src_tools_tor_gencert_SOURCES = src/tools/tor-gencert.c
src_tools_tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
src_tools_tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_tools_tor_gencert_LDADD = \
$(TOR_CRYPTO_LIBS) \
$(TOR_UTIL_LIBS) \
$(rust_ldadd) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ $(TOR_LIBS_CRYPTLIB) \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
src_tools_tor_print_ed_signing_cert_SOURCES = src/tools/tor-print-ed-signing-cert.c
@ -35,18 +35,18 @@ src_tools_tor_print_ed_signing_cert_LDADD = \
src/trunnel/libor-trunnel.a \
$(TOR_CRYPTO_LIBS) \
$(TOR_UTIL_LIBS) \
@TOR_LIB_MATH@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_MATH@ $(TOR_LIBS_CRYPTLIB) \
@TOR_LIB_WS32@ @TOR_LIB_USERENV@
if COVERAGE_ENABLED
src_tools_tor_cov_gencert_SOURCES = src/tools/tor-gencert.c
src_tools_tor_cov_gencert_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_tools_tor_cov_gencert_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_tools_tor_cov_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
src_tools_tor_cov_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB)
src_tools_tor_cov_gencert_LDADD = \
$(TOR_CRYPTO_TESTING_LIBS) \
$(TOR_UTIL_TESTING_LIBS) \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ $(TOR_LIBS_CRYPTLIB) \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
endif

View File

@ -14,6 +14,8 @@
#endif
#include "lib/cc/compat_compiler.h"
#include "lib/crypt_ops/crypto_init.h"
#include "lib/crypt_ops/crypto_openssl_mgt.h"
/* Some versions of OpenSSL declare X509_STORE_CTX_set_verify_cb twice in
* x509.h and x509_vfy.h. Suppress the GCC warning so we can build with
@ -31,9 +33,9 @@ ENABLE_GCC_WARNING(redundant-decls)
#include <errno.h>
#include "lib/crypt_ops/crypto.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_rsa.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/binascii.h"
#include "lib/encoding/time_fmt.h"
@ -266,7 +268,7 @@ load_identity_key(void)
IDENTITY_KEY_BITS);
if (!(key = generate_key(IDENTITY_KEY_BITS))) {
log_err(LD_GENERAL, "Couldn't generate identity key.");
crypto_log_errors(LOG_ERR, "Generating identity key");
crypto_openssl_log_errors(LOG_ERR, "Generating identity key");
return 1;
}
identity_key = EVP_PKEY_new();
@ -288,7 +290,7 @@ load_identity_key(void)
NULL, NULL)) {
log_err(LD_GENERAL, "Couldn't write identity key to %s",
identity_key_file);
crypto_log_errors(LOG_ERR, "Writing identity key");
crypto_openssl_log_errors(LOG_ERR, "Writing identity key");
abort_writing_to_file(open_file);
return 1;
}
@ -353,7 +355,7 @@ generate_signing_key(void)
SIGNING_KEY_BITS);
if (!(key = generate_key(SIGNING_KEY_BITS))) {
log_err(LD_GENERAL, "Couldn't generate signing key.");
crypto_log_errors(LOG_ERR, "Generating signing key");
crypto_openssl_log_errors(LOG_ERR, "Generating signing key");
return 1;
}
signing_key = EVP_PKEY_new();
@ -369,7 +371,7 @@ generate_signing_key(void)
/* Write signing key with no encryption. */
if (!PEM_write_RSAPrivateKey(f, key, NULL, NULL, 0, NULL, NULL)) {
crypto_log_errors(LOG_WARN, "writing signing key");
crypto_openssl_log_errors(LOG_WARN, "writing signing key");
abort_writing_to_file(open_file);
return 1;
}
@ -393,7 +395,7 @@ key_to_string(EVP_PKEY *key)
b = BIO_new(BIO_s_mem());
if (!PEM_write_bio_RSAPublicKey(b, rsa)) {
crypto_log_errors(LOG_WARN, "writing public key to string");
crypto_openssl_log_errors(LOG_WARN, "writing public key to string");
RSA_free(rsa);
return NULL;
}