aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/aes.c409
-rw-r--r--src/common/aes.h29
-rw-r--r--src/common/buffers_tls.c179
-rw-r--r--src/common/buffers_tls.h19
-rw-r--r--src/common/ciphers.inc100
-rw-r--r--src/common/compat_openssl.h51
-rw-r--r--src/common/crypto.c508
-rw-r--r--src/common/crypto.h76
-rw-r--r--src/common/crypto_curve25519.c359
-rw-r--r--src/common/crypto_curve25519.h89
-rw-r--r--src/common/crypto_dh.c510
-rw-r--r--src/common/crypto_dh.h49
-rw-r--r--src/common/crypto_digest.c583
-rw-r--r--src/common/crypto_digest.h136
-rw-r--r--src/common/crypto_ed25519.c817
-rw-r--r--src/common/crypto_ed25519.h145
-rw-r--r--src/common/crypto_format.c299
-rw-r--r--src/common/crypto_format.h47
-rw-r--r--src/common/crypto_hkdf.c193
-rw-r--r--src/common/crypto_hkdf.h28
-rw-r--r--src/common/crypto_openssl_mgt.c161
-rw-r--r--src/common/crypto_openssl_mgt.h85
-rw-r--r--src/common/crypto_pwbox.c215
-rw-r--r--src/common/crypto_pwbox.h23
-rw-r--r--src/common/crypto_rand.c615
-rw-r--r--src/common/crypto_rand.h52
-rw-r--r--src/common/crypto_rsa.c1162
-rw-r--r--src/common/crypto_rsa.h119
-rw-r--r--src/common/crypto_s2k.c476
-rw-r--r--src/common/crypto_s2k.h73
-rw-r--r--src/common/crypto_util.c130
-rw-r--r--src/common/crypto_util.h30
-rw-r--r--src/common/include.am43
-rw-r--r--src/common/tortls.c2663
-rw-r--r--src/common/tortls.h295
35 files changed, 0 insertions, 10768 deletions
diff --git a/src/common/aes.c b/src/common/aes.c
deleted file mode 100644
index 70e48a74f3..0000000000
--- a/src/common/aes.c
+++ /dev/null
@@ -1,409 +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 aes.c
- * \brief Implements a counter-mode stream cipher on top of AES.
- **/
-
-#include "orconfig.h"
-
-#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#endif
-
-#include "common/compat_openssl.h"
-#include <openssl/opensslv.h>
-#include "common/crypto_openssl_mgt.h"
-
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0)
-#error "We require OpenSSL >= 1.0.0"
-#endif
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/modes.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include "common/compat.h"
-#include "common/aes.h"
-#include "common/util.h"
-#include "common/torlog.h"
-#include "lib/ctime/di_ops.h"
-
-#ifdef ANDROID
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
-/* We have five strategies for implementing AES counter mode.
- *
- * Best with x86 and x86_64: Use EVP_aes_*_ctr() and EVP_EncryptUpdate().
- * This is possible with OpenSSL 1.0.1, where the counter-mode implementation
- * can use bit-sliced or vectorized AES or AESNI as appropriate.
- *
- * Otherwise: Pick the best possible AES block implementation that OpenSSL
- * gives us, and the best possible counter-mode implementation, and combine
- * them.
- */
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0)
-
-/* With newer OpenSSL versions, the older fallback modes don't compile. So
- * don't use them, even if we lack specific acceleration. */
-
-#define USE_EVP_AES_CTR
-
-#elif OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,0,1) && \
- (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__))
-
-#define USE_EVP_AES_CTR
-
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) || ... */
-
-/* We have 2 strategies for getting the AES block cipher: Via OpenSSL's
- * AES_encrypt function, or via OpenSSL's EVP_EncryptUpdate function.
- *
- * If there's any hardware acceleration in play, we want to be using EVP_* so
- * we can get it. Otherwise, we'll want AES_*, which seems to be about 5%
- * faster than indirecting through the EVP layer.
- */
-
-/* We have 2 strategies for getting a plug-in counter mode: use our own, or
- * use OpenSSL's.
- *
- * Here we have a counter mode that's faster than the one shipping with
- * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode
- * implementation faster than the one here (by about 7%). So we pick which
- * one to used based on the Openssl version above. (OpenSSL 1.0.0a fixed a
- * critical bug in that counter mode implementation, so we need to test to
- * make sure that we have a fixed version.)
- */
-
-#ifdef USE_EVP_AES_CTR
-
-/* We don't actually define the struct here. */
-
-aes_cnt_cipher_t *
-aes_new_cipher(const uint8_t *key, const uint8_t *iv, int key_bits)
-{
- EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
- const EVP_CIPHER *c;
- switch (key_bits) {
- case 128: c = EVP_aes_128_ctr(); break;
- case 192: c = EVP_aes_192_ctr(); break;
- case 256: c = EVP_aes_256_ctr(); break;
- default: tor_assert(0); // LCOV_EXCL_LINE
- }
- EVP_EncryptInit(cipher, c, key, iv);
- return (aes_cnt_cipher_t *) cipher;
-}
-void
-aes_cipher_free_(aes_cnt_cipher_t *cipher_)
-{
- if (!cipher_)
- return;
- EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
-#ifdef OPENSSL_1_1_API
- EVP_CIPHER_CTX_reset(cipher);
-#else
- EVP_CIPHER_CTX_cleanup(cipher);
-#endif
- EVP_CIPHER_CTX_free(cipher);
-}
-void
-aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len)
-{
- int outl;
- EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
-
- tor_assert(len < INT_MAX);
-
- EVP_EncryptUpdate(cipher, (unsigned char*)data,
- &outl, (unsigned char*)data, (int)len);
-}
-int
-evaluate_evp_for_aes(int force_val)
-{
- (void) force_val;
- log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP "
- "counter-mode implementation. Using it.");
- return 0;
-}
-int
-evaluate_ctr_for_aes(void)
-{
- return 0;
-}
-#else /* !(defined(USE_EVP_AES_CTR)) */
-
-/*======================================================================*/
-/* Interface to AES code, and counter implementation */
-
-/** Implements an AES counter-mode cipher. */
-struct aes_cnt_cipher {
-/** This next element (however it's defined) is the AES key. */
- union {
- EVP_CIPHER_CTX evp;
- AES_KEY aes;
- } key;
-
-#if !defined(WORDS_BIGENDIAN)
-#define USING_COUNTER_VARS
- /** These four values, together, implement a 128-bit counter, with
- * counter0 as the low-order word and counter3 as the high-order word. */
- uint32_t counter3;
- uint32_t counter2;
- uint32_t counter1;
- uint32_t counter0;
-#endif /* !defined(WORDS_BIGENDIAN) */
-
- union {
- /** The counter, in big-endian order, as bytes. */
- uint8_t buf[16];
- /** The counter, in big-endian order, as big-endian words. Note that
- * on big-endian platforms, this is redundant with counter3...0,
- * so we just use these values instead. */
- uint32_t buf32[4];
- } ctr_buf;
-
- /** The encrypted value of ctr_buf. */
- uint8_t buf[16];
- /** Our current stream position within buf. */
- unsigned int pos;
-
- /** True iff we're using the evp implementation of this cipher. */
- uint8_t using_evp;
-};
-
-/** True iff we should prefer the EVP implementation for AES, either because
- * we're testing it or because we have hardware acceleration configured */
-static int should_use_EVP = 0;
-
-/** Check whether we should use the EVP interface for AES. If <b>force_val</b>
- * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP
- * if there is an engine enabled for aes-ecb. */
-int
-evaluate_evp_for_aes(int force_val)
-{
- ENGINE *e;
-
- if (force_val >= 0) {
- should_use_EVP = force_val;
- return 0;
- }
-#ifdef DISABLE_ENGINES
- should_use_EVP = 0;
-#else
- e = ENGINE_get_cipher_engine(NID_aes_128_ecb);
-
- if (e) {
- log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.",
- ENGINE_get_name(e));
- should_use_EVP = 1;
- } else {
- log_info(LD_CRYPTO, "No AES engine found; using AES_* functions.");
- should_use_EVP = 0;
- }
-#endif /* defined(DISABLE_ENGINES) */
-
- return 0;
-}
-
-/** Test the OpenSSL counter mode implementation to see whether it has the
- * counter-mode bug from OpenSSL 1.0.0. If the implementation works, then
- * we will use it for future encryption/decryption operations.
- *
- * We can't just look at the OpenSSL version, since some distributions update
- * their OpenSSL packages without changing the version number.
- **/
-int
-evaluate_ctr_for_aes(void)
-{
- /* Result of encrypting an all-zero block with an all-zero 128-bit AES key.
- * This should be the same as encrypting an all-zero block with an all-zero
- * 128-bit AES key in counter mode, starting at position 0 of the stream.
- */
- static const unsigned char encrypt_zero[] =
- "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e";
- unsigned char zero[16];
- unsigned char output[16];
- unsigned char ivec[16];
- unsigned char ivec_tmp[16];
- unsigned int pos, i;
- AES_KEY key;
- memset(zero, 0, sizeof(zero));
- memset(ivec, 0, sizeof(ivec));
- AES_set_encrypt_key(zero, 128, &key);
-
- pos = 0;
- /* Encrypting a block one byte at a time should make the error manifest
- * itself for known bogus openssl versions. */
- for (i=0; i<16; ++i)
- AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos);
-
- if (fast_memneq(output, encrypt_zero, 16)) {
- /* Counter mode is buggy */
- /* LCOV_EXCL_START */
- log_err(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; "
- "quitting tor.");
- exit(1); // exit ok: openssl is broken.
- /* LCOV_EXCL_STOP */
- }
- return 0;
-}
-
-#if !defined(USING_COUNTER_VARS)
-#define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)])
-#else
-#define COUNTER(c, n) ((c)->counter ## n)
-#endif
-
-static void aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key,
- int key_bits);
-static void aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv);
-
-/**
- * Return a newly allocated counter-mode AES128 cipher implementation,
- * using the 128-bit key <b>key</b> and the 128-bit IV <b>iv</b>.
- */
-aes_cnt_cipher_t*
-aes_new_cipher(const uint8_t *key, const uint8_t *iv, int bits)
-{
- aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t));
-
- aes_set_key(result, key, bits);
- aes_set_iv(result, iv);
-
- return result;
-}
-
-/** Set the key of <b>cipher</b> to <b>key</b>, which is
- * <b>key_bits</b> bits long (must be 128, 192, or 256). Also resets
- * the counter to 0.
- */
-static void
-aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, int key_bits)
-{
- if (should_use_EVP) {
- const EVP_CIPHER *c = 0;
- switch (key_bits) {
- case 128: c = EVP_aes_128_ecb(); break;
- case 192: c = EVP_aes_192_ecb(); break;
- case 256: c = EVP_aes_256_ecb(); break;
- default: tor_assert(0); // LCOV_EXCL_LINE
- }
- EVP_EncryptInit(&cipher->key.evp, c, key, NULL);
- cipher->using_evp = 1;
- } else {
- AES_set_encrypt_key(key, key_bits,&cipher->key.aes);
- cipher->using_evp = 0;
- }
-
-#ifdef USING_COUNTER_VARS
- cipher->counter0 = 0;
- cipher->counter1 = 0;
- cipher->counter2 = 0;
- cipher->counter3 = 0;
-#endif /* defined(USING_COUNTER_VARS) */
-
- memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf));
-
- cipher->pos = 0;
-
- memset(cipher->buf, 0, sizeof(cipher->buf));
-}
-
-/** Release storage held by <b>cipher</b>
- */
-void
-aes_cipher_free_(aes_cnt_cipher_t *cipher)
-{
- if (!cipher)
- return;
- if (cipher->using_evp) {
- EVP_CIPHER_CTX_cleanup(&cipher->key.evp);
- }
- memwipe(cipher, 0, sizeof(aes_cnt_cipher_t));
- tor_free(cipher);
-}
-
-#if defined(USING_COUNTER_VARS)
-#define UPDATE_CTR_BUF(c, n) STMT_BEGIN \
- (c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \
- STMT_END
-#else
-#define UPDATE_CTR_BUF(c, n)
-#endif /* defined(USING_COUNTER_VARS) */
-
-/* Helper function to use EVP with openssl's counter-mode wrapper. */
-static void
-evp_block128_fn(const uint8_t in[16],
- uint8_t out[16],
- const void *key)
-{
- EVP_CIPHER_CTX *ctx = (void*)key;
- int inl=16, outl=16;
- EVP_EncryptUpdate(ctx, out, &outl, in, inl);
-}
-
-/** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place.
- * Uses the key in <b>cipher</b>, and advances the counter by <b>len</b> bytes
- * as it encrypts.
- */
-void
-aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
-{
- /* Note that the "128" below refers to the length of the counter,
- * not the length of the AES key. */
- if (cipher->using_evp) {
- /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If
- * it weren't disabled, it might be better just to use that.
- */
- CRYPTO_ctr128_encrypt((const unsigned char *)data,
- (unsigned char *)data,
- len,
- &cipher->key.evp,
- cipher->ctr_buf.buf,
- cipher->buf,
- &cipher->pos,
- evp_block128_fn);
- } else {
- AES_ctr128_encrypt((const unsigned char *)data,
- (unsigned char *)data,
- len,
- &cipher->key.aes,
- cipher->ctr_buf.buf,
- cipher->buf,
- &cipher->pos);
- }
-}
-
-/** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
- * in <b>iv</b>. */
-static void
-aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv)
-{
-#ifdef USING_COUNTER_VARS
- cipher->counter3 = ntohl(get_uint32(iv));
- cipher->counter2 = ntohl(get_uint32(iv+4));
- cipher->counter1 = ntohl(get_uint32(iv+8));
- cipher->counter0 = ntohl(get_uint32(iv+12));
-#endif /* defined(USING_COUNTER_VARS) */
- cipher->pos = 0;
- memcpy(cipher->ctr_buf.buf, iv, 16);
-}
-
-#endif /* defined(USE_EVP_AES_CTR) */
-
diff --git a/src/common/aes.h b/src/common/aes.h
deleted file mode 100644
index e1287d330e..0000000000
--- a/src/common/aes.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/* Implements a minimal interface to counter-mode AES. */
-
-#ifndef TOR_AES_H
-#define TOR_AES_H
-
-/**
- * \file aes.h
- * \brief Headers for aes.c
- */
-
-typedef struct aes_cnt_cipher aes_cnt_cipher_t;
-
-aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
- int key_bits);
-void aes_cipher_free_(aes_cnt_cipher_t *cipher);
-#define aes_cipher_free(cipher) \
- FREE_AND_NULL(aes_cnt_cipher_t, aes_cipher_free_, (cipher))
-void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len);
-
-int evaluate_evp_for_aes(int force_value);
-int evaluate_ctr_for_aes(void);
-
-#endif /* !defined(TOR_AES_H) */
-
diff --git a/src/common/buffers_tls.c b/src/common/buffers_tls.c
deleted file mode 100644
index 0a57b95529..0000000000
--- a/src/common/buffers_tls.c
+++ /dev/null
@@ -1,179 +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 */
-
-#define BUFFERS_PRIVATE
-#include "orconfig.h"
-#include <stddef.h>
-#include "common/buffers.h"
-#include "common/buffers_tls.h"
-#include "common/compat.h"
-#include "lib/compress/compress.h"
-#include "common/util.h"
-#include "lib/cc/torint.h"
-#include "common/torlog.h"
-#include "common/tortls.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/** As read_to_chunk(), but return (negative) error code on error, blocking,
- * or TLS, and the number of bytes read otherwise. */
-static inline int
-read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
- size_t at_most)
-{
- int read_result;
-
- tor_assert(CHUNK_REMAINING_CAPACITY(chunk) >= at_most);
- read_result = tor_tls_read(tls, CHUNK_WRITE_PTR(chunk), at_most);
- if (read_result < 0)
- return read_result;
- buf->datalen += read_result;
- chunk->datalen += read_result;
- return read_result;
-}
-
-/** As read_to_buf, but reads from a TLS connection, and returns a TLS
- * status value rather than the number of bytes read.
- *
- * Using TLS on OR connections complicates matters in two ways.
- *
- * First, a TLS stream has its own read buffer independent of the
- * connection's read buffer. (TLS needs to read an entire frame from
- * the network before it can decrypt any data. Thus, trying to read 1
- * byte from TLS can require that several KB be read from the network
- * and decrypted. The extra data is stored in TLS's decrypt buffer.)
- * Because the data hasn't been read by Tor (it's still inside the TLS),
- * this means that sometimes a connection "has stuff to read" even when
- * poll() didn't return POLLIN. The tor_tls_get_pending_bytes function is
- * used in connection.c to detect TLS objects with non-empty internal
- * buffers and read from them again.
- *
- * Second, the TLS stream's events do not correspond directly to network
- * events: sometimes, before a TLS stream can read, the network must be
- * ready to write -- or vice versa.
- */
-int
-buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
-{
- int r = 0;
- size_t total_read = 0;
-
- check_no_tls_errors();
-
- if (BUG(buf->datalen >= INT_MAX))
- return -1;
- if (BUG(buf->datalen >= INT_MAX - at_most))
- return -1;
-
- while (at_most > total_read) {
- size_t readlen = at_most - total_read;
- chunk_t *chunk;
- if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
- chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
- if (readlen > chunk->memlen)
- readlen = chunk->memlen;
- } else {
- size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
- chunk = buf->tail;
- if (cap < readlen)
- readlen = cap;
- }
-
- r = read_to_chunk_tls(buf, chunk, tls, readlen);
- if (r < 0)
- return r; /* Error */
- tor_assert(total_read+r < INT_MAX);
- total_read += r;
- if ((size_t)r < readlen) /* eof, block, or no more to read. */
- break;
- }
- return (int)total_read;
-}
-
-/** Helper for buf_flush_to_tls(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. (Tries to write
- * more if there is a forced pending write size.) On success, deduct the
- * bytes written from *<b>buf_flushlen</b>. Return the number of bytes
- * written on success, and a TOR_TLS error code on failure or blocking.
- */
-static inline int
-flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
- size_t sz, size_t *buf_flushlen)
-{
- int r;
- size_t forced;
- char *data;
-
- forced = tor_tls_get_forced_write_size(tls);
- if (forced > sz)
- sz = forced;
- if (chunk) {
- data = chunk->data;
- tor_assert(sz <= chunk->datalen);
- } else {
- data = NULL;
- tor_assert(sz == 0);
- }
- r = tor_tls_write(tls, data, sz);
- if (r < 0)
- return r;
- if (*buf_flushlen > (size_t)r)
- *buf_flushlen -= r;
- else
- *buf_flushlen = 0;
- buf_drain(buf, r);
- log_debug(LD_NET,"flushed %d bytes, %d ready to flush, %d remain.",
- r,(int)*buf_flushlen,(int)buf->datalen);
- return r;
-}
-
-/** As buf_flush_to_socket(), but writes data to a TLS connection. Can write
- * more than <b>flushlen</b> bytes.
- */
-int
-buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
- size_t *buf_flushlen)
-{
- int r;
- size_t flushed = 0;
- ssize_t sz;
- tor_assert(buf_flushlen);
- if (BUG(*buf_flushlen > buf->datalen)) {
- *buf_flushlen = buf->datalen;
- }
- if (BUG(flushlen > *buf_flushlen)) {
- flushlen = *buf_flushlen;
- }
- sz = (ssize_t) flushlen;
-
- /* we want to let tls write even if flushlen is zero, because it might
- * have a partial record pending */
- check_no_tls_errors();
-
- do {
- size_t flushlen0;
- if (buf->head) {
- if ((ssize_t)buf->head->datalen >= sz)
- flushlen0 = sz;
- else
- flushlen0 = buf->head->datalen;
- } else {
- flushlen0 = 0;
- }
-
- r = flush_chunk_tls(tls, buf, buf->head, flushlen0, buf_flushlen);
- if (r < 0)
- return r;
- flushed += r;
- sz -= r;
- if (r == 0) /* Can't flush any more now. */
- break;
- } while (sz > 0);
- tor_assert(flushed < INT_MAX);
- return (int)flushed;
-}
-
diff --git a/src/common/buffers_tls.h b/src/common/buffers_tls.h
deleted file mode 100644
index d9d26c82bd..0000000000
--- a/src/common/buffers_tls.h
+++ /dev/null
@@ -1,19 +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 */
-
-#ifndef TOR_BUFFERS_TLS_H
-#define TOR_BUFFERS_TLS_H
-
-struct buf_t;
-struct tor_tls_t;
-
-int buf_read_from_tls(struct buf_t *buf,
- struct tor_tls_t *tls, size_t at_most);
-int buf_flush_to_tls(struct buf_t *buf, struct tor_tls_t *tls,
- size_t sz, size_t *buf_flushlen);
-
-#endif /* !defined(TOR_BUFFERS_TLS_H) */
-
diff --git a/src/common/ciphers.inc b/src/common/ciphers.inc
deleted file mode 100644
index 0084b3e325..0000000000
--- a/src/common/ciphers.inc
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This is an include file used to define the list of ciphers clients should
- * advertise. Before including it, you should define the CIPHER and XCIPHER
- * macros.
- *
- * This file was automatically generated by get_mozilla_ciphers.py;
- * TLSv1.3 ciphers were added manually.
- */
-
-/* Here are the TLS1.3 ciphers. Note that we don't have XCIPHER instances
- * here, since we don't want to ever fake them.
- */
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- CIPHER(0x1301, TLS1_3_TXT_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_3_TXT_AES_256_GCM_SHA384
- CIPHER(0x1302, TLS1_3_TXT_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256
- CIPHER(0x1303, TLS1_3_TXT_CHACHA20_POLY1305_SHA256)
-#endif
-#ifdef TLS1_3_TXT_AES_128_CCM_SHA256
- CIPHER(0x1304, TLS1_3_TXT_AES_128_CCM_SHA256)
-#endif
-
-/* Here's the machine-generated list. */
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- CIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
-#else
- XCIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- CIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-#else
- XCIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- CIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)
-#else
- XCIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305
- CIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305)
-#else
- XCIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- CIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
-#else
- XCIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- CIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
-#else
- XCIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- CIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
-#else
- XCIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- CIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
-#else
- XCIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA
- CIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-#else
- XCIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA
- CIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-#else
- XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA
- CIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
-#else
- XCIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA
- CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA)
-#else
- XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA)
-#endif
-#ifdef TLS1_TXT_RSA_WITH_AES_128_SHA
- CIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA)
-#else
- XCIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA)
-#endif
-#ifdef TLS1_TXT_RSA_WITH_AES_256_SHA
- CIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA)
-#else
- XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA)
-#endif
-#ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA
- CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA)
-#else
- XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA)
-#endif
diff --git a/src/common/compat_openssl.h b/src/common/compat_openssl.h
deleted file mode 100644
index a94b264927..0000000000
--- a/src/common/compat_openssl.h
+++ /dev/null
@@ -1,51 +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 */
-
-#ifndef TOR_COMPAT_OPENSSL_H
-#define TOR_COMPAT_OPENSSL_H
-
-#include <openssl/opensslv.h>
-#include "common/crypto_openssl_mgt.h"
-
-/**
- * \file compat_openssl.h
- *
- * \brief compatibility definitions for working with different openssl forks
- **/
-
-#if !defined(LIBRESSL_VERSION_NUMBER) && \
- OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,1)
-#error "We require OpenSSL >= 1.0.1"
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && \
- ! defined(LIBRESSL_VERSION_NUMBER)
-/* We define this macro if we're trying to build with the majorly refactored
- * API in OpenSSL 1.1 */
-#define OPENSSL_1_1_API
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && ... */
-
-#ifndef OPENSSL_VERSION
-#define OPENSSL_VERSION SSLEAY_VERSION
-#endif
-
-#ifndef OPENSSL_1_1_API
-#define OpenSSL_version(v) SSLeay_version(v)
-#define OpenSSL_version_num() SSLeay()
-#define RAND_OpenSSL() RAND_SSLeay()
-#define STATE_IS_SW_SERVER_HELLO(st) \
- (((st) == SSL3_ST_SW_SRVR_HELLO_A) || \
- ((st) == SSL3_ST_SW_SRVR_HELLO_B))
-#define OSSL_HANDSHAKE_STATE int
-#define CONST_IF_OPENSSL_1_1_API
-#else /* !(!defined(OPENSSL_1_1_API)) */
-#define STATE_IS_SW_SERVER_HELLO(st) \
- ((st) == TLS_ST_SW_SRVR_HELLO)
-#define CONST_IF_OPENSSL_1_1_API const
-#endif /* !defined(OPENSSL_1_1_API) */
-
-#endif /* !defined(TOR_COMPAT_OPENSSL_H) */
-
diff --git a/src/common/crypto.c b/src/common/crypto.c
deleted file mode 100644
index 8a8bb2b770..0000000000
--- a/src/common/crypto.c
+++ /dev/null
@@ -1,508 +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 "common/compat_openssl.h"
-#include "common/crypto.h"
-#include "common/crypto_curve25519.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_dh.h"
-#include "common/crypto_ed25519.h"
-#include "common/crypto_format.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_rsa.h"
-#include "common/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 "common/torlog.h"
-#include "lib/cc/torint.h"
-#include "common/aes.h"
-#include "common/util.h"
-#include "common/container.h"
-#include "common/compat.h"
-#include "common/sandbox.h"
-#include "common/util_format.h"
-
-#include "keccak-tiny/keccak-tiny.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;
-}
-
-/** @} */
diff --git a/src/common/crypto.h b/src/common/crypto.h
deleted file mode 100644
index 1324468097..0000000000
--- a/src/common/crypto.h
+++ /dev/null
@@ -1,76 +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.h
- *
- * \brief Headers for crypto.c
- **/
-
-#ifndef TOR_CRYPTO_H
-#define TOR_CRYPTO_H
-
-#include "orconfig.h"
-
-#include <stdio.h>
-#include "lib/cc/torint.h"
-#include "common/compat.h"
-#include "common/util.h"
-#include "common/crypto_rsa.h"
-
-/** Length of our symmetric cipher's keys of 128-bit. */
-#define CIPHER_KEY_LEN 16
-/** Length of our symmetric cipher's IV of 128-bit. */
-#define CIPHER_IV_LEN 16
-/** 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);
-crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv);
-crypto_cipher_t *crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
- const uint8_t *iv,
- int bits);
-void crypto_cipher_free_(crypto_cipher_t *env);
-#define crypto_cipher_free(c) \
- FREE_AND_NULL(crypto_cipher_t, crypto_cipher_free_, (c))
-
-/* symmetric crypto */
-const char *crypto_cipher_get_key(crypto_cipher_t *env);
-
-int crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen);
-int crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
- const char *from, size_t fromlen);
-void crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *d, size_t len);
-
-int crypto_cipher_encrypt_with_iv(const char *key,
- char *to, size_t tolen,
- const char *from, size_t fromlen);
-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) */
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c
deleted file mode 100644
index f28cebb887..0000000000
--- a/src/common/crypto_curve25519.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Copyright (c) 2012-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_curve25519.c
- *
- * \brief Wrapper code for a curve25519 implementation.
- *
- * Curve25519 is an Elliptic-Curve Diffie Hellman handshake, designed by
- * Dan Bernstein. For more information, see https://cr.yp.to/ecdh.html
- *
- * Tor uses Curve25519 as the basis of its "ntor" circuit extension
- * handshake, and in related code. The functions in this module are
- * used to find the most suitable available Curve25519 implementation,
- * to provide wrappers around it, and so on.
- */
-
-#define CRYPTO_CURVE25519_PRIVATE
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "common/container.h"
-#include "common/crypto_curve25519.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_format.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_util.h"
-#include "common/util.h"
-#include "common/torlog.h"
-
-#include "ed25519/donna/ed25519_donna_tor.h"
-
-/* ==============================
- Part 1: wrap a suitable curve25519 implementation as curve25519_impl
- ============================== */
-
-#ifdef USE_CURVE25519_DONNA
-int curve25519_donna(uint8_t *mypublic,
- const uint8_t *secret, const uint8_t *basepoint);
-#endif
-#ifdef USE_CURVE25519_NACL
-#ifdef HAVE_CRYPTO_SCALARMULT_CURVE25519_H
-#include <crypto_scalarmult_curve25519.h>
-#elif defined(HAVE_NACL_CRYPTO_SCALARMULT_CURVE25519_H)
-#include <nacl/crypto_scalarmult_curve25519.h>
-#endif
-#endif /* defined(USE_CURVE25519_NACL) */
-
-static void pick_curve25519_basepoint_impl(void);
-
-/** This is set to 1 if we have an optimized Ed25519-based
- * implementation for multiplying a value by the basepoint; to 0 if we
- * don't, and to -1 if we haven't checked. */
-static int curve25519_use_ed = -1;
-
-/**
- * Helper function: call the most appropriate backend to compute the
- * scalar "secret" times the point "point". Store the result in
- * "output". Return 0 on success, negative on failure.
- **/
-STATIC int
-curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *point)
-{
- uint8_t bp[CURVE25519_PUBKEY_LEN];
- int r;
- memcpy(bp, point, CURVE25519_PUBKEY_LEN);
- /* Clear the high bit, in case our backend foolishly looks at it. */
- bp[31] &= 0x7f;
-#ifdef USE_CURVE25519_DONNA
- r = curve25519_donna(output, secret, bp);
-#elif defined(USE_CURVE25519_NACL)
- r = crypto_scalarmult_curve25519(output, secret, bp);
-#else
-#error "No implementation of curve25519 is available."
-#endif /* defined(USE_CURVE25519_DONNA) || ... */
- memwipe(bp, 0, sizeof(bp));
- return r;
-}
-
-/**
- * Helper function: Multiply the scalar "secret" by the Curve25519
- * basepoint (X=9), and store the result in "output". Return 0 on
- * success, -1 on failure.
- */
-STATIC int
-curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
-{
- int r = 0;
- if (BUG(curve25519_use_ed == -1)) {
- /* LCOV_EXCL_START - Only reached if we forgot to call curve25519_init() */
- pick_curve25519_basepoint_impl();
- /* LCOV_EXCL_STOP */
- }
-
- /* TODO: Someone should benchmark curved25519_scalarmult_basepoint versus
- * an optimized NaCl build to see which should be used when compiled with
- * NaCl available. I suspected that the ed25519 optimization always wins.
- */
- if (PREDICT_LIKELY(curve25519_use_ed == 1)) {
- curved25519_scalarmult_basepoint_donna(output, secret);
- r = 0;
- } else {
- static const uint8_t basepoint[32] = {9};
- r = curve25519_impl(output, secret, basepoint);
- }
- return r;
-}
-
-/**
- * Override the decision of whether to use the Ed25519-based basepoint
- * multiply function. Used for testing.
- */
-void
-curve25519_set_impl_params(int use_ed)
-{
- curve25519_use_ed = use_ed;
-}
-
-/* ==============================
- Part 2: Wrap curve25519_impl with some convenience types and functions.
- ============================== */
-
-/**
- * Return true iff a curve25519_public_key_t seems valid. (It's not necessary
- * to see if the point is on the curve, since the twist is also secure, but we
- * do need to make sure that it isn't the point at infinity.) */
-int
-curve25519_public_key_is_ok(const curve25519_public_key_t *key)
-{
- return !safe_mem_is_zero(key->public_key, CURVE25519_PUBKEY_LEN);
-}
-
-/**
- * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If
- * <b>extra_strong</b> is true, this key is possibly going to get used more
- * than once, so use a better-than-usual RNG. Return 0 on success, -1 on
- * failure.
- *
- * This function does not adjust the output of the RNG at all; the will caller
- * will need to clear or set the appropriate bits to make curve25519 work.
- */
-int
-curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
-{
- if (extra_strong)
- crypto_strongest_rand(out, CURVE25519_SECKEY_LEN);
- else
- crypto_rand((char*)out, CURVE25519_SECKEY_LEN);
-
- return 0;
-}
-
-/** Generate a new keypair and return the secret key. If <b>extra_strong</b>
- * is true, this key is possibly going to get used more than once, so
- * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
-int
-curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
- int extra_strong)
-{
- if (curve25519_rand_seckey_bytes(key_out->secret_key, extra_strong) < 0)
- return -1;
-
- key_out->secret_key[0] &= 248;
- key_out->secret_key[31] &= 127;
- key_out->secret_key[31] |= 64;
-
- return 0;
-}
-
-/**
- * Given a secret key in <b>seckey</b>, create the corresponding public
- * key in <b>key_out</b>.
- */
-void
-curve25519_public_key_generate(curve25519_public_key_t *key_out,
- const curve25519_secret_key_t *seckey)
-{
- curve25519_basepoint_impl(key_out->public_key, seckey->secret_key);
-}
-
-/**
- * Construct a new keypair in *<b>keypair_out</b>. If <b>extra_strong</b>
- * is true, this key is possibly going to get used more than once, so
- * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
-int
-curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
- int extra_strong)
-{
- if (curve25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
- return -1;
- curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
- return 0;
-}
-
-/** Store the keypair <b>keypair</b>, including its secret and public
- * parts, to the file <b>fname</b>. Use the string tag <b>tag</b> to
- * distinguish this from other Curve25519 keypairs. Return 0 on success,
- * -1 on failure.
- *
- * See crypto_write_tagged_contents_to_file() for more information on
- * the metaformat used for these keys.*/
-int
-curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
- const char *fname,
- const char *tag)
-{
- uint8_t contents[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
- int r;
-
- memcpy(contents, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN);
- memcpy(contents+CURVE25519_SECKEY_LEN,
- keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN);
-
- r = crypto_write_tagged_contents_to_file(fname,
- "c25519v1",
- tag,
- contents,
- sizeof(contents));
-
- memwipe(contents, 0, sizeof(contents));
- return r;
-}
-
-/** Read a curve25519 keypair from a file named <b>fname</b> created by
- * curve25519_keypair_write_to_file(). Store the keypair in
- * <b>keypair_out</b>, and the associated tag string in <b>tag_out</b>.
- * Return 0 on success, and -1 on failure. */
-int
-curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
- char **tag_out,
- const char *fname)
-{
- uint8_t content[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
- ssize_t len;
- int r = -1;
-
- len = crypto_read_tagged_contents_from_file(fname, "c25519v1", tag_out,
- content, sizeof(content));
- if (len != sizeof(content))
- goto end;
-
- /* Make sure that the public key matches the secret key */
- memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
- curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
- if (tor_memneq(keypair_out->pubkey.public_key,
- content + CURVE25519_SECKEY_LEN,
- CURVE25519_PUBKEY_LEN))
- goto end;
-
- r = 0;
-
- end:
- memwipe(content, 0, sizeof(content));
- if (r != 0) {
- memset(keypair_out, 0, sizeof(*keypair_out));
- tor_free(*tag_out);
- }
- return r;
-}
-
-/** Perform the curve25519 ECDH handshake with <b>skey</b> and <b>pkey</b>,
- * writing CURVE25519_OUTPUT_LEN bytes of output into <b>output</b>. */
-void
-curve25519_handshake(uint8_t *output,
- const curve25519_secret_key_t *skey,
- const curve25519_public_key_t *pkey)
-{
- curve25519_impl(output, skey->secret_key, pkey->public_key);
-}
-
-/** Check whether the ed25519-based curve25519 basepoint optimization seems to
- * be working. If so, return 0; otherwise return -1. */
-static int
-curve25519_basepoint_spot_check(void)
-{
- static const uint8_t alicesk[32] = {
- 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
- 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
- 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
- 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
- };
- static const uint8_t alicepk[32] = {
- 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
- 0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
- 0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
- 0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
- };
- const int loop_max=200;
- int save_use_ed = curve25519_use_ed;
- unsigned char e1[32] = { 5 };
- unsigned char e2[32] = { 5 };
- unsigned char x[32],y[32];
- int i;
- int r=0;
-
- /* Check the most basic possible sanity via the test secret/public key pair
- * used in "Cryptography in NaCl - 2. Secret keys and public keys". This
- * may catch catastrophic failures on systems where Curve25519 is expensive,
- * without requiring a ton of key generation.
- */
- curve25519_use_ed = 1;
- r |= curve25519_basepoint_impl(x, alicesk);
- if (fast_memneq(x, alicepk, 32))
- goto fail;
-
- /* Ok, the optimization appears to produce passable results, try a few more
- * values, maybe there's something subtle wrong.
- */
- for (i = 0; i < loop_max; ++i) {
- curve25519_use_ed = 0;
- r |= curve25519_basepoint_impl(x, e1);
- curve25519_use_ed = 1;
- r |= curve25519_basepoint_impl(y, e2);
- if (fast_memneq(x,y,32))
- goto fail;
- memcpy(e1, x, 32);
- memcpy(e2, x, 32);
- }
-
- goto end;
- // LCOV_EXCL_START -- we can only hit this code if there is a bug in our
- // curve25519-basepoint implementation.
- fail:
- r = -1;
- // LCOV_EXCL_STOP
- end:
- curve25519_use_ed = save_use_ed;
- return r;
-}
-
-/** Choose whether to use the ed25519-based curve25519-basepoint
- * implementation. */
-static void
-pick_curve25519_basepoint_impl(void)
-{
- curve25519_use_ed = 1;
-
- if (curve25519_basepoint_spot_check() == 0)
- return;
-
- /* LCOV_EXCL_START
- * only reachable if our basepoint implementation broken */
- log_warn(LD_BUG|LD_CRYPTO, "The ed25519-based curve25519 basepoint "
- "multiplication seems broken; using the curve25519 "
- "implementation.");
- curve25519_use_ed = 0;
- /* LCOV_EXCL_STOP */
-}
-
-/** Initialize the curve25519 implementations. This is necessary if you're
- * going to use them in a multithreaded setting, and not otherwise. */
-void
-curve25519_init(void)
-{
- pick_curve25519_basepoint_impl();
-}
-
diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h
deleted file mode 100644
index 8a5b9b2018..0000000000
--- a/src/common/crypto_curve25519.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Copyright (c) 2012-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_CURVE25519_H
-#define TOR_CRYPTO_CURVE25519_H
-
-#include "common/testsupport.h"
-#include "lib/cc/torint.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_openssl_mgt.h"
-
-/** Length of a curve25519 public key when encoded. */
-#define CURVE25519_PUBKEY_LEN 32
-/** Length of a curve25519 secret key when encoded. */
-#define CURVE25519_SECKEY_LEN 32
-/** Length of the result of a curve25519 handshake. */
-#define CURVE25519_OUTPUT_LEN 32
-
-/** Wrapper type for a curve25519 public key.
- *
- * (We define a separate type for these to make it less likely that we'll
- * mistake them for secret keys.)
- * */
-typedef struct curve25519_public_key_t {
- uint8_t public_key[CURVE25519_PUBKEY_LEN];
-} curve25519_public_key_t;
-
-/** Wrapper type for a curve25519 secret key
- *
- * (We define a separate type for these to make it less likely that we'll
- * mistake them for public keys.)
- **/
-typedef struct curve25519_secret_key_t {
- uint8_t secret_key[CURVE25519_SECKEY_LEN];
-} curve25519_secret_key_t;
-
-/** A paired public and private key for curve25519. **/
-typedef struct curve25519_keypair_t {
- curve25519_public_key_t pubkey;
- curve25519_secret_key_t seckey;
-} curve25519_keypair_t;
-
-/* These functions require that we actually know how to use curve25519 keys.
- * The other data structures and functions in this header let us parse them,
- * store them, and move them around.
- */
-
-int curve25519_public_key_is_ok(const curve25519_public_key_t *);
-
-int curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
- int extra_strong);
-void curve25519_public_key_generate(curve25519_public_key_t *key_out,
- const curve25519_secret_key_t *seckey);
-int curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
- int extra_strong);
-
-void curve25519_handshake(uint8_t *output,
- const curve25519_secret_key_t *,
- const curve25519_public_key_t *);
-
-int curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
- const char *fname,
- const char *tag);
-
-int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
- char **tag_out,
- const char *fname);
-
-int curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong);
-
-#ifdef CRYPTO_CURVE25519_PRIVATE
-STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
- const uint8_t *basepoint);
-
-STATIC int curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret);
-#endif /* defined(CRYPTO_CURVE25519_PRIVATE) */
-
-#define CURVE25519_BASE64_PADDED_LEN 44
-
-int curve25519_public_from_base64(curve25519_public_key_t *pkey,
- const char *input);
-int curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey);
-
-void curve25519_set_impl_params(int use_ed);
-void curve25519_init(void);
-
-#endif /* !defined(TOR_CRYPTO_CURVE25519_H) */
-
diff --git a/src/common/crypto_dh.c b/src/common/crypto_dh.c
deleted file mode 100644
index a9bd348ff4..0000000000
--- a/src/common/crypto_dh.c
+++ /dev/null
@@ -1,510 +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_dh.c
- * \brief Block of functions related with DH utilities and operations.
- **/
-
-#include "common/compat_openssl.h"
-#include "common/crypto_dh.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_hkdf.h"
-#include "common/crypto_util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/dh.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/bn.h>
-
-#include "common/torlog.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.
- */
-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.
- */
-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;
-}
-
-/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
- * modulus. */
-void
-crypto_set_tls_dh_prime(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:
-#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 \>= DH_BYTES.
- */
-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 DH_BYTES (%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))
- 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;
-}
-
-/** 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
- * <b>secret_bytes_out</b> bytes of shared key material and write them
- * to <b>secret_out</b>. Return the number of bytes generated on success,
- * or -1 on failure.
- *
- * (We generate key material by computing
- * SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
- * where || is concatenation.)
- */
-ssize_t
-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;
- }
- 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.");
- goto error;
- }
- secret_len = result;
- if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
- (uint8_t*)secret_out, secret_bytes_out)<0)
- goto error;
- secret_len = secret_bytes_out;
-
- goto done;
- 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);
- }
- 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);
-}
-
-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;
-}
diff --git a/src/common/crypto_dh.h b/src/common/crypto_dh.h
deleted file mode 100644
index 1e77acc011..0000000000
--- a/src/common/crypto_dh.h
+++ /dev/null
@@ -1,49 +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_dh.h
- *
- * \brief Headers for crypto_dh.c
- **/
-
-#ifndef TOR_CRYPTO_DH_H
-#define TOR_CRYPTO_DH_H
-
-#include "common/util.h"
-
-/** Length of our DH keys. */
-#define DH_BYTES (1024/8)
-
-typedef struct crypto_dh_t crypto_dh_t;
-
-/* Key negotiation */
-#define DH_TYPE_CIRCUIT 1
-#define DH_TYPE_REND 2
-#define DH_TYPE_TLS 3
-void crypto_set_tls_dh_prime(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);
-int crypto_dh_generate_public(crypto_dh_t *dh);
-int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
- size_t pubkey_out_len);
-ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
- const char *pubkey, size_t pubkey_len,
- char *secret_out, size_t secret_out_len);
-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 */
-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);
-
-#endif /* !defined(TOR_CRYPTO_DH_H) */
-
diff --git a/src/common/crypto_digest.c b/src/common/crypto_digest.c
deleted file mode 100644
index 708fbf9be6..0000000000
--- a/src/common/crypto_digest.c
+++ /dev/null
@@ -1,583 +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_digest.c
- * \brief Block of functions related with digest and xof utilities and
- * operations.
- **/
-
-#include "common/container.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_openssl_mgt.h"
-#include "common/crypto_util.h"
-#include "common/torlog.h"
-
-#include "keccak-tiny/keccak-tiny.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-/* Crypto digest functions */
-
-/** Compute the SHA1 digest of the <b>len</b> bytes on data stored in
- * <b>m</b>. Write the DIGEST_LEN byte result into <b>digest</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-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)
- return -1;
- return 0;
-}
-
-/** Compute a 256-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
- * using the algorithm <b>algorithm</b>. Write the DIGEST_LEN256-byte result
- * into <b>digest</b>. Return 0 on success, -1 on failure. */
-int
-crypto_digest256(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm)
-{
- tor_assert(m);
- tor_assert(digest);
- tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
-
- int ret = 0;
- if (algorithm == DIGEST_SHA256)
- ret = (SHA256((const uint8_t*)m,len,(uint8_t*)digest) != NULL);
- else
- ret = (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
- > -1);
-
- if (!ret)
- return -1;
- return 0;
-}
-
-/** Compute a 512-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
- * using the algorithm <b>algorithm</b>. Write the DIGEST_LEN512-byte result
- * into <b>digest</b>. Return 0 on success, -1 on failure. */
-int
-crypto_digest512(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm)
-{
- tor_assert(m);
- tor_assert(digest);
- tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
-
- int ret = 0;
- if (algorithm == DIGEST_SHA512)
- ret = (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
- != NULL);
- else
- ret = (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
- > -1);
-
- if (!ret)
- return -1;
- return 0;
-}
-
-/** Set the common_digests_t in <b>ds_out</b> to contain every digest on the
- * <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on
- * success, -1 on failure. */
-int
-crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len)
-{
- tor_assert(ds_out);
- memset(ds_out, 0, sizeof(*ds_out));
- if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0)
- return -1;
- if (crypto_digest256(ds_out->d[DIGEST_SHA256], m, len, DIGEST_SHA256) < 0)
- return -1;
-
- return 0;
-}
-
-/** Return the name of an algorithm, as used in directory documents. */
-const char *
-crypto_digest_algorithm_get_name(digest_algorithm_t alg)
-{
- switch (alg) {
- case DIGEST_SHA1:
- return "sha1";
- case DIGEST_SHA256:
- return "sha256";
- case DIGEST_SHA512:
- return "sha512";
- case DIGEST_SHA3_256:
- return "sha3-256";
- case DIGEST_SHA3_512:
- return "sha3-512";
- // LCOV_EXCL_START
- default:
- tor_fragile_assert();
- return "??unknown_digest??";
- // LCOV_EXCL_STOP
- }
-}
-
-/** Given the name of a digest algorithm, return its integer value, or -1 if
- * the name is not recognized. */
-int
-crypto_digest_algorithm_parse_name(const char *name)
-{
- if (!strcmp(name, "sha1"))
- return DIGEST_SHA1;
- else if (!strcmp(name, "sha256"))
- return DIGEST_SHA256;
- else if (!strcmp(name, "sha512"))
- return DIGEST_SHA512;
- else if (!strcmp(name, "sha3-256"))
- return DIGEST_SHA3_256;
- else if (!strcmp(name, "sha3-512"))
- return DIGEST_SHA3_512;
- else
- return -1;
-}
-
-/** Given an algorithm, return the digest length in bytes. */
-size_t
-crypto_digest_algorithm_get_length(digest_algorithm_t alg)
-{
- switch (alg) {
- case DIGEST_SHA1:
- return DIGEST_LEN;
- case DIGEST_SHA256:
- return DIGEST256_LEN;
- case DIGEST_SHA512:
- return DIGEST512_LEN;
- case DIGEST_SHA3_256:
- return DIGEST256_LEN;
- case DIGEST_SHA3_512:
- return DIGEST512_LEN;
- default:
- tor_assert(0); // LCOV_EXCL_LINE
- return 0; /* Unreachable */ // LCOV_EXCL_LINE
- }
-}
-
-/** Intermediate information about the digest of a stream of data. */
-struct crypto_digest_t {
- digest_algorithm_t algorithm; /**< Which algorithm is in use? */
- /** State for the digest we're using. Only one member of the
- * union is usable, depending on the value of <b>algorithm</b>. Note also
- * that space for other members might not even be allocated!
- */
- union {
- SHA_CTX sha1; /**< state for SHA1 */
- SHA256_CTX sha2; /**< state for SHA256 */
- SHA512_CTX sha512; /**< state for SHA512 */
- keccak_state sha3; /**< state for SHA3-[256,512] */
- } d;
-};
-
-#ifdef TOR_UNIT_TESTS
-
-digest_algorithm_t
-crypto_digest_get_algorithm(crypto_digest_t *digest)
-{
- tor_assert(digest);
-
- return digest->algorithm;
-}
-
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/**
- * Return the number of bytes we need to malloc in order to get a
- * crypto_digest_t for <b>alg</b>, or the number of bytes we need to wipe
- * when we free one.
- */
-static size_t
-crypto_digest_alloc_bytes(digest_algorithm_t alg)
-{
- /* Helper: returns the number of bytes in the 'f' field of 'st' */
-#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
- /* Gives the length of crypto_digest_t through the end of the field 'd' */
-#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
- STRUCT_FIELD_SIZE(crypto_digest_t, f))
- switch (alg) {
- 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);
- case DIGEST_SHA3_256:
- case DIGEST_SHA3_512:
- return END_OF_FIELD(d.sha3);
- default:
- tor_assert(0); // LCOV_EXCL_LINE
- return 0; // LCOV_EXCL_LINE
- }
-#undef END_OF_FIELD
-#undef STRUCT_FIELD_SIZE
-}
-
-/**
- * Internal function: create and return a new digest object for 'algorithm'.
- * Does not typecheck the algorithm.
- */
-static crypto_digest_t *
-crypto_digest_new_internal(digest_algorithm_t algorithm)
-{
- crypto_digest_t *r = tor_malloc(crypto_digest_alloc_bytes(algorithm));
- r->algorithm = algorithm;
-
- switch (algorithm)
- {
- case DIGEST_SHA1:
- SHA1_Init(&r->d.sha1);
- break;
- case DIGEST_SHA256:
- SHA256_Init(&r->d.sha2);
- break;
- case DIGEST_SHA512:
- SHA512_Init(&r->d.sha512);
- break;
- case DIGEST_SHA3_256:
- keccak_digest_init(&r->d.sha3, 256);
- break;
- case DIGEST_SHA3_512:
- keccak_digest_init(&r->d.sha3, 512);
- break;
- default:
- tor_assert_unreached();
- }
-
- return r;
-}
-
-/** Allocate and return a new digest object to compute SHA1 digests.
- */
-crypto_digest_t *
-crypto_digest_new(void)
-{
- return crypto_digest_new_internal(DIGEST_SHA1);
-}
-
-/** Allocate and return a new digest object to compute 256-bit digests
- * using <b>algorithm</b>.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest256_new`
- * C_RUST_COUPLED: `crypto::digest::Sha256::default`
- */
-crypto_digest_t *
-crypto_digest256_new(digest_algorithm_t algorithm)
-{
- tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
- return crypto_digest_new_internal(algorithm);
-}
-
-/** Allocate and return a new digest object to compute 512-bit digests
- * using <b>algorithm</b>. */
-crypto_digest_t *
-crypto_digest512_new(digest_algorithm_t algorithm)
-{
- tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
- return crypto_digest_new_internal(algorithm);
-}
-
-/** Deallocate a digest object.
- */
-void
-crypto_digest_free_(crypto_digest_t *digest)
-{
- if (!digest)
- return;
- size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- memwipe(digest, 0, bytes);
- tor_free(digest);
-}
-
-/** Add <b>len</b> bytes from <b>data</b> to the digest object.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_add_bytess`
- * C_RUST_COUPLED: `crypto::digest::Sha256::process`
- */
-void
-crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
- size_t len)
-{
- tor_assert(digest);
- tor_assert(data);
- /* Using the SHA*_*() calls directly means we don't support doing
- * SHA in hardware. But so far the delay of getting the question
- * to the hardware, and hearing the answer, is likely higher than
- * just doing it ourselves. Hashes are fast.
- */
- switch (digest->algorithm) {
- case DIGEST_SHA1:
- SHA1_Update(&digest->d.sha1, (void*)data, len);
- break;
- case DIGEST_SHA256:
- SHA256_Update(&digest->d.sha2, (void*)data, len);
- break;
- case DIGEST_SHA512:
- SHA512_Update(&digest->d.sha512, (void*)data, len);
- break;
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
- case DIGEST_SHA3_512:
- keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
- break;
- default:
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- break;
- /* LCOV_EXCL_STOP */
- }
-}
-
-/** Compute the hash of the data that has been passed to the digest
- * object; write the first out_len bytes of the result to <b>out</b>.
- * <b>out_len</b> must be \<= DIGEST512_LEN.
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_get_digest`
- * C_RUST_COUPLED: `impl digest::FixedOutput for Sha256`
- */
-void
-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));
-
- /* The SHA-3 code handles copying into a temporary ctx, and also can handle
- * short output buffers by truncating appropriately. */
- if (digest->algorithm == DIGEST_SHA3_256 ||
- digest->algorithm == DIGEST_SHA3_512) {
- keccak_digest_sum(&digest->d.sha3, (uint8_t *)out, out_len);
- return;
- }
-
- const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
- /* memcpy into a temporary ctx, since SHA*_Final clears the context */
- memcpy(&tmpenv, digest, alloc_bytes);
- switch (digest->algorithm) {
- case DIGEST_SHA1:
- SHA1_Final(r, &tmpenv.d.sha1);
- break;
- case DIGEST_SHA256:
- SHA256_Final(r, &tmpenv.d.sha2);
- break;
- case DIGEST_SHA512:
- SHA512_Final(r, &tmpenv.d.sha512);
- break;
-//LCOV_EXCL_START
- case DIGEST_SHA3_256: /* FALLSTHROUGH */
- case DIGEST_SHA3_512:
- default:
- log_warn(LD_BUG, "Handling unexpected algorithm %d", digest->algorithm);
- /* This is fatal, because it should never happen. */
- tor_assert_unreached();
- break;
-//LCOV_EXCL_STOP
- }
- memcpy(out, r, out_len);
- memwipe(r, 0, sizeof(r));
-}
-
-/** Allocate and return a new digest object with the same state as
- * <b>digest</b>
- *
- * C_RUST_COUPLED: `external::crypto_digest::crypto_digest_dup`
- * C_RUST_COUPLED: `impl Clone for crypto::digest::Sha256`
- */
-crypto_digest_t *
-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);
-}
-
-/** Temporarily save the state of <b>digest</b> in <b>checkpoint</b>.
- * Asserts that <b>digest</b> is a SHA1 digest object.
- */
-void
-crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
- const crypto_digest_t *digest)
-{
- const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- tor_assert(bytes <= sizeof(checkpoint->mem));
- memcpy(checkpoint->mem, digest, bytes);
-}
-
-/** Restore the state of <b>digest</b> from <b>checkpoint</b>.
- * Asserts that <b>digest</b> is a SHA1 digest object. Requires that the
- * state was previously stored with crypto_digest_checkpoint() */
-void
-crypto_digest_restore(crypto_digest_t *digest,
- const crypto_digest_checkpoint_t *checkpoint)
-{
- const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
- memcpy(digest, checkpoint->mem, bytes);
-}
-
-/** Replace the state of the digest object <b>into</b> with the state
- * of the digest object <b>from</b>. Requires that 'into' and 'from'
- * have the same digest type.
- */
-void
-crypto_digest_assign(crypto_digest_t *into,
- const crypto_digest_t *from)
-{
- tor_assert(into);
- tor_assert(from);
- tor_assert(into->algorithm == from->algorithm);
- const size_t alloc_bytes = crypto_digest_alloc_bytes(from->algorithm);
- memcpy(into,from,alloc_bytes);
-}
-
-/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
- * at <b>digest_out</b> to the hash of the concatenation of those strings,
- * plus the optional string <b>append</b>, computed with the algorithm
- * <b>alg</b>.
- * <b>out_len</b> must be \<= DIGEST512_LEN. */
-void
-crypto_digest_smartlist(char *digest_out, size_t len_out,
- const smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg)
-{
- crypto_digest_smartlist_prefix(digest_out, len_out, NULL, lst, append, alg);
-}
-
-/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
- * at <b>digest_out</b> to the hash of the concatenation of: the
- * optional string <b>prepend</b>, those strings,
- * and the optional string <b>append</b>, computed with the algorithm
- * <b>alg</b>.
- * <b>len_out</b> must be \<= DIGEST512_LEN. */
-void
-crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
- const char *prepend,
- const smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg)
-{
- crypto_digest_t *d = crypto_digest_new_internal(alg);
- if (prepend)
- crypto_digest_add_bytes(d, prepend, strlen(prepend));
- SMARTLIST_FOREACH(lst, const char *, cp,
- crypto_digest_add_bytes(d, cp, strlen(cp)));
- if (append)
- crypto_digest_add_bytes(d, append, strlen(append));
- crypto_digest_get_digest(d, digest_out, len_out);
- crypto_digest_free(d);
-}
-
-/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
- * the <b>key</b> of length <b>key_len</b>. Store the DIGEST256_LEN-byte
- * result in <b>hmac_out</b>. Asserts on failure.
- */
-void
-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);
- rv = HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
- (unsigned char*)hmac_out, NULL);
- tor_assert(rv);
-}
-
-/** Compute a MAC using SHA3-256 of <b>msg_len</b> bytes in <b>msg</b> using a
- * <b>key</b> of length <b>key_len</b> and a <b>salt</b> of length
- * <b>salt_len</b>. Store the result of <b>len_out</b> bytes in in
- * <b>mac_out</b>. This function can't fail. */
-void
-crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
- const uint8_t *key, size_t key_len,
- const uint8_t *msg, size_t msg_len)
-{
- crypto_digest_t *digest;
-
- const uint64_t key_len_netorder = tor_htonll(key_len);
-
- tor_assert(mac_out);
- tor_assert(key);
- tor_assert(msg);
-
- digest = crypto_digest256_new(DIGEST_SHA3_256);
-
- /* Order matters here that is any subsystem using this function should
- * expect this very precise ordering in the MAC construction. */
- crypto_digest_add_bytes(digest, (const char *) &key_len_netorder,
- sizeof(key_len_netorder));
- crypto_digest_add_bytes(digest, (const char *) key, key_len);
- crypto_digest_add_bytes(digest, (const char *) msg, msg_len);
- crypto_digest_get_digest(digest, (char *) mac_out, len_out);
- crypto_digest_free(digest);
-}
-
-/* xof functions */
-
-/** Internal state for a eXtendable-Output Function (XOF). */
-struct crypto_xof_t {
- keccak_state s;
-};
-
-/** Allocate a new XOF object backed by SHAKE-256. The security level
- * provided is a function of the length of the output used. Read and
- * understand FIPS-202 A.2 "Additional Consideration for Extendable-Output
- * Functions" before using this construct.
- */
-crypto_xof_t *
-crypto_xof_new(void)
-{
- crypto_xof_t *xof;
- xof = tor_malloc(sizeof(crypto_xof_t));
- keccak_xof_init(&xof->s, 256);
- return xof;
-}
-
-/** Absorb bytes into a XOF object. Must not be called after a call to
- * crypto_xof_squeeze_bytes() for the same instance, and will assert
- * if attempted.
- */
-void
-crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len)
-{
- int i = keccak_xof_absorb(&xof->s, data, len);
- tor_assert(i == 0);
-}
-
-/** Squeeze bytes out of a XOF object. Calling this routine will render
- * the XOF instance ineligible to absorb further data.
- */
-void
-crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len)
-{
- int i = keccak_xof_squeeze(&xof->s, out, len);
- tor_assert(i == 0);
-}
-
-/** Cleanse and deallocate a XOF object. */
-void
-crypto_xof_free_(crypto_xof_t *xof)
-{
- if (!xof)
- return;
- memwipe(xof, 0, sizeof(crypto_xof_t));
- tor_free(xof);
-}
-
diff --git a/src/common/crypto_digest.h b/src/common/crypto_digest.h
deleted file mode 100644
index 96ac038507..0000000000
--- a/src/common/crypto_digest.h
+++ /dev/null
@@ -1,136 +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_digest.h
- *
- * \brief Headers for crypto_digest.c
- **/
-
-#ifndef TOR_CRYPTO_DIGEST_H
-#define TOR_CRYPTO_DIGEST_H
-
-#include <stdio.h>
-
-#include "common/container.h"
-#include "lib/cc/torint.h"
-
-/** Length of the output of our message digest. */
-#define DIGEST_LEN 20
-/** Length of the output of our second (improved) message digests. (For now
- * this is just sha256, but it could be any other 256-bit digest.) */
-#define DIGEST256_LEN 32
-/** Length of the output of our 64-bit optimized message digests (SHA512). */
-#define DIGEST512_LEN 64
-
-/** Length of a sha1 message digest when encoded in base32 with trailing =
- * signs removed. */
-#define BASE32_DIGEST_LEN 32
-/** Length of a sha1 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST_LEN 27
-/** Length of a sha256 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST256_LEN 43
-/** Length of a sha512 message digest when encoded in base64 with trailing =
- * signs removed. */
-#define BASE64_DIGEST512_LEN 86
-
-/** Length of hex encoding of SHA1 digest, not including final NUL. */
-#define HEX_DIGEST_LEN 40
-/** Length of hex encoding of SHA256 digest, not including final NUL. */
-#define HEX_DIGEST256_LEN 64
-/** Length of hex encoding of SHA512 digest, not including final NUL. */
-#define HEX_DIGEST512_LEN 128
-
-typedef enum {
- DIGEST_SHA1 = 0,
- DIGEST_SHA256 = 1,
- DIGEST_SHA512 = 2,
- DIGEST_SHA3_256 = 3,
- DIGEST_SHA3_512 = 4,
-} digest_algorithm_t;
-#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
-#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
-
-#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512)
-/** Structure used to temporarily save the a digest object. Only implemented
- * for SHA1 digest for now. */
-typedef struct crypto_digest_checkpoint_t {
- uint8_t mem[DIGEST_CHECKPOINT_BYTES];
-} crypto_digest_checkpoint_t;
-
-/** A set of all the digests we commonly compute, taken on a single
- * string. Any digests that are shorter than 512 bits are right-padded
- * with 0 bits.
- *
- * Note that this representation wastes 44 bytes for the SHA1 case, so
- * don't use it for anything where we need to allocate a whole bunch at
- * once.
- **/
-typedef struct {
- char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
-} common_digests_t;
-
-typedef struct crypto_digest_t crypto_digest_t;
-typedef struct crypto_xof_t crypto_xof_t;
-
-/* SHA-1 and other digests */
-int crypto_digest(char *digest, const char *m, size_t len);
-int crypto_digest256(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm);
-int crypto_digest512(char *digest, const char *m, size_t len,
- digest_algorithm_t algorithm);
-int crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len);
-void crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
- const char *prepend,
- const struct smartlist_t *lst,
- const char *append,
- digest_algorithm_t alg);
-void crypto_digest_smartlist(char *digest_out, size_t len_out,
- const struct smartlist_t *lst, const char *append,
- digest_algorithm_t alg);
-const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg);
-size_t crypto_digest_algorithm_get_length(digest_algorithm_t alg);
-int crypto_digest_algorithm_parse_name(const char *name);
-crypto_digest_t *crypto_digest_new(void);
-crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
-crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
-void crypto_digest_free_(crypto_digest_t *digest);
-#define crypto_digest_free(d) \
- FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
-void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
- size_t len);
-void crypto_digest_get_digest(crypto_digest_t *digest,
- char *out, size_t out_len);
-crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest);
-void crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
- const crypto_digest_t *digest);
-void crypto_digest_restore(crypto_digest_t *digest,
- const crypto_digest_checkpoint_t *checkpoint);
-void crypto_digest_assign(crypto_digest_t *into,
- const crypto_digest_t *from);
-void crypto_hmac_sha256(char *hmac_out,
- const char *key, size_t key_len,
- const char *msg, size_t msg_len);
-void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
- const uint8_t *key, size_t key_len,
- const uint8_t *msg, size_t msg_len);
-
-/* xof functions*/
-crypto_xof_t *crypto_xof_new(void);
-void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
-void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
-void crypto_xof_free_(crypto_xof_t *xof);
-#define crypto_xof_free(xof) \
- FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
-
-#ifdef TOR_UNIT_TESTS
-digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
-#endif
-
-#endif /* !defined(TOR_CRYPTO_DIGEST_H) */
-
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
deleted file mode 100644
index b0b954796c..0000000000
--- a/src/common/crypto_ed25519.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/* Copyright (c) 2013-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_ed25519.c
- *
- * \brief Wrapper code for an ed25519 implementation.
- *
- * Ed25519 is a Schnorr signature on a Twisted Edwards curve, defined
- * by Dan Bernstein. For more information, see https://ed25519.cr.yp.to/
- *
- * This module wraps our choice of Ed25519 backend, and provides a few
- * convenience functions for checking and generating signatures. It also
- * provides Tor-specific tools for key blinding and for converting Ed25519
- * keys to and from the corresponding Curve25519 keys.
- */
-
-#define CRYPTO_ED25519_PRIVATE
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include "common/crypto_curve25519.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_ed25519.h"
-#include "common/crypto_format.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_util.h"
-#include "common/torlog.h"
-#include "common/util.h"
-#include "common/util_format.h"
-
-#include "ed25519/ref10/ed25519_ref10.h"
-#include "ed25519/donna/ed25519_donna_tor.h"
-
-static void pick_ed25519_impl(void);
-
-/** An Ed25519 implementation, as a set of function pointers. */
-typedef struct {
- int (*selftest)(void);
-
- int (*seckey)(unsigned char *);
- int (*seckey_expand)(unsigned char *, const unsigned char *);
- int (*pubkey)(unsigned char *, const unsigned char *);
- int (*keygen)(unsigned char *, unsigned char *);
-
- int (*open)(const unsigned char *, const unsigned char *, size_t, const
- unsigned char *);
- int (*sign)(unsigned char *, const unsigned char *, size_t,
- const unsigned char *, const unsigned char *);
- int (*open_batch)(const unsigned char **, size_t *, const unsigned char **,
- const unsigned char **, size_t, int *);
-
- int (*blind_secret_key)(unsigned char *, const unsigned char *,
- const unsigned char *);
- int (*blind_public_key)(unsigned char *, const unsigned char *,
- const unsigned char *);
-
- int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
- int);
-
- int (*ed25519_scalarmult_with_group_order)(unsigned char *,
- const unsigned char *);
-} ed25519_impl_t;
-
-/** The Ref10 Ed25519 implementation. This one is pure C and lightly
- * optimized. */
-static const ed25519_impl_t impl_ref10 = {
- NULL,
-
- ed25519_ref10_seckey,
- ed25519_ref10_seckey_expand,
- ed25519_ref10_pubkey,
- ed25519_ref10_keygen,
-
- ed25519_ref10_open,
- ed25519_ref10_sign,
- NULL,
-
- ed25519_ref10_blind_secret_key,
- ed25519_ref10_blind_public_key,
-
- ed25519_ref10_pubkey_from_curve25519_pubkey,
- ed25519_ref10_scalarmult_with_group_order,
-};
-
-/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
- * mostly C. The C still tends to be heavily platform-specific. */
-static const ed25519_impl_t impl_donna = {
- ed25519_donna_selftest,
-
- ed25519_donna_seckey,
- ed25519_donna_seckey_expand,
- ed25519_donna_pubkey,
- ed25519_donna_keygen,
-
- ed25519_donna_open,
- ed25519_donna_sign,
- ed25519_sign_open_batch_donna,
-
- ed25519_donna_blind_secret_key,
- ed25519_donna_blind_public_key,
-
- ed25519_donna_pubkey_from_curve25519_pubkey,
- ed25519_donna_scalarmult_with_group_order,
-};
-
-/** Which Ed25519 implementation are we using? NULL if we haven't decided
- * yet. */
-static const ed25519_impl_t *ed25519_impl = NULL;
-
-/** Helper: Return our chosen Ed25519 implementation.
- *
- * This should only be called after we've picked an implementation, but
- * it _does_ recover if you forget this.
- **/
-static inline const ed25519_impl_t *
-get_ed_impl(void)
-{
- if (BUG(ed25519_impl == NULL)) {
- pick_ed25519_impl(); // LCOV_EXCL_LINE - We always call ed25519_init().
- }
- return ed25519_impl;
-}
-
-#ifdef TOR_UNIT_TESTS
-/** For testing: used to remember our actual choice of Ed25519
- * implementation */
-static const ed25519_impl_t *saved_ed25519_impl = NULL;
-/** For testing: Use the Ed25519 implementation called <b>name</b> until
- * crypto_ed25519_testing_restore_impl is called. Recognized names are
- * "donna" and "ref10". */
-void
-crypto_ed25519_testing_force_impl(const char *name)
-{
- tor_assert(saved_ed25519_impl == NULL);
- saved_ed25519_impl = ed25519_impl;
- if (! strcmp(name, "donna")) {
- ed25519_impl = &impl_donna;
- } else {
- tor_assert(!strcmp(name, "ref10"));
- ed25519_impl = &impl_ref10;
- }
-}
-/** For testing: go back to whatever Ed25519 implementation we had picked
- * before crypto_ed25519_testing_force_impl was called.
- */
-void
-crypto_ed25519_testing_restore_impl(void)
-{
- ed25519_impl = saved_ed25519_impl;
- saved_ed25519_impl = NULL;
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/**
- * Initialize a new ed25519 secret key in <b>seckey_out</b>. If
- * <b>extra_strong</b>, take the RNG inputs directly from the operating
- * system. Return 0 on success, -1 on failure.
- */
-int
-ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
- int extra_strong)
-{
- int r;
- uint8_t seed[32];
- if (extra_strong)
- crypto_strongest_rand(seed, sizeof(seed));
- else
- crypto_rand((char*)seed, sizeof(seed));
-
- r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed);
- memwipe(seed, 0, sizeof(seed));
-
- return r < 0 ? -1 : 0;
-}
-
-/**
- * Given a 32-byte random seed in <b>seed</b>, expand it into an ed25519
- * secret key in <b>seckey_out</b>. Return 0 on success, -1 on failure.
- */
-int
-ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
- const uint8_t *seed)
-{
- if (get_ed_impl()->seckey_expand(seckey_out->seckey, seed) < 0)
- return -1;
- return 0;
-}
-
-/**
- * Given a secret key in <b>seckey</b>, expand it into an
- * ed25519 public key. Return 0 on success, -1 on failure.
- */
-int
-ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
- const ed25519_secret_key_t *seckey)
-{
- if (get_ed_impl()->pubkey(pubkey_out->pubkey, seckey->seckey) < 0)
- return -1;
- return 0;
-}
-
-/** Generate a new ed25519 keypair in <b>keypair_out</b>. If
- * <b>extra_strong</b> is set, try to mix some system entropy into the key
- * generation process. Return 0 on success, -1 on failure. */
-int
-ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
-{
- if (ed25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
- return -1;
- if (ed25519_public_key_generate(&keypair_out->pubkey,
- &keypair_out->seckey)<0)
- return -1;
- return 0;
-}
-
-/** Return true iff 'pubkey' is set to zero (eg to indicate that it is not
- * set). */
-int
-ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
-{
- return tor_mem_is_zero((char*)pubkey->pubkey, ED25519_PUBKEY_LEN);
-}
-
-/* Return a heap-allocated array that contains <b>msg</b> prefixed by the
- * string <b>prefix_str</b>. Set <b>final_msg_len_out</b> to the size of the
- * final array. If an error occurred, return NULL. It's the responsibility of
- * the caller to free the returned array. */
-static uint8_t *
-get_prefixed_msg(const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- size_t *final_msg_len_out)
-{
- size_t prefixed_msg_len, prefix_len;
- uint8_t *prefixed_msg;
-
- tor_assert(prefix_str);
- tor_assert(final_msg_len_out);
-
- prefix_len = strlen(prefix_str);
-
- /* msg_len + strlen(prefix_str) must not overflow. */
- if (msg_len > SIZE_T_CEILING - prefix_len) {
- return NULL;
- }
-
- prefixed_msg_len = msg_len + prefix_len;
- prefixed_msg = tor_malloc_zero(prefixed_msg_len);
-
- memcpy(prefixed_msg, prefix_str, prefix_len);
- memcpy(prefixed_msg + prefix_len, msg, msg_len);
-
- *final_msg_len_out = prefixed_msg_len;
- return prefixed_msg;
-}
-
-/**
- * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message
- * <b>msg</b>, using the secret and public key in <b>keypair</b>.
- *
- * Return 0 if we successfully signed the message, otherwise return -1.
- */
-int
-ed25519_sign(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const ed25519_keypair_t *keypair)
-{
- if (get_ed_impl()->sign(signature_out->sig, msg, len,
- keypair->seckey.seckey,
- keypair->pubkey.pubkey) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-/**
- * Like ed25519_sign(), but also prefix <b>msg</b> with <b>prefix_str</b>
- * before signing. <b>prefix_str</b> must be a NUL-terminated string.
- */
-MOCK_IMPL(int,
-ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair))
-{
- int retval;
- size_t prefixed_msg_len;
- uint8_t *prefixed_msg;
-
- tor_assert(prefix_str);
-
- prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
- &prefixed_msg_len);
- if (BUG(!prefixed_msg)) {
- /* LCOV_EXCL_START -- only possible when the message and prefix are
- * ridiculously huge */
- log_warn(LD_GENERAL, "Failed to get prefixed msg.");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- retval = ed25519_sign(signature_out,
- prefixed_msg, prefixed_msg_len,
- keypair);
- tor_free(prefixed_msg);
-
- return retval;
-}
-
-/**
- * Check whether if <b>signature</b> is a valid signature for the
- * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>.
- *
- * Return 0 if the signature is valid; -1 if it isn't.
- */
-MOCK_IMPL(int,
-ed25519_checksig,(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const ed25519_public_key_t *pubkey))
-{
- return
- get_ed_impl()->open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0;
-}
-
-/**
- * Like ed2519_checksig(), but also prefix <b>msg</b> with <b>prefix_str</b>
- * before verifying signature. <b>prefix_str</b> must be a NUL-terminated
- * string.
- */
-int
-ed25519_checksig_prefixed(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- const ed25519_public_key_t *pubkey)
-{
- int retval;
- size_t prefixed_msg_len;
- uint8_t *prefixed_msg;
-
- prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
- &prefixed_msg_len);
- if (BUG(!prefixed_msg)) {
- /* LCOV_EXCL_START -- only possible when the message and prefix are
- * ridiculously huge */
- log_warn(LD_GENERAL, "Failed to get prefixed msg.");
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- retval = ed25519_checksig(signature,
- prefixed_msg, prefixed_msg_len,
- pubkey);
- tor_free(prefixed_msg);
-
- return retval;
-}
-
-/** Validate every signature among those in <b>checkable</b>, which contains
- * exactly <b>n_checkable</b> elements. If <b>okay_out</b> is non-NULL, set
- * the i'th element of <b>okay_out</b> to 1 if the i'th element of
- * <b>checkable</b> is valid, and to 0 otherwise. Return 0 if every signature
- * was valid. Otherwise return -N, where N is the number of invalid
- * signatures.
- */
-MOCK_IMPL(int,
-ed25519_checksig_batch,(int *okay_out,
- const ed25519_checkable_t *checkable,
- int n_checkable))
-{
- int i, res;
- const ed25519_impl_t *impl = get_ed_impl();
-
- if (impl->open_batch == NULL) {
- /* No batch verification implementation available, fake it by checking the
- * each signature individually.
- */
- res = 0;
- for (i = 0; i < n_checkable; ++i) {
- const ed25519_checkable_t *ch = &checkable[i];
- int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
- if (r < 0)
- --res;
- if (okay_out)
- okay_out[i] = (r == 0);
- }
- } else {
- /* ed25519-donna style batch verification available.
- *
- * Theoretically, this should only be called if n_checkable >= 3, since
- * that's the threshold where the batch verification actually kicks in,
- * but the only difference is a few mallocs/frees.
- */
- const uint8_t **ms;
- size_t *lens;
- const uint8_t **pks;
- const uint8_t **sigs;
- int *oks;
- int all_ok;
-
- ms = tor_calloc(n_checkable, sizeof(uint8_t*));
- lens = tor_calloc(n_checkable, sizeof(size_t));
- pks = tor_calloc(n_checkable, sizeof(uint8_t*));
- sigs = tor_calloc(n_checkable, sizeof(uint8_t*));
- oks = okay_out ? okay_out : tor_calloc(n_checkable, sizeof(int));
-
- for (i = 0; i < n_checkable; ++i) {
- ms[i] = checkable[i].msg;
- lens[i] = checkable[i].len;
- pks[i] = checkable[i].pubkey->pubkey;
- sigs[i] = checkable[i].signature.sig;
- oks[i] = 0;
- }
-
- res = 0;
- all_ok = impl->open_batch(ms, lens, pks, sigs, n_checkable, oks);
- for (i = 0; i < n_checkable; ++i) {
- if (!oks[i])
- --res;
- }
- /* XXX: For now sanity check oks with the return value. Once we have
- * more confidence in the code, if `all_ok == 0` we can skip iterating
- * over oks since all the signatures were found to be valid.
- */
- tor_assert(((res == 0) && !all_ok) || ((res < 0) && all_ok));
-
- tor_free(ms);
- tor_free(lens);
- tor_free(pks);
- tor_free(sigs);
- if (! okay_out)
- tor_free(oks);
- }
-
- return res;
-}
-
-/**
- * Given a curve25519 keypair in <b>inp</b>, generate a corresponding
- * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the
- * sign bit of the X coordinate of the ed25519 key.
- *
- * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING
- * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228. In particular, it's probably
- * not a great idea to use it to sign attacker-supplied anything.
- */
-int
-ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
- int *signbit_out,
- const curve25519_keypair_t *inp)
-{
- const char string[] = "Derive high part of ed25519 key from curve25519 key";
- ed25519_public_key_t pubkey_check;
- crypto_digest_t *ctx;
- uint8_t sha512_output[DIGEST512_LEN];
-
- memcpy(out->seckey.seckey, inp->seckey.secret_key, 32);
-
- ctx = crypto_digest512_new(DIGEST_SHA512);
- crypto_digest_add_bytes(ctx, (const char*)out->seckey.seckey, 32);
- crypto_digest_add_bytes(ctx, (const char*)string, sizeof(string));
- crypto_digest_get_digest(ctx, (char *)sha512_output, sizeof(sha512_output));
- crypto_digest_free(ctx);
- memcpy(out->seckey.seckey + 32, sha512_output, 32);
-
- ed25519_public_key_generate(&out->pubkey, &out->seckey);
-
- *signbit_out = out->pubkey.pubkey[31] >> 7;
-
- ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey,
- *signbit_out);
-
- tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
-
- memwipe(&pubkey_check, 0, sizeof(pubkey_check));
- memwipe(sha512_output, 0, sizeof(sha512_output));
-
- return 0;
-}
-
-/**
- * Given a curve25519 public key and sign bit of X coordinate of the ed25519
- * public key, generate the corresponding ed25519 public key.
- */
-int
-ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
- const curve25519_public_key_t *pubkey_in,
- int signbit)
-{
- return get_ed_impl()->pubkey_from_curve25519_pubkey(pubkey->pubkey,
- pubkey_in->public_key,
- signbit);
-}
-
-/**
- * Given an ed25519 keypair in <b>inp</b>, generate a corresponding
- * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input
- * in 'param'.
- *
- * Tor uses key blinding for the "next-generation" hidden services design:
- * service descriptors are encrypted with a key derived from the service's
- * long-term public key, and then signed with (and stored at a position
- * indexed by) a short-term key derived by blinding the long-term keys.
- *
- * Return 0 if blinding was successful, else return -1. */
-int
-ed25519_keypair_blind(ed25519_keypair_t *out,
- const ed25519_keypair_t *inp,
- const uint8_t *param)
-{
- ed25519_public_key_t pubkey_check;
-
- get_ed_impl()->blind_secret_key(out->seckey.seckey,
- inp->seckey.seckey, param);
-
- if (ed25519_public_blind(&pubkey_check, &inp->pubkey, param) < 0) {
- return -1;
- }
- ed25519_public_key_generate(&out->pubkey, &out->seckey);
-
- tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
-
- memwipe(&pubkey_check, 0, sizeof(pubkey_check));
-
- return 0;
-}
-
-/**
- * Given an ed25519 public key in <b>inp</b>, generate a corresponding blinded
- * public key in <b>out</b>, blinded with the 32-byte parameter in
- * <b>param</b>. Return 0 on success, -1 on railure.
- */
-int
-ed25519_public_blind(ed25519_public_key_t *out,
- const ed25519_public_key_t *inp,
- const uint8_t *param)
-{
- return get_ed_impl()->blind_public_key(out->pubkey, inp->pubkey, param);
-}
-
-/**
- * Store seckey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
- const char *filename,
- const char *tag)
-{
- return crypto_write_tagged_contents_to_file(filename,
- "ed25519v1-secret",
- tag,
- seckey->seckey,
- sizeof(seckey->seckey));
-}
-
-/**
- * Read seckey unencrypted from <b>filename</b>, storing it into
- * <b>seckey_out</b>. Set *<b>tag_out</b> to the tag it was marked with.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
- char **tag_out,
- const char *filename)
-{
- ssize_t len;
-
- len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-secret",
- tag_out, seckey_out->seckey,
- sizeof(seckey_out->seckey));
- if (len == sizeof(seckey_out->seckey)) {
- return 0;
- } else if (len >= 0) {
- errno = EINVAL;
- }
-
- tor_free(*tag_out);
- return -1;
-}
-
-/**
- * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
- const char *filename,
- const char *tag)
-{
- return crypto_write_tagged_contents_to_file(filename,
- "ed25519v1-public",
- tag,
- pubkey->pubkey,
- sizeof(pubkey->pubkey));
-}
-
-/**
- * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
- char **tag_out,
- const char *filename)
-{
- ssize_t len;
-
- len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-public",
- tag_out, pubkey_out->pubkey,
- sizeof(pubkey_out->pubkey));
- if (len == sizeof(pubkey_out->pubkey)) {
- return 0;
- } else if (len >= 0) {
- errno = EINVAL;
- }
-
- tor_free(*tag_out);
- return -1;
-}
-
-/** Release all storage held for <b>kp</b>. */
-void
-ed25519_keypair_free_(ed25519_keypair_t *kp)
-{
- if (! kp)
- return;
-
- memwipe(kp, 0, sizeof(*kp));
- tor_free(kp);
-}
-
-/** Return true iff <b>key1</b> and <b>key2</b> are the same public key. */
-int
-ed25519_pubkey_eq(const ed25519_public_key_t *key1,
- const ed25519_public_key_t *key2)
-{
- tor_assert(key1);
- tor_assert(key2);
- return tor_memeq(key1->pubkey, key2->pubkey, ED25519_PUBKEY_LEN);
-}
-
-/**
- * Set <b>dest</b> to contain the same key as <b>src</b>.
- */
-void
-ed25519_pubkey_copy(ed25519_public_key_t *dest,
- const ed25519_public_key_t *src)
-{
- tor_assert(dest);
- tor_assert(src);
- memcpy(dest, src, sizeof(ed25519_public_key_t));
-}
-
-/** Check whether the given Ed25519 implementation seems to be working.
- * If so, return 0; otherwise return -1. */
-MOCK_IMPL(STATIC int,
-ed25519_impl_spot_check,(void))
-{
- static const uint8_t alicesk[32] = {
- 0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,
- 0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,
- 0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,
- 0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7
- };
- static const uint8_t alicepk[32] = {
- 0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,
- 0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,
- 0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,
- 0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25
- };
- static const uint8_t alicemsg[2] = { 0xaf, 0x82 };
- static const uint8_t alicesig[64] = {
- 0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,
- 0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,
- 0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,
- 0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,
- 0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,
- 0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,
- 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,
- 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a
- };
- const ed25519_impl_t *impl = get_ed_impl();
- uint8_t sk[ED25519_SECKEY_LEN];
- uint8_t pk[ED25519_PUBKEY_LEN];
- uint8_t sig[ED25519_SIG_LEN];
- int r = 0;
-
- /* Some implementations (eg: The modified Ed25519-donna) have handy self-test
- * code that sanity-checks the internals. If present, use that to screen out
- * catastrophic errors like massive compiler failure.
- */
- if (impl->selftest && impl->selftest() != 0)
- goto fail;
-
- /* Validate results versus known answer tests. People really should be
- * running "make test" instead of relying on this, but it's better than
- * nothing.
- *
- * Test vectors taken from "EdDSA & Ed25519 - 6. Test Vectors for Ed25519
- * (TEST3)" (draft-josefsson-eddsa-ed25519-03).
- */
-
- /* Key expansion, public key derivation. */
- if (impl->seckey_expand(sk, alicesk) < 0)
- goto fail;
- if (impl->pubkey(pk, sk) < 0)
- goto fail;
- if (fast_memneq(pk, alicepk, ED25519_PUBKEY_LEN))
- goto fail;
-
- /* Signing, verification. */
- if (impl->sign(sig, alicemsg, sizeof(alicemsg), sk, pk) < 0)
- return -1;
- if (fast_memneq(sig, alicesig, ED25519_SIG_LEN))
- return -1;
- if (impl->open(sig, alicemsg, sizeof(alicemsg), pk) < 0)
- return -1;
-
- /* XXX/yawning: Someone that's more paranoid than I am, can write "Assume
- * ref0 is canonical, and fuzz impl against it" if they want, but I doubt
- * that will catch anything that the known answer tests won't.
- */
- goto end;
-
- // LCOV_EXCL_START -- We can only reach this if our ed25519 implementation is
- // broken.
- fail:
- r = -1;
- // LCOV_EXCL_STOP
- end:
- return r;
-}
-
-/** Force the Ed25519 implementation to a given one, without sanity checking
- * the output. Used for testing.
- */
-void
-ed25519_set_impl_params(int use_donna)
-{
- if (use_donna)
- ed25519_impl = &impl_donna;
- else
- ed25519_impl = &impl_ref10;
-}
-
-/** Choose whether to use the Ed25519-donna implementation. */
-static void
-pick_ed25519_impl(void)
-{
- ed25519_impl = &impl_donna;
-
- if (ed25519_impl_spot_check() == 0)
- return;
-
- /* LCOV_EXCL_START
- * unreachable unless ed25519_donna is broken */
- log_warn(LD_CRYPTO, "The Ed25519-donna implementation seems broken; using "
- "the ref10 implementation.");
- ed25519_impl = &impl_ref10;
- /* LCOV_EXCL_STOP */
-}
-
-/* Initialize the Ed25519 implementation. This is necessary if you're
- * going to use them in a multithreaded setting, and not otherwise. */
-void
-ed25519_init(void)
-{
- pick_ed25519_impl();
-}
-
-/* Return true if <b>point</b> is the identity element of the ed25519 group. */
-static int
-ed25519_point_is_identity_element(const uint8_t *point)
-{
- /* The identity element in ed25159 is the point with coordinates (0,1). */
- static const uint8_t ed25519_identity[32] = {
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
- return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
-}
-
-/** Validate <b>pubkey</b> to ensure that it has no torsion component.
- * Return 0 if <b>pubkey</b> is valid, else return -1. */
-int
-ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
-{
- uint8_t result[32] = {9};
-
- /* First check that we were not given the identity element */
- if (ed25519_point_is_identity_element(pubkey->pubkey)) {
- log_warn(LD_CRYPTO, "ed25519 pubkey is the identity");
- return -1;
- }
-
- /* For any point on the curve, doing l*point should give the identity element
- * (where l is the group order). Do the computation and check that the
- * identity element is returned. */
- if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
- pubkey->pubkey) < 0) {
- log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed");
- return -1;
- }
-
- if (!ed25519_point_is_identity_element(result)) {
- log_warn(LD_CRYPTO, "ed25519 validation failed");
- return -1;
- }
-
- return 0;
-}
-
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
deleted file mode 100644
index 981b0dce28..0000000000
--- a/src/common/crypto_ed25519.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* Copyright (c) 2012-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_CRYPTO_ED25519_H
-#define TOR_CRYPTO_ED25519_H
-
-#include "common/testsupport.h"
-#include "lib/cc/torint.h"
-#include "common/crypto_curve25519.h"
-#include "common/util.h"
-
-#define ED25519_PUBKEY_LEN 32
-#define ED25519_SECKEY_LEN 64
-#define ED25519_SECKEY_SEED_LEN 32
-#define ED25519_SIG_LEN 64
-
-/** An Ed25519 signature. */
-typedef struct {
- uint8_t sig[ED25519_SIG_LEN];
-} ed25519_signature_t;
-
-/** An Ed25519 public key */
-typedef struct {
- uint8_t pubkey[ED25519_PUBKEY_LEN];
-} ed25519_public_key_t;
-
-/** An Ed25519 secret key */
-typedef struct {
- /** Note that we store secret keys in an expanded format that doesn't match
- * the format from standard ed25519. Ed25519 stores a 32-byte value k and
- * expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
- * of the base point, and second 32 bytes as an input to a hash function
- * for deriving r. But because we implement key blinding, we need to store
- * keys in the 64-byte expanded form. */
- uint8_t seckey[ED25519_SECKEY_LEN];
-} ed25519_secret_key_t;
-
-/** An Ed25519 keypair. */
-typedef struct {
- ed25519_public_key_t pubkey;
- ed25519_secret_key_t seckey;
-} ed25519_keypair_t;
-
-int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
- int extra_strong);
-int ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
- const uint8_t *seed);
-
-int ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
- const ed25519_secret_key_t *seckey);
-int ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong);
-int ed25519_sign(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const ed25519_keypair_t *key);
-MOCK_DECL(int,ed25519_checksig,(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const ed25519_public_key_t *pubkey));
-
-MOCK_DECL(int,
-ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair));
-
-int
-ed25519_checksig_prefixed(const ed25519_signature_t *signature,
- const uint8_t *msg, size_t len,
- const char *prefix_str,
- const ed25519_public_key_t *pubkey);
-
-int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey);
-
-/**
- * A collection of information necessary to check an Ed25519 signature. Used
- * for batch verification.
- */
-typedef struct {
- /** The public key that supposedly generated the signature. */
- const ed25519_public_key_t *pubkey;
- /** The signature to check. */
- ed25519_signature_t signature;
- /** The message that the signature is supposed to have been applied to. */
- const uint8_t *msg;
- /** The length of the message. */
- size_t len;
-} ed25519_checkable_t;
-
-MOCK_DECL(int, ed25519_checksig_batch,(int *okay_out,
- const ed25519_checkable_t *checkable,
- int n_checkable));
-
-int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
- int *signbit_out,
- const curve25519_keypair_t *inp);
-
-int ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
- const curve25519_public_key_t *pubkey_in,
- int signbit);
-int ed25519_keypair_blind(ed25519_keypair_t *out,
- const ed25519_keypair_t *inp,
- const uint8_t *param);
-int ed25519_public_blind(ed25519_public_key_t *out,
- const ed25519_public_key_t *inp,
- const uint8_t *param);
-
-/* XXXX read encrypted, write encrypted. */
-
-int ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
- const char *filename,
- const char *tag);
-int ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
- char **tag_out,
- const char *filename);
-int ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
- const char *filename,
- const char *tag);
-int ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
- char **tag_out,
- const char *filename);
-
-void ed25519_keypair_free_(ed25519_keypair_t *kp);
-#define ed25519_keypair_free(kp) \
- FREE_AND_NULL(ed25519_keypair_t, ed25519_keypair_free_, (kp))
-
-int ed25519_pubkey_eq(const ed25519_public_key_t *key1,
- const ed25519_public_key_t *key2);
-void ed25519_pubkey_copy(ed25519_public_key_t *dest,
- const ed25519_public_key_t *src);
-
-void ed25519_set_impl_params(int use_donna);
-void ed25519_init(void);
-
-int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey);
-
-#ifdef TOR_UNIT_TESTS
-void crypto_ed25519_testing_force_impl(const char *name);
-void crypto_ed25519_testing_restore_impl(void);
-#endif
-
-#ifdef CRYPTO_ED25519_PRIVATE
-MOCK_DECL(STATIC int, ed25519_impl_spot_check, (void));
-#endif
-
-#endif /* !defined(TOR_CRYPTO_ED25519_H) */
-
diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c
deleted file mode 100644
index 6245b70ccb..0000000000
--- a/src/common/crypto_format.c
+++ /dev/null
@@ -1,299 +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_format.c
- *
- * \brief Formatting and parsing code for crypto-related data structures.
- */
-
-#include "orconfig.h"
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "common/container.h"
-#include "common/crypto_curve25519.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_ed25519.h"
-#include "common/crypto_format.h"
-#include "common/crypto_util.h"
-#include "common/util.h"
-#include "common/util_format.h"
-#include "common/torlog.h"
-
-/** Write the <b>datalen</b> bytes from <b>data</b> to the file named
- * <b>fname</b> in the tagged-data format. This format contains a
- * 32-byte header, followed by the data itself. The header is the
- * NUL-padded string "== <b>typestring</b>: <b>tag</b> ==". The length
- * of <b>typestring</b> and <b>tag</b> must therefore be no more than
- * 24.
- **/
-int
-crypto_write_tagged_contents_to_file(const char *fname,
- const char *typestring,
- const char *tag,
- const uint8_t *data,
- size_t datalen)
-{
- char header[32];
- smartlist_t *chunks = smartlist_new();
- sized_chunk_t ch0, ch1;
- int r = -1;
-
- memset(header, 0, sizeof(header));
- if (tor_snprintf(header, sizeof(header),
- "== %s: %s ==", typestring, tag) < 0)
- goto end;
- ch0.bytes = header;
- ch0.len = 32;
- ch1.bytes = (const char*) data;
- ch1.len = datalen;
- smartlist_add(chunks, &ch0);
- smartlist_add(chunks, &ch1);
-
- r = write_chunks_to_file(fname, chunks, 1, 0);
-
- end:
- smartlist_free(chunks);
- return r;
-}
-
-/** Read a tagged-data file from <b>fname</b> into the
- * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the
- * typestring matches <b>typestring</b>; store the tag into a newly allocated
- * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of
- * data on success. Preserves the errno from reading the file. */
-ssize_t
-crypto_read_tagged_contents_from_file(const char *fname,
- const char *typestring,
- char **tag_out,
- uint8_t *data_out,
- ssize_t data_out_len)
-{
- char prefix[33];
- char *content = NULL;
- struct stat st;
- ssize_t r = -1;
- size_t st_size = 0;
- int saved_errno = 0;
-
- *tag_out = NULL;
- st.st_size = 0;
- content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
- if (! content) {
- saved_errno = errno;
- goto end;
- }
- if (st.st_size < 32 || st.st_size > 32 + data_out_len) {
- saved_errno = EINVAL;
- goto end;
- }
- st_size = (size_t)st.st_size;
-
- memcpy(prefix, content, 32);
- prefix[32] = 0;
- /* Check type, extract tag. */
- if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") ||
- ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) {
- saved_errno = EINVAL;
- goto end;
- }
-
- if (strcmpstart(prefix+3, typestring) ||
- 3+strlen(typestring) >= 32 ||
- strcmpstart(prefix+3+strlen(typestring), ": ")) {
- saved_errno = EINVAL;
- goto end;
- }
-
- *tag_out = tor_strndup(prefix+5+strlen(typestring),
- strlen(prefix)-8-strlen(typestring));
-
- memcpy(data_out, content+32, st_size-32);
- r = st_size - 32;
-
- end:
- if (content)
- memwipe(content, 0, st_size);
- tor_free(content);
- if (saved_errno)
- errno = saved_errno;
- return r;
-}
-
-/** Encode <b>pkey</b> as a base64-encoded string, without trailing "="
- * characters, in the buffer <b>output</b>, which must have at least
- * CURVE25519_BASE64_PADDED_LEN+1 bytes available. Return 0 on success, -1 on
- * failure. */
-int
-curve25519_public_to_base64(char *output,
- const curve25519_public_key_t *pkey)
-{
- char buf[128];
- base64_encode(buf, sizeof(buf),
- (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN, 0);
- buf[CURVE25519_BASE64_PADDED_LEN] = '\0';
- memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1);
- return 0;
-}
-
-/** Try to decode a base64-encoded curve25519 public key from <b>input</b>
- * into the object at <b>pkey</b>. Return 0 on success, -1 on failure.
- * Accepts keys with or without a trailing "=". */
-int
-curve25519_public_from_base64(curve25519_public_key_t *pkey,
- const char *input)
-{
- size_t len = strlen(input);
- if (len == CURVE25519_BASE64_PADDED_LEN - 1) {
- /* not padded */
- return digest256_from_base64((char*)pkey->public_key, input);
- } else if (len == CURVE25519_BASE64_PADDED_LEN) {
- char buf[128];
- if (base64_decode(buf, sizeof(buf), input, len) != CURVE25519_PUBKEY_LEN)
- return -1;
- memcpy(pkey->public_key, buf, CURVE25519_PUBKEY_LEN);
- return 0;
- } else {
- return -1;
- }
-}
-
-/** For logging convenience: Convert <b>pkey</b> to a statically allocated
- * base64 string and return it. Not threadsafe. Format not meant to be
- * computer-readable; it may change in the future. Subsequent calls invalidate
- * previous returns. */
-const char *
-ed25519_fmt(const ed25519_public_key_t *pkey)
-{
- static char formatted[ED25519_BASE64_LEN+1];
- if (pkey) {
- if (ed25519_public_key_is_zero(pkey)) {
- strlcpy(formatted, "<unset>", sizeof(formatted));
- } else {
- int r = ed25519_public_to_base64(formatted, pkey);
- tor_assert(!r);
- }
- } else {
- strlcpy(formatted, "<null>", sizeof(formatted));
- }
- return formatted;
-}
-
-/** Try to decode the string <b>input</b> into an ed25519 public key. On
- * success, store the value in <b>pkey</b> and return 0. Otherwise return
- * -1. */
-int
-ed25519_public_from_base64(ed25519_public_key_t *pkey,
- const char *input)
-{
- return digest256_from_base64((char*)pkey->pubkey, input);
-}
-
-/** Encode the public key <b>pkey</b> into the buffer at <b>output</b>,
- * which must have space for ED25519_BASE64_LEN bytes of encoded key,
- * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
- */
-int
-ed25519_public_to_base64(char *output,
- const ed25519_public_key_t *pkey)
-{
- return digest256_to_base64(output, (const char *)pkey->pubkey);
-}
-
-/** Encode the signature <b>sig</b> into the buffer at <b>output</b>,
- * which must have space for ED25519_SIG_BASE64_LEN bytes of encoded signature,
- * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
- */
-int
-ed25519_signature_to_base64(char *output,
- const ed25519_signature_t *sig)
-{
- char buf[256];
- int n = base64_encode_nopad(buf, sizeof(buf), sig->sig, ED25519_SIG_LEN);
- tor_assert(n == ED25519_SIG_BASE64_LEN);
- memcpy(output, buf, ED25519_SIG_BASE64_LEN+1);
- return 0;
-}
-
-/** Try to decode the string <b>input</b> into an ed25519 signature. On
- * success, store the value in <b>sig</b> and return 0. Otherwise return
- * -1. */
-int
-ed25519_signature_from_base64(ed25519_signature_t *sig,
- const char *input)
-{
-
- if (strlen(input) != ED25519_SIG_BASE64_LEN)
- return -1;
- char buf[ED25519_SIG_BASE64_LEN+3];
- memcpy(buf, input, ED25519_SIG_BASE64_LEN);
- buf[ED25519_SIG_BASE64_LEN+0] = '=';
- buf[ED25519_SIG_BASE64_LEN+1] = '=';
- buf[ED25519_SIG_BASE64_LEN+2] = 0;
- char decoded[128];
- int n = base64_decode(decoded, sizeof(decoded), buf, strlen(buf));
- if (n < 0 || n != ED25519_SIG_LEN)
- return -1;
- memcpy(sig->sig, decoded, ED25519_SIG_LEN);
-
- return 0;
-}
-
-/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing =
- * characters, and store the nul-terminated result in the first
- * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest_to_base64(char *d64, const char *digest)
-{
- char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST_LEN, 0);
- buf[BASE64_DIGEST_LEN] = '\0';
- memcpy(d64, buf, BASE64_DIGEST_LEN+1);
- return 0;
-}
-
-/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
- * trailing newline or = characters), decode it and store the result in the
- * first DIGEST_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest_from_base64(char *digest, const char *d64)
-{
- if (base64_decode(digest, DIGEST_LEN, d64, strlen(d64)) == DIGEST_LEN)
- return 0;
- else
- return -1;
-}
-
-/** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the
- * trailing = characters, and store the nul-terminated result in the first
- * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
- /* XXXX unify with crypto_format.c code */
-int
-digest256_to_base64(char *d64, const char *digest)
-{
- char buf[256];
- base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN, 0);
- buf[BASE64_DIGEST256_LEN] = '\0';
- memcpy(d64, buf, BASE64_DIGEST256_LEN+1);
- return 0;
-}
-
-/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without
- * trailing newline or = characters), decode it and store the result in the
- * first DIGEST256_LEN bytes at <b>digest</b>. */
-/* XXXX unify with crypto_format.c code */
-int
-digest256_from_base64(char *digest, const char *d64)
-{
- if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN)
- return 0;
- else
- return -1;
-}
-
diff --git a/src/common/crypto_format.h b/src/common/crypto_format.h
deleted file mode 100644
index 47f52b94b7..0000000000
--- a/src/common/crypto_format.h
+++ /dev/null
@@ -1,47 +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 */
-
-#ifndef TOR_CRYPTO_FORMAT_H
-#define TOR_CRYPTO_FORMAT_H
-
-#include "common/testsupport.h"
-#include "lib/cc/torint.h"
-#include "common/crypto_ed25519.h"
-
-int crypto_write_tagged_contents_to_file(const char *fname,
- const char *typestring,
- const char *tag,
- const uint8_t *data,
- size_t datalen);
-
-ssize_t crypto_read_tagged_contents_from_file(const char *fname,
- const char *typestring,
- char **tag_out,
- uint8_t *data_out,
- ssize_t data_out_len);
-
-#define ED25519_BASE64_LEN 43
-int ed25519_public_from_base64(ed25519_public_key_t *pkey,
- const char *input);
-int ed25519_public_to_base64(char *output,
- const ed25519_public_key_t *pkey);
-const char *ed25519_fmt(const ed25519_public_key_t *pkey);
-
-/* XXXX move these to crypto_format.h */
-#define ED25519_SIG_BASE64_LEN 86
-
-int ed25519_signature_from_base64(ed25519_signature_t *sig,
- const char *input);
-int ed25519_signature_to_base64(char *output,
- const ed25519_signature_t *sig);
-
-int digest_to_base64(char *d64, const char *digest);
-int digest_from_base64(char *digest, const char *d64);
-int digest256_to_base64(char *d64, const char *digest);
-int digest256_from_base64(char *digest, const char *d64);
-
-#endif /* !defined(TOR_CRYPTO_FORMAT_H) */
-
diff --git a/src/common/crypto_hkdf.c b/src/common/crypto_hkdf.c
deleted file mode 100644
index 8dc15b6ffb..0000000000
--- a/src/common/crypto_hkdf.c
+++ /dev/null
@@ -1,193 +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_hkdf.c
- * \brief Block of functions related with HKDF utilities and operations.
- **/
-
-#include "common/crypto_hkdf.h"
-#include "common/crypto_util.h"
-#include "common/crypto_digest.h"
-
-#include "common/crypto_openssl_mgt.h"
-#include <openssl/opensslv.h>
-
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
-#define HAVE_OPENSSL_HKDF 1
-#include <openssl/kdf.h>
-#endif
-
-/** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
- * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
- * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
- * H(K | [00]) | H(K | [01]) | ....
- *
- * This is the key expansion algorithm used in the "TAP" circuit extension
- * mechanism; it shouldn't be used for new protocols.
- *
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- int i, r = -1;
- uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
- uint8_t digest[DIGEST_LEN];
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST_LEN*256);
-
- memcpy(tmp, key_in, key_in_len);
- for (cp = key_out, i=0; cp < key_out+key_out_len;
- ++i, cp += DIGEST_LEN) {
- tmp[key_in_len] = i;
- if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
- goto exit;
- memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
- }
-
- r = 0;
- exit:
- memwipe(tmp, 0, key_in_len+1);
- tor_free(tmp);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-#ifdef HAVE_OPENSSL_HKDF
-/**
- * Perform RFC5869 HKDF computation using OpenSSL (only to be called from
- * crypto_expand_key_material_rfc5869_sha256_openssl). Note that OpenSSL
- * requires input key to be nonempty and salt length to be equal or less
- * than 1024.
- */
-static int
-crypto_expand_key_material_rfc5869_sha256_openssl(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- int r;
- EVP_PKEY_CTX *evp_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
- tor_assert(evp_pkey_ctx);
- tor_assert(key_in_len != 0);
- tor_assert(salt_in_len <= 1024);
-
- r = EVP_PKEY_derive_init(evp_pkey_ctx);
- tor_assert(r == 1);
-
- r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
- tor_assert(r == 1);
-
- r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
- tor_assert(r == 1);
-
- r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
- tor_assert(r == 1);
-
- r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
- tor_assert(r == 1);
-
- r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
- tor_assert(r == 1);
-
- EVP_PKEY_CTX_free(evp_pkey_ctx);
- return 0;
-}
-
-#else
-
-/**
- * Perform RFC5869 HKDF computation using our own legacy implementation.
- * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
- */
-static int
-crypto_expand_key_material_rfc5869_sha256_legacy(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- uint8_t prk[DIGEST256_LEN];
- uint8_t tmp[DIGEST256_LEN + 128 + 1];
- uint8_t mac[DIGEST256_LEN];
- int i;
- uint8_t *outp;
- size_t tmp_len;
-
- crypto_hmac_sha256((char*)prk,
- (const char*)salt_in, salt_in_len,
- (const char*)key_in, key_in_len);
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST256_LEN * 256);
- tor_assert(info_in_len <= 128);
- memset(tmp, 0, sizeof(tmp));
- outp = key_out;
- i = 1;
-
- while (key_out_len) {
- size_t n;
- if (i > 1) {
- memcpy(tmp, mac, DIGEST256_LEN);
- memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
- tmp[DIGEST256_LEN+info_in_len] = i;
- tmp_len = DIGEST256_LEN + info_in_len + 1;
- } else {
- memcpy(tmp, info_in, info_in_len);
- tmp[info_in_len] = i;
- tmp_len = info_in_len + 1;
- }
- crypto_hmac_sha256((char*)mac,
- (const char*)prk, DIGEST256_LEN,
- (const char*)tmp, tmp_len);
- n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
- memcpy(outp, mac, n);
- key_out_len -= n;
- outp += n;
- ++i;
- }
-
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(mac, 0, sizeof(mac));
- return 0;
-}
-#endif
-
-/** Expand some secret key material according to RFC5869, using SHA256 as the
- * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
- * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
- * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
- * and "info" parameters respectively. On success, write <b>key_out_len</b>
- * bytes to <b>key_out</b> and return 0. Assert on failure.
- */
-int
-crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len)
-{
- tor_assert(key_in);
- tor_assert(key_in_len > 0);
-
-#ifdef HAVE_OPENSSL_HKDF
- return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
- key_in_len, salt_in,
- salt_in_len, info_in,
- info_in_len,
- key_out, key_out_len);
-#else
- return crypto_expand_key_material_rfc5869_sha256_legacy(key_in,
- key_in_len, salt_in,
- salt_in_len, info_in,
- info_in_len,
- key_out, key_out_len);
-#endif
-}
diff --git a/src/common/crypto_hkdf.h b/src/common/crypto_hkdf.h
deleted file mode 100644
index 784f4bbbe4..0000000000
--- a/src/common/crypto_hkdf.h
+++ /dev/null
@@ -1,28 +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_hkdf.h
- *
- * \brief Headers for crypto_hkdf.h
- **/
-
-#ifndef TOR_CRYPTO_HKDF_H
-#define TOR_CRYPTO_HKDF_H
-
-#include "common/util.h"
-
-int crypto_expand_key_material_TAP(const uint8_t *key_in,
- size_t key_in_len,
- uint8_t *key_out, size_t key_out_len);
-int crypto_expand_key_material_rfc5869_sha256(
- const uint8_t *key_in, size_t key_in_len,
- const uint8_t *salt_in, size_t salt_in_len,
- const uint8_t *info_in, size_t info_in_len,
- uint8_t *key_out, size_t key_out_len);
-
-#endif /* !defined(TOR_CRYPTO_HKDF_H) */
-
diff --git a/src/common/crypto_openssl_mgt.c b/src/common/crypto_openssl_mgt.c
deleted file mode 100644
index 8acb9cdf1c..0000000000
--- a/src/common/crypto_openssl_mgt.c
+++ /dev/null
@@ -1,161 +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_openssl.c
- *
- * \brief Block of functions related to operations from OpenSSL.
- **/
-
-#include "common/compat_openssl.h"
-#include "common/crypto_openssl_mgt.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/rand.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-#include <openssl/crypto.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#ifndef NEW_THREAD_API
-/** A number of preallocated mutexes for use by OpenSSL. */
-static tor_mutex_t **openssl_mutexes_ = NULL;
-/** How many mutexes have we allocated for use by OpenSSL? */
-static int n_openssl_mutexes_ = 0;
-#endif /* !defined(NEW_THREAD_API) */
-
-/** Declare STATIC functions */
-STATIC char * parse_openssl_version_str(const char *raw_version);
-#ifndef NEW_THREAD_API
-STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
-STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
-#endif
-
-/* Returns a trimmed and human-readable version of an openssl version string
-* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
-* May 2012' and this will parse them into a form similar to '1.0.0b' */
-STATIC char *
-parse_openssl_version_str(const char *raw_version)
-{
- const char *end_of_version = NULL;
- /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
- trim that down. */
- if (!strcmpstart(raw_version, "OpenSSL ")) {
- raw_version += strlen("OpenSSL ");
- end_of_version = strchr(raw_version, ' ');
- }
-
- if (end_of_version)
- return tor_strndup(raw_version,
- end_of_version-raw_version);
- else
- return tor_strdup(raw_version);
-}
-
-static char *crypto_openssl_version_str = NULL;
-/* Return a human-readable version of the run-time openssl version number. */
-const char *
-crypto_openssl_get_version_str(void)
-{
- if (crypto_openssl_version_str == NULL) {
- const char *raw_version = OpenSSL_version(OPENSSL_VERSION);
- crypto_openssl_version_str = parse_openssl_version_str(raw_version);
- }
- return crypto_openssl_version_str;
-}
-
-static char *crypto_openssl_header_version_str = NULL;
-/* Return a human-readable version of the compile-time openssl version
-* number. */
-const char *
-crypto_openssl_get_header_version_str(void)
-{
- if (crypto_openssl_header_version_str == NULL) {
- crypto_openssl_header_version_str =
- parse_openssl_version_str(OPENSSL_VERSION_TEXT);
- }
- return crypto_openssl_header_version_str;
-}
-
-#ifndef OPENSSL_THREADS
-#error OpenSSL has been built without thread support. Tor requires an \
- OpenSSL library with thread support enabled.
-#endif
-
-#ifndef NEW_THREAD_API
-/** Helper: OpenSSL uses this callback to manipulate mutexes. */
-STATIC void
-openssl_locking_cb_(int mode, int n, const char *file, int line)
-{
- (void)file;
- (void)line;
- if (!openssl_mutexes_)
- /* This is not a really good fix for the
- * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
- * it can't hurt. */
- return;
- if (mode & CRYPTO_LOCK)
- tor_mutex_acquire(openssl_mutexes_[n]);
- else
- tor_mutex_release(openssl_mutexes_[n]);
-}
-
-STATIC void
-tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
-{
- CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
-}
-#endif /* !defined(NEW_THREAD_API) */
-
-/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
- * multithreaded. Returns 0. */
-int
-setup_openssl_threading(void)
-{
-#ifndef NEW_THREAD_API
- int i;
- int n = CRYPTO_num_locks();
- n_openssl_mutexes_ = n;
- openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
- for (i=0; i < n; ++i)
- openssl_mutexes_[i] = tor_mutex_new();
- CRYPTO_set_locking_callback(openssl_locking_cb_);
- CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
-#endif /* !defined(NEW_THREAD_API) */
- return 0;
-}
-
-/** free OpenSSL variables */
-void
-crypto_openssl_free_all(void)
-{
- tor_free(crypto_openssl_version_str);
- tor_free(crypto_openssl_header_version_str);
-
-#ifndef NEW_THREAD_API
- if (n_openssl_mutexes_) {
- int n = n_openssl_mutexes_;
- tor_mutex_t **ms = openssl_mutexes_;
- int i;
- openssl_mutexes_ = NULL;
- n_openssl_mutexes_ = 0;
- for (i=0;i<n;++i) {
- tor_mutex_free(ms[i]);
- }
- tor_free(ms);
- }
-#endif /* !defined(NEW_THREAD_API) */
-}
-
diff --git a/src/common/crypto_openssl_mgt.h b/src/common/crypto_openssl_mgt.h
deleted file mode 100644
index e3f5531b7d..0000000000
--- a/src/common/crypto_openssl_mgt.h
+++ /dev/null
@@ -1,85 +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_openssl.h
- *
- * \brief Headers for crypto_openssl.c
- **/
-
-#ifndef TOR_CRYPTO_OPENSSL_H
-#define TOR_CRYPTO_OPENSSL_H
-
-#include <stdio.h>
-#include "common/util.h"
-
-#include <openssl/engine.h>
-
-/*
- Macro to create an arbitrary OpenSSL version number as used by
- OPENSSL_VERSION_NUMBER or SSLeay(), since the actual numbers are a bit hard
- to read.
-
- Don't use this directly, instead use one of the other OPENSSL_V macros
- below.
-
- The format is: 4 bits major, 8 bits minor, 8 bits fix, 8 bits patch, 4 bit
- status.
- */
-#define OPENSSL_VER(a,b,c,d,e) \
- (((a)<<28) | \
- ((b)<<20) | \
- ((c)<<12) | \
- ((d)<< 4) | \
- (e))
-/** An openssl release number. For example, OPENSSL_V(0,9,8,'j') is the
- * version for the released version of 0.9.8j */
-#define OPENSSL_V(a,b,c,d) \
- OPENSSL_VER((a),(b),(c),(d)-'a'+1,0xf)
-/** An openssl release number for the first release in the series. For
- * example, OPENSSL_V_NOPATCH(1,0,0) is the first released version of OpenSSL
- * 1.0.0. */
-#define OPENSSL_V_NOPATCH(a,b,c) \
- OPENSSL_VER((a),(b),(c),0,0xf)
-/** The first version that would occur for any alpha or beta in an openssl
- * series. For example, OPENSSL_V_SERIES(0,9,8) is greater than any released
- * 0.9.7, and less than any released 0.9.8. */
-#define OPENSSL_V_SERIES(a,b,c) \
- OPENSSL_VER((a),(b),(c),0,0)
-
-#ifdef ANDROID
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \
- !defined(LIBRESSL_VERSION_NUMBER)
-/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require
- * seting up various callbacks.
- *
- * OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype,
- * while the previous one was restored in pre5, and the function made a no-op
- * (along with a deprecated annotation, which produces a compiler warning).
- *
- * While it is possible to support all three versions of the thread API,
- * a version that existed only for one snapshot pre-release is kind of
- * pointless, so let's not.
- */
-#define NEW_THREAD_API
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */
-
-/* global openssl state */
-const char * crypto_openssl_get_version_str(void);
-const char * crypto_openssl_get_header_version_str(void);
-
-/* OpenSSL threading setup function */
-int setup_openssl_threading(void);
-
-/* Tor OpenSSL utility functions */
-void crypto_openssl_free_all(void);
-
-#endif /* !defined(TOR_CRYPTO_OPENSSL_H) */
-
diff --git a/src/common/crypto_pwbox.c b/src/common/crypto_pwbox.c
deleted file mode 100644
index 799a8799e6..0000000000
--- a/src/common/crypto_pwbox.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Copyright (c) 2014-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file crypto_pwbox.c
- *
- * \brief Code for encrypting secrets in a password-protected form and saving
- * them to disk.
- */
-
-#include "common/crypto.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_pwbox.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_s2k.h"
-#include "common/crypto_util.h"
-#include "lib/ctime/di_ops.h"
-#include "common/util.h"
-#include "trunnel/pwbox.h"
-
-/* 8 bytes "TORBOX00"
- 1 byte: header len (H)
- H bytes: header, denoting secret key algorithm.
- 16 bytes: IV
- Round up to multiple of 128 bytes, then encrypt:
- 4 bytes: data len
- data
- zeros
- 32 bytes: HMAC-SHA256 of all previous bytes.
-*/
-
-#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 1 + 32 + CIPHER_IV_LEN)
-
-/**
- * Make an authenticated passphrase-encrypted blob to encode the
- * <b>input_len</b> bytes in <b>input</b> using the passphrase
- * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory
- * to hold the encrypted data, and store a pointer to that memory in
- * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an
- * argument to the passphrase-hashing function.
- */
-int
-crypto_pwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *input, size_t input_len,
- const char *secret, size_t secret_len,
- unsigned s2k_flags)
-{
- uint8_t *result = NULL, *encrypted_portion;
- size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
- ssize_t result_len;
- int spec_len;
- uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
- pwbox_encoded_t *enc = NULL;
- ssize_t enc_len;
-
- crypto_cipher_t *cipher;
- int rv;
-
- enc = pwbox_encoded_new();
-
- pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN);
-
- spec_len = secret_to_key_make_specifier(
- pwbox_encoded_getarray_skey_header(enc),
- S2K_MAXLEN,
- s2k_flags);
- if (BUG(spec_len < 0 || spec_len > S2K_MAXLEN))
- goto err;
- pwbox_encoded_setlen_skey_header(enc, spec_len);
- enc->header_len = spec_len;
-
- crypto_rand((char*)enc->iv, sizeof(enc->iv));
-
- pwbox_encoded_setlen_data(enc, encrypted_len);
- encrypted_portion = pwbox_encoded_getarray_data(enc);
-
- set_uint32(encrypted_portion, htonl((uint32_t)input_len));
- memcpy(encrypted_portion+4, input, input_len);
-
- /* Now that all the data is in position, derive some keys, encrypt, and
- * digest */
- const int s2k_rv = secret_to_key_derivekey(keys, sizeof(keys),
- pwbox_encoded_getarray_skey_header(enc),
- spec_len,
- secret, secret_len);
- if (BUG(s2k_rv < 0))
- goto err;
-
- cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
- crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
- crypto_cipher_free(cipher);
-
- result_len = pwbox_encoded_encoded_len(enc);
- if (BUG(result_len < 0))
- goto err;
- result = tor_malloc(result_len);
- enc_len = pwbox_encoded_encode(result, result_len, enc);
- if (BUG(enc_len < 0))
- goto err;
- tor_assert(enc_len == result_len);
-
- crypto_hmac_sha256((char*) result + result_len - 32,
- (const char*)keys + CIPHER_KEY_LEN,
- DIGEST256_LEN,
- (const char*)result,
- result_len - 32);
-
- *out = result;
- *outlen_out = result_len;
- rv = 0;
- goto out;
-
- /* LCOV_EXCL_START
-
- This error case is often unreachable if we're correctly coded, unless
- somebody adds a new error case somewhere, or unless you're building
- without scrypto support.
-
- - make_specifier can't fail, unless S2K_MAX_LEN is too short.
- - secret_to_key_derivekey can't really fail unless we're missing
- scrypt, or the underlying function fails, or we pass it a bogus
- algorithm or parameters.
- - pwbox_encoded_encoded_len can't fail unless we're using trunnel
- incorrectly.
- - pwbox_encoded_encode can't fail unless we're using trunnel wrong,
- or it's buggy.
- */
- err:
- tor_free(result);
- rv = -1;
- /* LCOV_EXCL_STOP */
- out:
- pwbox_encoded_free(enc);
- memwipe(keys, 0, sizeof(keys));
- return rv;
-}
-
-/**
- * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in
- * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes.
- * On success, return 0 and allocate a new chunk of memory to hold the
- * decrypted data, and store a pointer to that memory in *<b>out</b>, and its
- * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if
- * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is
- * definitely corrupt.
- */
-int
-crypto_unpwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len)
-{
- uint8_t *result = NULL;
- const uint8_t *encrypted;
- uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
- uint8_t hmac[DIGEST256_LEN];
- uint32_t result_len;
- size_t encrypted_len;
- crypto_cipher_t *cipher = NULL;
- int rv = UNPWBOX_CORRUPTED;
- ssize_t got_len;
-
- pwbox_encoded_t *enc = NULL;
-
- got_len = pwbox_encoded_parse(&enc, inp, input_len);
- if (got_len < 0 || (size_t)got_len != input_len)
- goto err;
-
- /* Now derive the keys and check the hmac. */
- if (secret_to_key_derivekey(keys, sizeof(keys),
- pwbox_encoded_getarray_skey_header(enc),
- pwbox_encoded_getlen_skey_header(enc),
- secret, secret_len) < 0)
- goto err;
-
- crypto_hmac_sha256((char *)hmac,
- (const char*)keys + CIPHER_KEY_LEN, DIGEST256_LEN,
- (const char*)inp, input_len - DIGEST256_LEN);
-
- if (tor_memneq(hmac, enc->hmac, DIGEST256_LEN)) {
- rv = UNPWBOX_BAD_SECRET;
- goto err;
- }
-
- /* How long is the plaintext? */
- encrypted = pwbox_encoded_getarray_data(enc);
- encrypted_len = pwbox_encoded_getlen_data(enc);
- if (encrypted_len < 4)
- goto err;
-
- cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
- crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
- result_len = ntohl(result_len);
- if (encrypted_len < result_len + 4)
- goto err;
-
- /* Allocate a buffer and decrypt */
- result = tor_malloc_zero(result_len);
- crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len);
-
- *out = result;
- *outlen_out = result_len;
-
- rv = UNPWBOX_OKAY;
- goto out;
-
- err:
- tor_free(result);
-
- out:
- crypto_cipher_free(cipher);
- pwbox_encoded_free(enc);
- memwipe(keys, 0, sizeof(keys));
- return rv;
-}
-
diff --git a/src/common/crypto_pwbox.h b/src/common/crypto_pwbox.h
deleted file mode 100644
index 9ed35a150e..0000000000
--- a/src/common/crypto_pwbox.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (c) 2014-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef CRYPTO_PWBOX_H_INCLUDED_
-#define CRYPTO_PWBOX_H_INCLUDED_
-
-#include "lib/cc/torint.h"
-
-#define UNPWBOX_OKAY 0
-#define UNPWBOX_BAD_SECRET -1
-#define UNPWBOX_CORRUPTED -2
-
-int crypto_pwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len,
- unsigned s2k_flags);
-
-int crypto_unpwbox(uint8_t **out, size_t *outlen_out,
- const uint8_t *inp, size_t input_len,
- const char *secret, size_t secret_len);
-
-#endif /* !defined(CRYPTO_PWBOX_H_INCLUDED_) */
-
diff --git a/src/common/crypto_rand.c b/src/common/crypto_rand.c
deleted file mode 100644
index 6c88e28d88..0000000000
--- a/src/common/crypto_rand.c
+++ /dev/null
@@ -1,615 +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_rand.c
- *
- * \brief Functions for initialising and seeding (pseudo-)random
- * number generators, and working with randomness.
- **/
-
-#ifndef CRYPTO_RAND_PRIVATE
-#define CRYPTO_RAND_PRIVATE
-
-#include "common/crypto_rand.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#include <wincrypt.h>
-#endif /* defined(_WIN32) */
-
-#include "common/container.h"
-#include "common/compat.h"
-#include "common/compat_openssl.h"
-#include "common/crypto_util.h"
-#include "common/sandbox.h"
-#include "common/testsupport.h"
-#include "common/torlog.h"
-#include "common/util.h"
-#include "common/util_format.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-#include <openssl/rand.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_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#endif
-#ifdef HAVE_SYS_RANDOM_H
-#include <sys/random.h>
-#endif
-
-/**
- * How many bytes of entropy we add at once.
- *
- * This is how much entropy OpenSSL likes to add right now, so maybe it will
- * work for us too.
- **/
-#define ADD_ENTROPY 32
-
-/**
- * Longest recognized DNS query.
- **/
-#define MAX_DNS_LABEL_SIZE 63
-
-/**
- * Largest strong entropy request permitted.
- **/
-#define MAX_STRONGEST_RAND_SIZE 256
-
-/**
- * Set the seed of the weak RNG to a random value.
- **/
-void
-crypto_seed_weak_rng(tor_weak_rng_t *rng)
-{
- unsigned seed;
- crypto_rand((void*)&seed, sizeof(seed));
- tor_init_weak_random(rng, seed);
-}
-
-#ifdef TOR_UNIT_TESTS
-int break_strongest_rng_syscall = 0;
-int break_strongest_rng_fallback = 0;
-#endif
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * via system calls, storing it into <b>out</b>. Return 0 on success, -1 on
- * failure. A maximum request size of 256 bytes is imposed.
- **/
-static int
-crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
-{
- tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
-
- /* We only log at notice-level here because in the case that this function
- * fails the crypto_strongest_rand_raw() caller will log with a warning-level
- * message and let crypto_strongest_rand() error out and finally terminating
- * Tor with an assertion error.
- */
-
-#ifdef TOR_UNIT_TESTS
- if (break_strongest_rng_syscall)
- return -1;
-#endif
-
-#if defined(_WIN32)
- static int provider_set = 0;
- static HCRYPTPROV provider;
-
- if (!provider_set) {
- if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT)) {
- log_notice(LD_CRYPTO, "Unable to set Windows CryptoAPI provider [1].");
- return -1;
- }
- provider_set = 1;
- }
- if (!CryptGenRandom(provider, out_len, out)) {
- log_notice(LD_CRYPTO, "Unable get entropy from the Windows CryptoAPI.");
- return -1;
- }
-
- return 0;
-#elif defined(__linux__) && defined(SYS_getrandom)
- static int getrandom_works = 1; /* Be optimistic about our chances... */
-
- /* getrandom() isn't as straightforward as getentropy(), and has
- * no glibc wrapper.
- *
- * As far as I can tell from getrandom(2) and the source code, the
- * requests we issue will always succeed (though it will block on the
- * call if /dev/urandom isn't seeded yet), since we are NOT specifying
- * GRND_NONBLOCK and the request is <= 256 bytes.
- *
- * The manpage is unclear on what happens if a signal interrupts the call
- * while the request is blocked due to lack of entropy....
- *
- * We optimistically assume that getrandom() is available and functional
- * because it is the way of the future, and 2 branch mispredicts pale in
- * comparison to the overheads involved with failing to open
- * /dev/srandom followed by opening and reading from /dev/urandom.
- */
- if (PREDICT_LIKELY(getrandom_works)) {
- long ret;
- /* A flag of '0' here means to read from '/dev/urandom', and to
- * block if insufficient entropy is available to service the
- * request.
- */
- const unsigned int flags = 0;
- do {
- ret = syscall(SYS_getrandom, out, out_len, flags);
- } while (ret == -1 && ((errno == EINTR) ||(errno == EAGAIN)));
-
- if (PREDICT_UNLIKELY(ret == -1)) {
- /* LCOV_EXCL_START we can't actually make the syscall fail in testing. */
- tor_assert(errno != EAGAIN);
- tor_assert(errno != EINTR);
-
- /* Useful log message for errno. */
- if (errno == ENOSYS) {
- log_notice(LD_CRYPTO, "Can't get entropy from getrandom()."
- " You are running a version of Tor built to support"
- " getrandom(), but the kernel doesn't implement this"
- " function--probably because it is too old?"
- " Trying fallback method instead.");
- } else {
- log_notice(LD_CRYPTO, "Can't get entropy from getrandom(): %s."
- " Trying fallback method instead.",
- strerror(errno));
- }
-
- getrandom_works = 0; /* Don't bother trying again. */
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- tor_assert(ret == (long)out_len);
- return 0;
- }
-
- return -1; /* getrandom() previously failed unexpectedly. */
-#elif defined(HAVE_GETENTROPY)
- /* getentropy() is what Linux's getrandom() wants to be when it grows up.
- * the only gotcha is that requests are limited to 256 bytes.
- */
- return getentropy(out, out_len);
-#else
- (void) out;
-#endif /* defined(_WIN32) || ... */
-
- /* This platform doesn't have a supported syscall based random. */
- return -1;
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * via the per-platform fallback mechanism, storing it into <b>out</b>.
- * Return 0 on success, -1 on failure. A maximum request size of 256 bytes
- * is imposed.
- **/
-static int
-crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
-{
-#ifdef TOR_UNIT_TESTS
- if (break_strongest_rng_fallback)
- return -1;
-#endif
-
-#ifdef _WIN32
- /* Windows exclusively uses crypto_strongest_rand_syscall(). */
- (void)out;
- (void)out_len;
- return -1;
-#else /* !(defined(_WIN32)) */
- static const char *filenames[] = {
- "/dev/srandom", "/dev/urandom", "/dev/random", NULL
- };
- int fd, i;
- size_t n;
-
- for (i = 0; filenames[i]; ++i) {
- log_debug(LD_FS, "Considering %s as entropy source", filenames[i]);
- fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
- if (fd<0) continue;
- log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
- n = read_all(fd, (char*)out, out_len, 0);
- close(fd);
- if (n != out_len) {
- /* LCOV_EXCL_START
- * We can't make /dev/foorandom actually fail. */
- log_notice(LD_CRYPTO,
- "Error reading from entropy source %s (read only %lu bytes).",
- filenames[i],
- (unsigned long)n);
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- return 0;
- }
-
- return -1;
-#endif /* defined(_WIN32) */
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * storing it into <b>out</b>. Return 0 on success, -1 on failure. A maximum
- * request size of 256 bytes is imposed.
- **/
-STATIC int
-crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
-{
- static const size_t sanity_min_size = 16;
- static const int max_attempts = 3;
- tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
-
- /* For buffers >= 16 bytes (128 bits), we sanity check the output by
- * zero filling the buffer and ensuring that it actually was at least
- * partially modified.
- *
- * Checking that any individual byte is non-zero seems like it would
- * fail too often (p = out_len * 1/256) for comfort, but this is an
- * "adjust according to taste" sort of check.
- */
- memwipe(out, 0, out_len);
- for (int i = 0; i < max_attempts; i++) {
- /* Try to use the syscall/OS favored mechanism to get strong entropy. */
- if (crypto_strongest_rand_syscall(out, out_len) != 0) {
- /* Try to use the less-favored mechanism to get strong entropy. */
- if (crypto_strongest_rand_fallback(out, out_len) != 0) {
- /* Welp, we tried. Hopefully the calling code terminates the process
- * since we're basically boned without good entropy.
- */
- log_warn(LD_CRYPTO,
- "Cannot get strong entropy: no entropy source found.");
- return -1;
- }
- }
-
- if ((out_len < sanity_min_size) || !tor_mem_is_zero((char*)out, out_len))
- return 0;
- }
-
- /* LCOV_EXCL_START
- *
- * We tried max_attempts times to fill a buffer >= 128 bits long,
- * and each time it returned all '0's. Either the system entropy
- * source is busted, or the user should go out and buy a ticket to
- * every lottery on the planet.
- */
- log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
-
- return -1;
- /* LCOV_EXCL_STOP */
-}
-
-/**
- * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
- * storing it into <b>out</b>.
- **/
-void
-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.
- */
- uint8_t inp[DLEN*2];
- uint8_t tmp[DLEN];
- tor_assert(out);
- while (out_len) {
- crypto_rand((char*) inp, DLEN);
- if (crypto_strongest_rand_raw(inp+DLEN, DLEN) < 0) {
- // LCOV_EXCL_START
- log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
- "important key. Exiting.");
- /* Die with an assertion so we get a stack trace. */
- tor_assert(0);
- // LCOV_EXCL_STOP
- }
- if (out_len >= DLEN) {
- SHA512(inp, sizeof(inp), out);
- out += DLEN;
- out_len -= DLEN;
- } else {
- SHA512(inp, sizeof(inp), tmp);
- memcpy(out, tmp, out_len);
- break;
- }
- }
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(inp, 0, sizeof(inp));
-#undef DLEN
-}
-
-/**
- * Seed OpenSSL's random number generator with bytes from the operating
- * system. Return 0 on success, -1 on failure.
- **/
-int
-crypto_seed_rng(void)
-{
- int rand_poll_ok = 0, load_entropy_ok = 0;
- uint8_t buf[ADD_ENTROPY];
-
- /* OpenSSL has a RAND_poll function that knows about more kinds of
- * entropy than we do. We'll try calling that, *and* calling our own entropy
- * functions. If one succeeds, we'll accept the RNG as seeded. */
- rand_poll_ok = RAND_poll();
- if (rand_poll_ok == 0)
- log_warn(LD_CRYPTO, "RAND_poll() failed."); // LCOV_EXCL_LINE
-
- load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
- if (load_entropy_ok) {
- RAND_seed(buf, sizeof(buf));
- }
-
- memwipe(buf, 0, sizeof(buf));
-
- if ((rand_poll_ok || load_entropy_ok) && RAND_status() == 1)
- return 0;
- else
- return -1;
-}
-
-/**
- * Write <b>n</b> bytes of strong random data to <b>to</b>. Supports mocking
- * for unit tests.
- *
- * This function is not allowed to fail; if it would fail to generate strong
- * entropy, it must terminate the process instead.
- **/
-MOCK_IMPL(void,
-crypto_rand, (char *to, size_t n))
-{
- crypto_rand_unmocked(to, n);
-}
-
-/**
- * Write <b>n</b> bytes of strong random data to <b>to</b>. Most callers
- * will want crypto_rand instead.
- *
- * This function is not allowed to fail; if it would fail to generate strong
- * entropy, it must terminate the process instead.
- **/
-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);
- /* 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);
-}
-
-/**
- * Return a pseudorandom integer, chosen uniformly from the values
- * between 0 and <b>max</b>-1 inclusive. <b>max</b> must be between 1 and
- * INT_MAX+1, inclusive.
- */
-int
-crypto_rand_int(unsigned int max)
-{
- unsigned int val;
- unsigned int cutoff;
- tor_assert(max <= ((unsigned int)INT_MAX)+1);
- tor_assert(max > 0); /* don't div by 0 */
-
- /* We ignore any values that are >= 'cutoff,' to avoid biasing the
- * distribution with clipping at the upper end of unsigned int's
- * range.
- */
- cutoff = UINT_MAX - (UINT_MAX%max);
- while (1) {
- crypto_rand((char*)&val, sizeof(val));
- if (val < cutoff)
- return val % max;
- }
-}
-
-/**
- * Return a pseudorandom integer, chosen uniformly from the values i such
- * that min <= i < max.
- *
- * <b>min</b> MUST be in range [0, <b>max</b>).
- * <b>max</b> MUST be in range (min, INT_MAX].
- **/
-int
-crypto_rand_int_range(unsigned int min, unsigned int max)
-{
- tor_assert(min < max);
- tor_assert(max <= INT_MAX);
-
- /* The overflow is avoided here because crypto_rand_int() returns a value
- * between 0 and (max - min) inclusive. */
- return min + crypto_rand_int(max - min);
-}
-
-/**
- * As crypto_rand_int_range, but supports uint64_t.
- **/
-uint64_t
-crypto_rand_uint64_range(uint64_t min, uint64_t max)
-{
- tor_assert(min < max);
- return min + crypto_rand_uint64(max - min);
-}
-
-/**
- * As crypto_rand_int_range, but supports time_t.
- **/
-time_t
-crypto_rand_time_range(time_t min, time_t max)
-{
- tor_assert(min < max);
- return min + (time_t)crypto_rand_uint64(max - min);
-}
-
-/**
- * Return a pseudorandom 64-bit integer, chosen uniformly from the values
- * between 0 and <b>max</b>-1 inclusive.
- **/
-uint64_t
-crypto_rand_uint64(uint64_t max)
-{
- uint64_t val;
- uint64_t cutoff;
- tor_assert(max < UINT64_MAX);
- tor_assert(max > 0); /* don't div by 0 */
-
- /* We ignore any values that are >= 'cutoff,' to avoid biasing the
- * distribution with clipping at the upper end of unsigned int's
- * range.
- */
- cutoff = UINT64_MAX - (UINT64_MAX%max);
- while (1) {
- crypto_rand((char*)&val, sizeof(val));
- if (val < cutoff)
- return val % max;
- }
-}
-
-/**
- * Return a pseudorandom double d, chosen uniformly from the range
- * 0.0 <= d < 1.0.
- **/
-double
-crypto_rand_double(void)
-{
- /* We just use an unsigned int here; we don't really care about getting
- * more than 32 bits of resolution */
- unsigned int u;
- crypto_rand((char*)&u, sizeof(u));
-#if SIZEOF_INT == 4
-#define UINT_MAX_AS_DOUBLE 4294967296.0
-#elif SIZEOF_INT == 8
-#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
-#else
-#error SIZEOF_INT is neither 4 nor 8
-#endif /* SIZEOF_INT == 4 || ... */
- return ((double)u) / UINT_MAX_AS_DOUBLE;
-}
-
-/**
- * Generate and return a new random hostname starting with <b>prefix</b>,
- * ending with <b>suffix</b>, and containing no fewer than
- * <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
- * characters. Does not check for failure.
- *
- * Clip <b>max_rand_len</b> to MAX_DNS_LABEL_SIZE.
- **/
-char *
-crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix,
- const char *suffix)
-{
- char *result, *rand_bytes;
- int randlen, rand_bytes_len;
- size_t resultlen, prefixlen;
-
- if (max_rand_len > MAX_DNS_LABEL_SIZE)
- max_rand_len = MAX_DNS_LABEL_SIZE;
- if (min_rand_len > max_rand_len)
- min_rand_len = max_rand_len;
-
- randlen = crypto_rand_int_range(min_rand_len, max_rand_len+1);
-
- prefixlen = strlen(prefix);
- resultlen = prefixlen + strlen(suffix) + randlen + 16;
-
- rand_bytes_len = ((randlen*5)+7)/8;
- if (rand_bytes_len % 5)
- rand_bytes_len += 5 - (rand_bytes_len%5);
- rand_bytes = tor_malloc(rand_bytes_len);
- crypto_rand(rand_bytes, rand_bytes_len);
-
- result = tor_malloc(resultlen);
- memcpy(result, prefix, prefixlen);
- base32_encode(result+prefixlen, resultlen-prefixlen,
- rand_bytes, rand_bytes_len);
- tor_free(rand_bytes);
- strlcpy(result+prefixlen+randlen, suffix, resultlen-(prefixlen+randlen));
-
- return result;
-}
-
-/**
- * Return a randomly chosen element of <b>sl</b>; or NULL if <b>sl</b>
- * is empty.
- **/
-void *
-smartlist_choose(const smartlist_t *sl)
-{
- int len = smartlist_len(sl);
- if (len)
- return smartlist_get(sl,crypto_rand_int(len));
- return NULL; /* no elements to choose from */
-}
-
-/**
- * Scramble the elements of <b>sl</b> into a random order.
- **/
-void
-smartlist_shuffle(smartlist_t *sl)
-{
- int i;
- /* From the end of the list to the front, choose at random from the
- positions we haven't looked at yet, and swap that position into the
- current position. Remember to give "no swap" the same probability as
- any other swap. */
- for (i = smartlist_len(sl)-1; i > 0; --i) {
- int j = crypto_rand_int(i+1);
- smartlist_swap(sl, i, j);
- }
-}
-
-/** Make sure that openssl is using its default PRNG. Return 1 if we had to
- * adjust it; 0 otherwise. */
-int
-crypto_force_rand_ssleay(void)
-{
- RAND_METHOD *default_method;
- default_method = RAND_OpenSSL();
- if (RAND_get_rand_method() != default_method) {
- log_notice(LD_CRYPTO, "It appears that one of our engines has provided "
- "a replacement the OpenSSL RNG. Resetting it to the default "
- "implementation.");
- RAND_set_rand_method(default_method);
- return 1;
- }
- return 0;
-}
-
-#endif /* !defined(CRYPTO_RAND_PRIVATE) */
-
diff --git a/src/common/crypto_rand.h b/src/common/crypto_rand.h
deleted file mode 100644
index 8309bb21ca..0000000000
--- a/src/common/crypto_rand.h
+++ /dev/null
@@ -1,52 +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_rand.h
- *
- * \brief Common functions for using (pseudo-)random number generators.
- **/
-
-#ifndef TOR_CRYPTO_RAND_H
-#define TOR_CRYPTO_RAND_H
-
-#include "lib/cc/torint.h"
-#include "common/util.h"
-
-/* random numbers */
-int crypto_seed_rng(void) ATTR_WUR;
-MOCK_DECL(void,crypto_rand,(char *to, size_t n));
-void crypto_rand_unmocked(char *to, size_t n);
-void crypto_strongest_rand(uint8_t *out, size_t out_len);
-int crypto_rand_int(unsigned int max);
-int crypto_rand_int_range(unsigned int min, unsigned int max);
-uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max);
-time_t crypto_rand_time_range(time_t min, time_t max);
-uint64_t crypto_rand_uint64(uint64_t max);
-double crypto_rand_double(void);
-struct tor_weak_rng_t;
-void crypto_seed_weak_rng(struct tor_weak_rng_t *rng);
-
-char *crypto_random_hostname(int min_rand_len, int max_rand_len,
- const char *prefix, const char *suffix);
-
-struct smartlist_t;
-void *smartlist_choose(const struct smartlist_t *sl);
-void smartlist_shuffle(struct smartlist_t *sl);
-int crypto_force_rand_ssleay(void);
-
-#ifdef CRYPTO_RAND_PRIVATE
-
-STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
-
-#ifdef TOR_UNIT_TESTS
-extern int break_strongest_rng_syscall;
-extern int break_strongest_rng_fallback;
-#endif
-#endif /* defined(CRYPTO_RAND_PRIVATE) */
-
-#endif /* !defined(TOR_CRYPTO_RAND_H) */
-
diff --git a/src/common/crypto_rsa.c b/src/common/crypto_rsa.c
deleted file mode 100644
index 3128983435..0000000000
--- a/src/common/crypto_rsa.c
+++ /dev/null
@@ -1,1162 +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_rsa.c
- * \brief Block of functions related with RSA utilities and operations.
- **/
-
-#include "common/crypto.h"
-#include "common/crypto_curve25519.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_format.h"
-#include "common/compat_openssl.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_rsa.h"
-#include "common/crypto_util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-#include <openssl/rand.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/conf.h>
-#include <openssl/hmac.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include "common/torlog.h"
-#include "common/util.h"
-#include "common/util_format.h"
-
-/** Declaration for crypto_pk_t structure. */
-struct crypto_pk_t
-{
- int refs; /**< reference count, so we don't have to copy keys */
- RSA *key; /**< The key itself */
-};
-
-/** Return the number of bytes added by padding method <b>padding</b>.
- */
-int
-crypto_get_rsa_padding_overhead(int padding)
-{
- switch (padding)
- {
- case RSA_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD;
- default: tor_assert(0); return -1; // LCOV_EXCL_LINE
- }
-}
-
-/** Given a padding method <b>padding</b>, return the correct OpenSSL constant.
- */
-int
-crypto_get_rsa_padding(int padding)
-{
- switch (padding)
- {
- case PK_PKCS1_OAEP_PADDING: return RSA_PKCS1_OAEP_PADDING;
- default: tor_assert(0); return -1; // LCOV_EXCL_LINE
- }
-}
-
-/** used internally: quicly validate a crypto_pk_t object as a private key.
- * Return 1 iff the public key is valid, 0 if obviously invalid.
- */
-static int
-crypto_pk_private_ok(const crypto_pk_t *k)
-{
-#ifdef OPENSSL_1_1_API
- if (!k || !k->key)
- return 0;
-
- const BIGNUM *p, *q;
- RSA_get0_factors(k->key, &p, &q);
- return p != NULL; /* XXX/yawning: Should we check q? */
-#else /* !(defined(OPENSSL_1_1_API)) */
- return k && k->key && k->key->p;
-#endif /* defined(OPENSSL_1_1_API) */
-}
-
-/** used by tortls.c: wrap an RSA* in a crypto_pk_t. */
-crypto_pk_t *
-crypto_new_pk_from_rsa_(RSA *rsa)
-{
- crypto_pk_t *env;
- tor_assert(rsa);
- env = tor_malloc(sizeof(crypto_pk_t));
- env->refs = 1;
- env->key = rsa;
- return env;
-}
-
-/** Helper, used by tor-gencert.c. Return the RSA from a
- * crypto_pk_t. */
-RSA *
-crypto_pk_get_rsa_(crypto_pk_t *env)
-{
- return env->key;
-}
-
-/** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_t. Iff
- * private is set, include the private-key portion of the key. Return a valid
- * pointer on success, and NULL on failure. */
-MOCK_IMPL(EVP_PKEY *,
-crypto_pk_get_evp_pkey_,(crypto_pk_t *env, int private))
-{
- RSA *key = NULL;
- EVP_PKEY *pkey = NULL;
- tor_assert(env->key);
- if (private) {
- if (!(key = RSAPrivateKey_dup(env->key)))
- goto error;
- } else {
- if (!(key = RSAPublicKey_dup(env->key)))
- goto error;
- }
- if (!(pkey = EVP_PKEY_new()))
- goto error;
- if (!(EVP_PKEY_assign_RSA(pkey, key)))
- goto error;
- return pkey;
- error:
- if (pkey)
- EVP_PKEY_free(pkey);
- if (key)
- RSA_free(key);
- return NULL;
-}
-
-/** Allocate and return storage for a public key. The key itself will not yet
- * be set.
- */
-MOCK_IMPL(crypto_pk_t *,
-crypto_pk_new,(void))
-{
- RSA *rsa;
-
- rsa = RSA_new();
- tor_assert(rsa);
- return crypto_new_pk_from_rsa_(rsa);
-}
-
-/** Release a reference to an asymmetric key; when all the references
- * are released, free the key.
- */
-void
-crypto_pk_free_(crypto_pk_t *env)
-{
- if (!env)
- return;
-
- if (--env->refs > 0)
- return;
- tor_assert(env->refs == 0);
-
- if (env->key)
- RSA_free(env->key);
-
- tor_free(env);
-}
-
-/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
- * Return 0 on success, -1 on failure.
- */
-MOCK_IMPL(int,
-crypto_pk_generate_key_with_bits,(crypto_pk_t *env, int bits))
-{
- tor_assert(env);
-
- if (env->key) {
- RSA_free(env->key);
- env->key = NULL;
- }
-
- {
- BIGNUM *e = BN_new();
- RSA *r = NULL;
- if (!e)
- goto done;
- if (! BN_set_word(e, 65537))
- goto done;
- r = RSA_new();
- if (!r)
- goto done;
- if (RSA_generate_key_ex(r, bits, e, NULL) == -1)
- goto done;
-
- env->key = r;
- r = NULL;
- done:
- if (e)
- BN_clear_free(e);
- if (r)
- RSA_free(r);
- }
-
- if (!env->key) {
- crypto_log_errors(LOG_WARN, "generating RSA key");
- return -1;
- }
-
- return 0;
-}
-
-/** A PEM callback that always reports a failure to get a password */
-static int
-pem_no_password_cb(char *buf, int size, int rwflag, void *u)
-{
- (void)buf;
- (void)size;
- (void)rwflag;
- (void)u;
- return -1;
-}
-
-/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>s</b>
- * into <b>env</b>. Return 0 on success, -1 on failure. If len is -1,
- * the string is nul-terminated.
- */
-int
-crypto_pk_read_private_key_from_string(crypto_pk_t *env,
- const char *s, ssize_t len)
-{
- BIO *b;
-
- tor_assert(env);
- tor_assert(s);
- tor_assert(len < INT_MAX && len < SSIZE_T_CEILING);
-
- /* Create a read-only memory BIO, backed by the string 's' */
- b = BIO_new_mem_buf((char*)s, (int)len);
- if (!b)
- return -1;
-
- if (env->key)
- RSA_free(env->key);
-
- env->key = PEM_read_bio_RSAPrivateKey(b,NULL,pem_no_password_cb,NULL);
-
- BIO_free(b);
-
- if (!env->key) {
- crypto_log_errors(LOG_WARN, "Error parsing private key");
- return -1;
- }
- return 0;
-}
-
-/** Read a PEM-encoded private key from the file named by
- * <b>keyfile</b> into <b>env</b>. Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
- const char *keyfile)
-{
- char *contents;
- int r;
-
- /* Read the file into a string. */
- contents = read_file_to_str(keyfile, 0, NULL);
- if (!contents) {
- log_warn(LD_CRYPTO, "Error reading private key from \"%s\"", keyfile);
- return -1;
- }
-
- /* Try to parse it. */
- r = crypto_pk_read_private_key_from_string(env, contents, -1);
- memwipe(contents, 0, strlen(contents));
- tor_free(contents);
- if (r)
- return -1; /* read_private_key_from_string already warned, so we don't.*/
-
- /* Make sure it's valid. */
- if (crypto_pk_check_key(env) <= 0)
- return -1;
-
- return 0;
-}
-
-/** Helper function to implement crypto_pk_write_*_key_to_string. Return 0 on
- * success, -1 on failure. */
-static int
-crypto_pk_write_key_to_string_impl(crypto_pk_t *env, char **dest,
- size_t *len, int is_public)
-{
- BUF_MEM *buf;
- BIO *b;
- int r;
-
- tor_assert(env);
- tor_assert(env->key);
- tor_assert(dest);
-
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- if (!b)
- return -1;
-
- /* Now you can treat b as if it were a file. Just use the
- * PEM_*_bio_* functions instead of the non-bio variants.
- */
- if (is_public)
- r = PEM_write_bio_RSAPublicKey(b, env->key);
- else
- 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");
- BIO_free(b);
- return -1;
- }
-
- BIO_get_mem_ptr(b, &buf);
-
- *dest = tor_malloc(buf->length+1);
- memcpy(*dest, buf->data, buf->length);
- (*dest)[buf->length] = 0; /* nul terminate it */
- *len = buf->length;
-
- BIO_free(b);
-
- return 0;
-}
-
-/** PEM-encode the public key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
- */
-int
-crypto_pk_write_public_key_to_string(crypto_pk_t *env, char **dest,
- size_t *len)
-{
- return crypto_pk_write_key_to_string_impl(env, dest, len, 1);
-}
-
-/** PEM-encode the private key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
- */
-int
-crypto_pk_write_private_key_to_string(crypto_pk_t *env, char **dest,
- size_t *len)
-{
- return crypto_pk_write_key_to_string_impl(env, dest, len, 0);
-}
-
-/** Read a PEM-encoded public key from the first <b>len</b> characters of
- * <b>src</b>, and store the result in <b>env</b>. Return 0 on success, -1 on
- * failure.
- */
-int
-crypto_pk_read_public_key_from_string(crypto_pk_t *env, const char *src,
- size_t len)
-{
- BIO *b;
-
- tor_assert(env);
- tor_assert(src);
- tor_assert(len<INT_MAX);
-
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- if (!b)
- return -1;
-
- BIO_write(b, src, (int)len);
-
- if (env->key)
- RSA_free(env->key);
- 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");
- return -1;
- }
-
- return 0;
-}
-
-/** Write the private key from <b>env</b> into the file named by <b>fname</b>,
- * PEM-encoded. Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
- const char *fname)
-{
- BIO *bio;
- char *cp;
- long len;
- char *s;
- int r;
-
- tor_assert(crypto_pk_private_ok(env));
-
- if (!(bio = BIO_new(BIO_s_mem())))
- return -1;
- if (PEM_write_bio_RSAPrivateKey(bio, env->key, NULL,NULL,0,NULL,NULL)
- == 0) {
- crypto_log_errors(LOG_WARN, "writing private key");
- BIO_free(bio);
- return -1;
- }
- len = BIO_get_mem_data(bio, &cp);
- tor_assert(len >= 0);
- s = tor_malloc(len+1);
- memcpy(s, cp, len);
- s[len]='\0';
- r = write_str_to_file(fname, s, 0);
- BIO_free(bio);
- memwipe(s, 0, strlen(s));
- tor_free(s);
- return r;
-}
-
-/** Return true iff <b>env</b> has a valid key.
- */
-int
-crypto_pk_check_key(crypto_pk_t *env)
-{
- int r;
- tor_assert(env);
-
- r = RSA_check_key(env->key);
- if (r <= 0)
- crypto_log_errors(LOG_WARN,"checking RSA key");
- return r;
-}
-
-/** Return true iff <b>key</b> contains the private-key portion of the RSA
- * key. */
-int
-crypto_pk_key_is_private(const crypto_pk_t *key)
-{
- tor_assert(key);
- return crypto_pk_private_ok(key);
-}
-
-/** Return true iff <b>env</b> contains a public key whose public exponent
- * equals 65537.
- */
-int
-crypto_pk_public_exponent_ok(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- const BIGNUM *e;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *n, *d;
- RSA_get0_key(env->key, &n, &e, &d);
-#else
- e = env->key->e;
-#endif /* defined(OPENSSL_1_1_API) */
- return BN_is_word(e, 65537);
-}
-
-/** Compare the public-key components of a and b. Return less than 0
- * if a\<b, 0 if a==b, and greater than 0 if a\>b. A NULL key is
- * considered to be less than all non-NULL keys, and equal to itself.
- *
- * Note that this may leak information about the keys through timing.
- */
-int
-crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b)
-{
- int result;
- char a_is_non_null = (a != NULL) && (a->key != NULL);
- char b_is_non_null = (b != NULL) && (b->key != NULL);
- char an_argument_is_null = !a_is_non_null | !b_is_non_null;
-
- result = tor_memcmp(&a_is_non_null, &b_is_non_null, sizeof(a_is_non_null));
- if (an_argument_is_null)
- return result;
-
- const BIGNUM *a_n, *a_e;
- const BIGNUM *b_n, *b_e;
-
-#ifdef OPENSSL_1_1_API
- const BIGNUM *a_d, *b_d;
- RSA_get0_key(a->key, &a_n, &a_e, &a_d);
- RSA_get0_key(b->key, &b_n, &b_e, &b_d);
-#else
- a_n = a->key->n;
- a_e = a->key->e;
- b_n = b->key->n;
- b_e = b->key->e;
-#endif /* defined(OPENSSL_1_1_API) */
-
- tor_assert(a_n != NULL && a_e != NULL);
- tor_assert(b_n != NULL && b_e != NULL);
-
- result = BN_cmp(a_n, b_n);
- if (result)
- return result;
- return BN_cmp(a_e, b_e);
-}
-
-/** Compare the public-key components of a and b. Return non-zero iff
- * a==b. A NULL key is considered to be distinct from all non-NULL
- * keys, and equal to itself.
- *
- * Note that this may leak information about the keys through timing.
- */
-int
-crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b)
-{
- return (crypto_pk_cmp_keys(a, b) == 0);
-}
-
-/** Return the size of the public key modulus in <b>env</b>, in bytes. */
-size_t
-crypto_pk_keysize(const crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- return (size_t) RSA_size((RSA*)env->key);
-}
-
-/** Return the size of the public key modulus of <b>env</b>, in bits. */
-int
-crypto_pk_num_bits(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
-#ifdef OPENSSL_1_1_API
- /* It's so stupid that there's no other way to check that n is valid
- * before calling RSA_bits().
- */
- const BIGNUM *n, *e, *d;
- RSA_get0_key(env->key, &n, &e, &d);
- tor_assert(n != NULL);
-
- return RSA_bits(env->key);
-#else /* !(defined(OPENSSL_1_1_API)) */
- tor_assert(env->key->n);
- return BN_num_bits(env->key->n);
-#endif /* defined(OPENSSL_1_1_API) */
-}
-
-/** Increase the reference count of <b>env</b>, and return it.
- */
-crypto_pk_t *
-crypto_pk_dup_key(crypto_pk_t *env)
-{
- tor_assert(env);
- tor_assert(env->key);
-
- env->refs++;
- return env;
-}
-
-#ifdef TOR_UNIT_TESTS
-/** For testing: replace dest with src. (Dest must have a refcount
- * of 1) */
-void
-crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src)
-{
- tor_assert(dest);
- tor_assert(dest->refs == 1);
- tor_assert(src);
- RSA_free(dest->key);
- dest->key = RSAPrivateKey_dup(src->key);
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Make a real honest-to-goodness copy of <b>env</b>, and return it.
- * Returns NULL on failure. */
-crypto_pk_t *
-crypto_pk_copy_full(crypto_pk_t *env)
-{
- RSA *new_key;
- int privatekey = 0;
- tor_assert(env);
- tor_assert(env->key);
-
- if (crypto_pk_private_ok(env)) {
- new_key = RSAPrivateKey_dup(env->key);
- privatekey = 1;
- } else {
- new_key = RSAPublicKey_dup(env->key);
- }
- if (!new_key) {
- /* LCOV_EXCL_START
- *
- * We can't cause RSA*Key_dup() to fail, so we can't really test this.
- */
- log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.",
- privatekey?"private":"public");
- crypto_log_errors(LOG_ERR,
- privatekey ? "Duplicating a private key" :
- "Duplicating a public key");
- tor_fragile_assert();
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- return crypto_new_pk_from_rsa_(new_key);
-}
-
-/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
- * bytes of data from <b>from</b>, with padding type 'padding',
- * storing the results on <b>to</b>.
- *
- * Returns the number of bytes written on success, -1 on failure.
- *
- * The encrypted data consists of:
- * - The source data, padded and encrypted with the public key, if the
- * padded source data is no longer than the public key, and <b>force</b>
- * is false, OR
- * - The beginning of the source data prefixed with a 16-byte symmetric key,
- * padded and encrypted with the public key; followed by the rest of
- * the source data encrypted in AES-CTR mode with the symmetric key.
- *
- * NOTE that this format does not authenticate the symmetrically encrypted
- * part of the data, and SHOULD NOT BE USED for new protocols.
- */
-int
-crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env,
- char *to, size_t tolen,
- const char *from,
- size_t fromlen,
- int padding, int force)
-{
- int overhead, outlen, r;
- size_t pkeylen, symlen;
- crypto_cipher_t *cipher = NULL;
- char *buf = NULL;
-
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < SIZE_T_CEILING);
-
- overhead = crypto_get_rsa_padding_overhead(crypto_get_rsa_padding(padding));
- pkeylen = crypto_pk_keysize(env);
-
- if (!force && fromlen+overhead <= pkeylen) {
- /* It all fits in a single encrypt. */
- return crypto_pk_public_encrypt(env,to,
- tolen,
- from,fromlen,padding);
- }
- tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN);
- tor_assert(tolen >= pkeylen);
-
- char key[CIPHER_KEY_LEN];
- crypto_rand(key, sizeof(key)); /* generate a new key. */
- cipher = crypto_cipher_new(key);
-
- buf = tor_malloc(pkeylen+1);
- memcpy(buf, key, CIPHER_KEY_LEN);
- memcpy(buf+CIPHER_KEY_LEN, from, pkeylen-overhead-CIPHER_KEY_LEN);
-
- /* Length of symmetrically encrypted data. */
- symlen = fromlen-(pkeylen-overhead-CIPHER_KEY_LEN);
-
- outlen = crypto_pk_public_encrypt(env,to,tolen,buf,pkeylen-overhead,padding);
- if (outlen!=(int)pkeylen) {
- goto err;
- }
- r = crypto_cipher_encrypt(cipher, to+outlen,
- from+pkeylen-overhead-CIPHER_KEY_LEN, symlen);
-
- if (r<0) goto err;
- memwipe(buf, 0, pkeylen);
- memwipe(key, 0, sizeof(key));
- tor_free(buf);
- crypto_cipher_free(cipher);
- tor_assert(outlen+symlen < INT_MAX);
- return (int)(outlen + symlen);
- err:
-
- memwipe(buf, 0, pkeylen);
- memwipe(key, 0, sizeof(key));
- tor_free(buf);
- crypto_cipher_free(cipher);
- return -1;
-}
-
-/** Invert crypto_pk_obsolete_public_hybrid_encrypt. Returns the number of
- * bytes written on success, -1 on failure.
- *
- * NOTE that this format does not authenticate the symmetrically encrypted
- * part of the data, and SHOULD NOT BE USED for new protocols.
- */
-int
-crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env,
- char *to,
- size_t tolen,
- const char *from,
- size_t fromlen,
- int padding, int warnOnFailure)
-{
- int outlen, r;
- size_t pkeylen;
- crypto_cipher_t *cipher = NULL;
- char *buf = NULL;
-
- tor_assert(fromlen < SIZE_T_CEILING);
- pkeylen = crypto_pk_keysize(env);
-
- if (fromlen <= pkeylen) {
- return crypto_pk_private_decrypt(env,to,tolen,from,fromlen,padding,
- warnOnFailure);
- }
-
- buf = tor_malloc(pkeylen);
- outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
- warnOnFailure);
- if (outlen<0) {
- log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
- "Error decrypting public-key data");
- goto err;
- }
- if (outlen < CIPHER_KEY_LEN) {
- log_fn(warnOnFailure?LOG_WARN:LOG_INFO, LD_CRYPTO,
- "No room for a symmetric key");
- goto err;
- }
- cipher = crypto_cipher_new(buf);
- if (!cipher) {
- goto err;
- }
- memcpy(to,buf+CIPHER_KEY_LEN,outlen-CIPHER_KEY_LEN);
- outlen -= CIPHER_KEY_LEN;
- tor_assert(tolen - outlen >= fromlen - pkeylen);
- r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen);
- if (r<0)
- goto err;
- memwipe(buf,0,pkeylen);
- tor_free(buf);
- crypto_cipher_free(cipher);
- tor_assert(outlen + fromlen < INT_MAX);
- return (int)(outlen + (fromlen-pkeylen));
- err:
- memwipe(buf,0,pkeylen);
- tor_free(buf);
- crypto_cipher_free(cipher);
- return -1;
-}
-
-/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
- * in <b>env</b>, using the padding method <b>padding</b>. On success,
- * write the result to <b>to</b>, and return the number of bytes
- * written. On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen, int padding)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen<INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
-
- r = RSA_public_encrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, crypto_get_rsa_padding(padding));
- if (r<0) {
- crypto_log_errors(LOG_WARN, "performing RSA encryption");
- return -1;
- }
- return r;
-}
-
-/** Decrypt <b>fromlen</b> bytes from <b>from</b> with the private key
- * in <b>env</b>, using the padding method <b>padding</b>. On success,
- * write the result to <b>to</b>, and return the number of bytes
- * written. On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(env->key);
- tor_assert(fromlen<INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- if (!crypto_pk_key_is_private(env))
- /* Not a private key */
- return -1;
-
- r = RSA_private_decrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, crypto_get_rsa_padding(padding));
-
- if (r<0) {
- crypto_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,
- "performing RSA decryption");
- return -1;
- }
- return r;
-}
-
-/** Check the signature in <b>from</b> (<b>fromlen</b> bytes long) with the
- * public key in <b>env</b>, using PKCS1 padding. On success, write the
- * signed data to <b>to</b>, and return the number of bytes written.
- * On failure, return -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-MOCK_IMPL(int,
-crypto_pk_public_checksig,(const crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen))
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- r = RSA_public_decrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- env->key, RSA_PKCS1_PADDING);
-
- if (r<0) {
- crypto_log_errors(LOG_INFO, "checking RSA signature");
- return -1;
- }
- return r;
-}
-
-/** Sign <b>fromlen</b> bytes of data from <b>from</b> with the private key in
- * <b>env</b>, using PKCS1 padding. On success, write the signature to
- * <b>to</b>, and return the number of bytes written. On failure, return
- * -1.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- int r;
- tor_assert(env);
- tor_assert(from);
- tor_assert(to);
- tor_assert(fromlen < INT_MAX);
- tor_assert(tolen >= crypto_pk_keysize(env));
- if (!crypto_pk_key_is_private(env))
- /* Not a private key */
- return -1;
-
- r = RSA_private_encrypt((int)fromlen,
- (unsigned char*)from, (unsigned char*)to,
- (RSA*)env->key, RSA_PKCS1_PADDING);
- if (r<0) {
- crypto_log_errors(LOG_WARN, "generating RSA signature");
- return -1;
- }
- return r;
-}
-
-/** ASN.1-encode the public portion of <b>pk</b> into <b>dest</b>.
- * Return -1 on error, or the number of characters used on success.
- */
-int
-crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len)
-{
- int len;
- unsigned char *buf = NULL;
-
- len = i2d_RSAPublicKey(pk->key, &buf);
- if (len < 0 || buf == NULL)
- return -1;
-
- if ((size_t)len > dest_len || dest_len > SIZE_T_CEILING) {
- OPENSSL_free(buf);
- return -1;
- }
- /* We don't encode directly into 'dest', because that would be illegal
- * type-punning. (C99 is smarter than me, C99 is smarter than me...)
- */
- memcpy(dest,buf,len);
- OPENSSL_free(buf);
- return len;
-}
-
-/** Decode an ASN.1-encoded public key from <b>str</b>; return the result on
- * success and NULL on failure.
- */
-crypto_pk_t *
-crypto_pk_asn1_decode(const char *str, size_t len)
-{
- RSA *rsa;
- unsigned char *buf;
- const unsigned char *cp;
- cp = buf = tor_malloc(len);
- memcpy(buf,str,len);
- rsa = d2i_RSAPublicKey(NULL, &cp, len);
- tor_free(buf);
- if (!rsa) {
- crypto_log_errors(LOG_WARN,"decoding public key");
- return NULL;
- }
- return crypto_new_pk_from_rsa_(rsa);
-}
-
-/** Given a private or public key <b>pk</b>, put a fingerprint of the
- * public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1 bytes of
- * space). Return 0 on success, -1 on failure.
- *
- * Fingerprints are computed as the SHA1 digest of the ASN.1 encoding
- * of the public key, converted to hexadecimal, in upper case, with a
- * space after every four digits.
- *
- * If <b>add_space</b> is false, omit the spaces.
- */
-int
-crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
-{
- char digest[DIGEST_LEN];
- char hexdigest[HEX_DIGEST_LEN+1];
- if (crypto_pk_get_digest(pk, digest)) {
- return -1;
- }
- base16_encode(hexdigest,sizeof(hexdigest),digest,DIGEST_LEN);
- if (add_space) {
- crypto_add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest);
- } else {
- strncpy(fp_out, hexdigest, HEX_DIGEST_LEN+1);
- }
- return 0;
-}
-
-/** Given a private or public key <b>pk</b>, put a hashed fingerprint of
- * the public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1
- * bytes of space). Return 0 on success, -1 on failure.
- *
- * Hashed fingerprints are computed as the SHA1 digest of the SHA1 digest
- * of the ASN.1 encoding of the public key, converted to hexadecimal, in
- * upper case.
- */
-int
-crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
-{
- char digest[DIGEST_LEN], hashed_digest[DIGEST_LEN];
- if (crypto_pk_get_digest(pk, digest)) {
- return -1;
- }
- if (crypto_digest(hashed_digest, digest, DIGEST_LEN) < 0) {
- return -1;
- }
- base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN);
- return 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
- * SHA1(data). Else return -1.
- */
-MOCK_IMPL(int,
-crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data,
- size_t datalen, const char *sig,
- size_t siglen))
-{
- char digest[DIGEST_LEN];
- char *buf;
- size_t buflen;
- int r;
-
- tor_assert(env);
- tor_assert(data);
- tor_assert(sig);
- tor_assert(datalen < SIZE_T_CEILING);
- tor_assert(siglen < SIZE_T_CEILING);
-
- if (crypto_digest(digest,data,datalen)<0) {
- log_warn(LD_BUG, "couldn't compute digest");
- return -1;
- }
- buflen = crypto_pk_keysize(env);
- buf = tor_malloc(buflen);
- r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
- if (r != DIGEST_LEN) {
- log_warn(LD_CRYPTO, "Invalid signature");
- tor_free(buf);
- return -1;
- }
- if (tor_memneq(buf, digest, DIGEST_LEN)) {
- log_warn(LD_CRYPTO, "Signature mismatched with digest.");
- tor_free(buf);
- return -1;
- }
- tor_free(buf);
-
- return 0;
-}
-
-/** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
- * <b>from</b>; sign the data with the private key in <b>env</b>, and
- * store it in <b>to</b>. Return the number of bytes written on
- * success, and -1 on failure.
- *
- * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
- * at least the length of the modulus of <b>env</b>.
- */
-int
-crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen)
-{
- int r;
- char digest[DIGEST_LEN];
- if (crypto_digest(digest,from,fromlen)<0)
- return -1;
- r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-/** Given a private or public key <b>pk</b>, put a SHA1 hash of the
- * public key into <b>digest_out</b> (must have DIGEST_LEN bytes of space).
- * Return 0 on success, -1 on failure.
- */
-int
-crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
-{
- char *buf;
- size_t buflen;
- int len;
- int rv = -1;
-
- buflen = crypto_pk_keysize(pk)*2;
- buf = tor_malloc(buflen);
- len = crypto_pk_asn1_encode(pk, buf, buflen);
- if (len < 0)
- goto done;
-
- if (crypto_digest(digest_out, buf, len) < 0)
- goto done;
-
- rv = 0;
- done:
- tor_free(buf);
- return rv;
-}
-
-/** Compute all digests of the DER encoding of <b>pk</b>, and store them
- * in <b>digests_out</b>. Return 0 on success, -1 on failure. */
-int
-crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
-{
- char *buf;
- size_t buflen;
- int len;
- int rv = -1;
-
- buflen = crypto_pk_keysize(pk)*2;
- buf = tor_malloc(buflen);
- len = crypto_pk_asn1_encode(pk, buf, buflen);
- if (len < 0)
- goto done;
-
- if (crypto_common_digests(digests_out, (char*)buf, len) < 0)
- goto done;
-
- rv = 0;
- done:
- tor_free(buf);
- return rv;
-}
-
-/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the
- * Base64 encoding of the DER representation of the private key as a NUL
- * terminated string, and return it via <b>priv_out</b>. Return 0 on
- * success, -1 on failure.
- *
- * It is the caller's responsibility to sanitize and free the resulting buffer.
- */
-int
-crypto_pk_base64_encode(const crypto_pk_t *pk, char **priv_out)
-{
- unsigned char *der = NULL;
- int der_len;
- int ret = -1;
-
- *priv_out = NULL;
-
- der_len = i2d_RSAPrivateKey(pk->key, &der);
- if (der_len < 0 || der == NULL)
- return ret;
-
- size_t priv_len = base64_encode_size(der_len, 0) + 1;
- char *priv = tor_malloc_zero(priv_len);
- if (base64_encode(priv, priv_len, (char *)der, der_len, 0) >= 0) {
- *priv_out = priv;
- ret = 0;
- } else {
- tor_free(priv);
- }
-
- memwipe(der, 0, der_len);
- OPENSSL_free(der);
- return ret;
-}
-
-/** Given a string containing the Base64 encoded DER representation of the
- * private key <b>str</b>, decode and return the result on success, or NULL
- * on failure.
- */
-crypto_pk_t *
-crypto_pk_base64_decode(const char *str, size_t len)
-{
- crypto_pk_t *pk = NULL;
-
- char *der = tor_malloc_zero(len + 1);
- int der_len = base64_decode(der, len, str, len);
- if (der_len <= 0) {
- log_warn(LD_CRYPTO, "Stored RSA private key seems corrupted (base64).");
- goto out;
- }
-
- 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");
- goto out;
- }
-
- pk = crypto_new_pk_from_rsa_(rsa);
-
- /* Make sure it's valid. */
- if (crypto_pk_check_key(pk) <= 0) {
- crypto_pk_free(pk);
- pk = NULL;
- goto out;
- }
-
- out:
- memwipe(der, 0, len + 1);
- tor_free(der);
- return pk;
-}
-
diff --git a/src/common/crypto_rsa.h b/src/common/crypto_rsa.h
deleted file mode 100644
index a80c46bb9f..0000000000
--- a/src/common/crypto_rsa.h
+++ /dev/null
@@ -1,119 +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_rsa.h
- *
- * \brief Headers for crypto_rsa.c
- **/
-
-#ifndef TOR_CRYPTO_RSA_H
-#define TOR_CRYPTO_RSA_H
-
-#include "orconfig.h"
-
-#include "common/crypto_digest.h"
-#include <stdio.h>
-#include "lib/cc/torint.h"
-#include "common/testsupport.h"
-#include "common/compat.h"
-#include "common/util.h"
-#include "common/torlog.h"
-
-/** Length of our public keys. */
-#define PK_BYTES (1024/8)
-
-/** Constant used to indicate OAEP padding for public-key encryption */
-#define PK_PKCS1_OAEP_PADDING 60002
-
-/** Number of bytes added for PKCS1-OAEP padding. */
-#define PKCS1_OAEP_PADDING_OVERHEAD 42
-
-/** A public key, or a public/private key-pair. */
-typedef struct crypto_pk_t crypto_pk_t;
-
-/* RSA environment setup */
-MOCK_DECL(crypto_pk_t *,crypto_pk_new,(void));
-void crypto_pk_free_(crypto_pk_t *env);
-#define crypto_pk_free(pk) FREE_AND_NULL(crypto_pk_t, crypto_pk_free_, (pk))
-int crypto_get_rsa_padding_overhead(int padding);
-int crypto_get_rsa_padding(int padding);
-
-/* public key crypto */
-MOCK_DECL(int, crypto_pk_generate_key_with_bits,(crypto_pk_t *env, int bits));
-#define crypto_pk_generate_key(env) \
- crypto_pk_generate_key_with_bits((env), (PK_BYTES*8))
-
-int crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
- const char *keyfile);
-int crypto_pk_write_public_key_to_string(crypto_pk_t *env,
- char **dest, size_t *len);
-int crypto_pk_write_private_key_to_string(crypto_pk_t *env,
- char **dest, size_t *len);
-int crypto_pk_read_public_key_from_string(crypto_pk_t *env,
- const char *src, size_t len);
-int crypto_pk_read_private_key_from_string(crypto_pk_t *env,
- const char *s, ssize_t len);
-int crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
- const char *fname);
-
-int crypto_pk_check_key(crypto_pk_t *env);
-int crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b);
-int crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b);
-size_t crypto_pk_keysize(const crypto_pk_t *env);
-int crypto_pk_num_bits(crypto_pk_t *env);
-crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig);
-crypto_pk_t *crypto_pk_copy_full(crypto_pk_t *orig);
-int crypto_pk_key_is_private(const crypto_pk_t *key);
-int crypto_pk_public_exponent_ok(crypto_pk_t *env);
-int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int force);
-int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to,
- size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure);
-int crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen, int padding);
-int crypto_pk_private_decrypt(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen,
- int padding, int warnOnFailure);
-MOCK_DECL(int, crypto_pk_public_checksig,(const crypto_pk_t *env,
- char *to, size_t tolen,
- const char *from, size_t fromlen));
-int crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen);
-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);
-
-MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env,
- const char *data, size_t datalen, const char *sig, size_t siglen));
-int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
- const char *from, size_t fromlen);
-int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out);
-int crypto_pk_get_common_digests(crypto_pk_t *pk,
- common_digests_t *digests_out);
-int crypto_pk_base64_encode(const crypto_pk_t *pk, char **priv_out);
-crypto_pk_t *crypto_pk_base64_decode(const char *str, size_t len);
-
-/* Prototypes for private functions only used by tortls.c, crypto.c, and the
- * unit tests. */
-struct rsa_st;
-struct rsa_st *crypto_pk_get_rsa_(crypto_pk_t *env);
-crypto_pk_t *crypto_new_pk_from_rsa_(struct rsa_st *rsa);
-MOCK_DECL(struct evp_pkey_st *, crypto_pk_get_evp_pkey_,(crypto_pk_t *env,
- int private));
-struct evp_pkey_st;
-
-#ifdef TOR_UNIT_TESTS
-void crypto_pk_assign_(crypto_pk_t *dest, const crypto_pk_t *src);
-#endif
-
-#endif
-
diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c
deleted file mode 100644
index db57691f60..0000000000
--- a/src/common/crypto_s2k.c
+++ /dev/null
@@ -1,476 +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_s2k.c
- *
- * \brief Functions for deriving keys from human-readable passphrases.
- */
-
-#define CRYPTO_S2K_PRIVATE
-
-#include "common/compat.h"
-#include "common/crypto.h"
-#include "common/crypto_digest.h"
-#include "common/crypto_hkdf.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_s2k.h"
-#include "common/crypto_util.h"
-#include "common/util.h"
-
-#include <openssl/evp.h>
-
-#if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
-#define HAVE_SCRYPT
-#include <libscrypt.h>
-#endif
-
-/* Encoded secrets take the form:
-
- u8 type;
- u8 salt_and_parameters[depends on type];
- u8 key[depends on type];
-
- As a special case, if the encoded secret is exactly 29 bytes long,
- type 0 is understood.
-
- Recognized types are:
- 00 -- RFC2440. salt_and_parameters is 9 bytes. key is 20 bytes.
- salt_and_parameters is 8 bytes random salt,
- 1 byte iteration info.
- 01 -- PKBDF2_SHA1. salt_and_parameters is 17 bytes. key is 20 bytes.
- salt_and_parameters is 16 bytes random salt,
- 1 byte iteration info.
- 02 -- SCRYPT_SALSA208_SHA256. salt_and_parameters is 18 bytes. key is
- 32 bytes.
- salt_and_parameters is 18 bytes random salt, 2 bytes iteration
- info.
-*/
-
-#define S2K_TYPE_RFC2440 0
-#define S2K_TYPE_PBKDF2 1
-#define S2K_TYPE_SCRYPT 2
-
-#define PBKDF2_SPEC_LEN 17
-#define PBKDF2_KEY_LEN 20
-
-#define SCRYPT_SPEC_LEN 18
-#define SCRYPT_KEY_LEN 32
-
-/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
- * specifier part of it, without the prefix type byte. Return -1 if it is not
- * a valid algorithm ID. */
-static int
-secret_to_key_spec_len(uint8_t type)
-{
- switch (type) {
- case S2K_TYPE_RFC2440:
- return S2K_RFC2440_SPECIFIER_LEN;
- case S2K_TYPE_PBKDF2:
- return PBKDF2_SPEC_LEN;
- case S2K_TYPE_SCRYPT:
- return SCRYPT_SPEC_LEN;
- default:
- return -1;
- }
-}
-
-/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
- * its preferred output. */
-static int
-secret_to_key_key_len(uint8_t type)
-{
- switch (type) {
- case S2K_TYPE_RFC2440:
- return DIGEST_LEN;
- case S2K_TYPE_PBKDF2:
- return DIGEST_LEN;
- case S2K_TYPE_SCRYPT:
- return DIGEST256_LEN;
- // LCOV_EXCL_START
- default:
- tor_fragile_assert();
- return -1;
- // LCOV_EXCL_STOP
- }
-}
-
-/** Given a specifier in <b>spec_and_key</b> of length
- * <b>spec_and_key_len</b>, along with its prefix algorithm ID byte, and along
- * with a key if <b>key_included</b> is true, check whether the whole
- * specifier-and-key is of valid length, and return the algorithm type if it
- * is. Set *<b>legacy_out</b> to 1 iff this is a legacy password hash or
- * legacy specifier. Return an error code on failure.
- */
-static int
-secret_to_key_get_type(const uint8_t *spec_and_key, size_t spec_and_key_len,
- int key_included, int *legacy_out)
-{
- size_t legacy_len = S2K_RFC2440_SPECIFIER_LEN;
- uint8_t type;
- int total_len;
-
- if (key_included)
- legacy_len += DIGEST_LEN;
-
- if (spec_and_key_len == legacy_len) {
- *legacy_out = 1;
- return S2K_TYPE_RFC2440;
- }
-
- *legacy_out = 0;
- if (spec_and_key_len == 0)
- return S2K_BAD_LEN;
-
- type = spec_and_key[0];
- total_len = secret_to_key_spec_len(type);
- if (total_len < 0)
- return S2K_BAD_ALGORITHM;
- if (key_included) {
- int keylen = secret_to_key_key_len(type);
- if (keylen < 0)
- return S2K_BAD_ALGORITHM;
- total_len += keylen;
- }
-
- if ((size_t)total_len + 1 == spec_and_key_len)
- return type;
- else
- return S2K_BAD_LEN;
-}
-
-/**
- * Write a new random s2k specifier of type <b>type</b>, without prefixing
- * type byte, to <b>spec_out</b>, which must have enough room. May adjust
- * parameter choice based on <b>flags</b>.
- */
-static int
-make_specifier(uint8_t *spec_out, uint8_t type, unsigned flags)
-{
- int speclen = secret_to_key_spec_len(type);
- if (speclen < 0)
- return S2K_BAD_ALGORITHM;
-
- crypto_rand((char*)spec_out, speclen);
- switch (type) {
- case S2K_TYPE_RFC2440:
- /* Hash 64 k of data. */
- spec_out[S2K_RFC2440_SPECIFIER_LEN-1] = 96;
- break;
- case S2K_TYPE_PBKDF2:
- /* 131 K iterations */
- spec_out[PBKDF2_SPEC_LEN-1] = 17;
- break;
- case S2K_TYPE_SCRYPT:
- if (flags & S2K_FLAG_LOW_MEM) {
- /* N = 1<<12 */
- spec_out[SCRYPT_SPEC_LEN-2] = 12;
- } else {
- /* N = 1<<15 */
- spec_out[SCRYPT_SPEC_LEN-2] = 15;
- }
- /* r = 8; p = 2. */
- spec_out[SCRYPT_SPEC_LEN-1] = (3u << 4) | (1u << 0);
- break;
- // LCOV_EXCL_START - we should have returned above.
- default:
- tor_fragile_assert();
- return S2K_BAD_ALGORITHM;
- // LCOV_EXCL_STOP
- }
-
- return speclen;
-}
-
-/** Implement RFC2440-style iterated-salted S2K conversion: convert the
- * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte
- * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier
- * are a salt; the 9th byte describes how much iteration to do.
- * If <b>key_out_len</b> &gt; DIGEST_LEN, use HDKF to expand the result.
- */
-void
-secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier)
-{
- crypto_digest_t *d;
- uint8_t c;
- size_t count, tmplen;
- char *tmp;
- uint8_t buf[DIGEST_LEN];
- tor_assert(key_out_len < SIZE_T_CEILING);
-
-#define EXPBIAS 6
- c = s2k_specifier[8];
- count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
-#undef EXPBIAS
-
- d = crypto_digest_new();
- tmplen = 8+secret_len;
- tmp = tor_malloc(tmplen);
- memcpy(tmp,s2k_specifier,8);
- memcpy(tmp+8,secret,secret_len);
- secret_len += 8;
- while (count) {
- if (count >= secret_len) {
- crypto_digest_add_bytes(d, tmp, secret_len);
- count -= secret_len;
- } else {
- crypto_digest_add_bytes(d, tmp, count);
- count = 0;
- }
- }
- crypto_digest_get_digest(d, (char*)buf, sizeof(buf));
-
- if (key_out_len <= sizeof(buf)) {
- memcpy(key_out, buf, key_out_len);
- } else {
- crypto_expand_key_material_rfc5869_sha256(buf, DIGEST_LEN,
- (const uint8_t*)s2k_specifier, 8,
- (const uint8_t*)"EXPAND", 6,
- (uint8_t*)key_out, key_out_len);
- }
- memwipe(tmp, 0, tmplen);
- memwipe(buf, 0, sizeof(buf));
- tor_free(tmp);
- crypto_digest_free(d);
-}
-
-/**
- * Helper: given a valid specifier without prefix type byte in <b>spec</b>,
- * whose length must be correct, and given a secret passphrase <b>secret</b>
- * of length <b>secret_len</b>, compute the key and store it into
- * <b>key_out</b>, which must have enough room for secret_to_key_key_len(type)
- * bytes. Return the number of bytes written on success and an error code
- * on failure.
- */
-STATIC int
-secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len,
- int type)
-{
- int rv;
- if (key_out_len > INT_MAX)
- return S2K_BAD_LEN;
-
- switch (type) {
- case S2K_TYPE_RFC2440:
- secret_to_key_rfc2440((char*)key_out, key_out_len, secret, secret_len,
- (const char*)spec);
- return (int)key_out_len;
-
- case S2K_TYPE_PBKDF2: {
- uint8_t log_iters;
- if (spec_len < 1 || secret_len > INT_MAX || spec_len > INT_MAX)
- return S2K_BAD_LEN;
- log_iters = spec[spec_len-1];
- if (log_iters > 31)
- return S2K_BAD_PARAMS;
- rv = PKCS5_PBKDF2_HMAC_SHA1(secret, (int)secret_len,
- spec, (int)spec_len-1,
- (1<<log_iters),
- (int)key_out_len, key_out);
- if (rv < 0)
- return S2K_FAILED;
- return (int)key_out_len;
- }
-
- case S2K_TYPE_SCRYPT: {
-#ifdef HAVE_SCRYPT
- uint8_t log_N, log_r, log_p;
- uint64_t N;
- uint32_t r, p;
- if (spec_len < 2)
- return S2K_BAD_LEN;
- log_N = spec[spec_len-2];
- log_r = (spec[spec_len-1]) >> 4;
- log_p = (spec[spec_len-1]) & 15;
- if (log_N > 63)
- return S2K_BAD_PARAMS;
- N = ((uint64_t)1) << log_N;
- r = 1u << log_r;
- p = 1u << log_p;
- rv = libscrypt_scrypt((const uint8_t*)secret, secret_len,
- spec, spec_len-2, N, r, p, key_out, key_out_len);
- if (rv != 0)
- return S2K_FAILED;
- return (int)key_out_len;
-#else /* !(defined(HAVE_SCRYPT)) */
- return S2K_NO_SCRYPT_SUPPORT;
-#endif /* defined(HAVE_SCRYPT) */
- }
- default:
- return S2K_BAD_ALGORITHM;
- }
-}
-
-/**
- * Given a specifier previously constructed with secret_to_key_make_specifier
- * in <b>spec</b> of length <b>spec_len</b>, and a secret password in
- * <b>secret</b> of length <b>secret_len</b>, generate <b>key_out_len</b>
- * bytes of cryptographic material in <b>key_out</b>. The native output of
- * the secret-to-key function will be truncated if key_out_len is short, and
- * expanded with HKDF if key_out_len is long. Returns S2K_OKAY on success,
- * and an error code on failure.
- */
-int
-secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len)
-{
- int legacy_format = 0;
- int type = secret_to_key_get_type(spec, spec_len, 0, &legacy_format);
- int r;
-
- if (type < 0)
- return type;
-#ifndef HAVE_SCRYPT
- if (type == S2K_TYPE_SCRYPT)
- return S2K_NO_SCRYPT_SUPPORT;
- #endif
-
- if (! legacy_format) {
- ++spec;
- --spec_len;
- }
-
- r = secret_to_key_compute_key(key_out, key_out_len, spec, spec_len,
- secret, secret_len, type);
- if (r < 0)
- return r;
- else
- return S2K_OKAY;
-}
-
-/**
- * Construct a new s2k algorithm specifier and salt in <b>buf</b>, according
- * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>. Up to
- * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Return the
- * number of bytes used on success and an error code on failure.
- */
-int
-secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags)
-{
- int rv;
- int spec_len;
-#ifdef HAVE_SCRYPT
- uint8_t type = S2K_TYPE_SCRYPT;
-#else
- uint8_t type = S2K_TYPE_RFC2440;
-#endif
-
- if (flags & S2K_FLAG_NO_SCRYPT)
- type = S2K_TYPE_RFC2440;
- if (flags & S2K_FLAG_USE_PBKDF2)
- type = S2K_TYPE_PBKDF2;
-
- spec_len = secret_to_key_spec_len(type);
-
- if ((int)buf_len < spec_len + 1)
- return S2K_TRUNCATED;
-
- buf[0] = type;
- rv = make_specifier(buf+1, type, flags);
- if (rv < 0)
- return rv;
- else
- return rv + 1;
-}
-
-/**
- * Hash a passphrase from <b>secret</b> of length <b>secret_len</b>, according
- * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>, and store the
- * hash along with salt and hashing parameters into <b>buf</b>. Up to
- * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Set
- * *<b>len_out</b> to the number of bytes used and return S2K_OKAY on success;
- * and return an error code on failure.
- */
-int
-secret_to_key_new(uint8_t *buf,
- size_t buf_len,
- size_t *len_out,
- const char *secret, size_t secret_len,
- unsigned flags)
-{
- int key_len;
- int spec_len;
- int type;
- int rv;
-
- spec_len = secret_to_key_make_specifier(buf, buf_len, flags);
-
- if (spec_len < 0)
- return spec_len;
-
- type = buf[0];
- key_len = secret_to_key_key_len(type);
-
- if (key_len < 0)
- return key_len;
-
- if ((int)buf_len < key_len + spec_len)
- return S2K_TRUNCATED;
-
- rv = secret_to_key_compute_key(buf + spec_len, key_len,
- buf + 1, spec_len-1,
- secret, secret_len, type);
- if (rv < 0)
- return rv;
-
- *len_out = spec_len + key_len;
-
- return S2K_OKAY;
-}
-
-/**
- * Given a hashed passphrase in <b>spec_and_key</b> of length
- * <b>spec_and_key_len</b> as generated by secret_to_key_new(), verify whether
- * it is a hash of the passphrase <b>secret</b> of length <b>secret_len</b>.
- * Return S2K_OKAY on a match, S2K_BAD_SECRET on a well-formed hash that
- * doesn't match this secret, and another error code on other errors.
- */
-int
-secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
- const char *secret, size_t secret_len)
-{
- int is_legacy = 0;
- int type = secret_to_key_get_type(spec_and_key, spec_and_key_len,
- 1, &is_legacy);
- uint8_t buf[32];
- int spec_len;
- int key_len;
- int rv;
-
- if (type < 0)
- return type;
-
- if (! is_legacy) {
- spec_and_key++;
- spec_and_key_len--;
- }
-
- spec_len = secret_to_key_spec_len(type);
- key_len = secret_to_key_key_len(type);
- tor_assert(spec_len > 0);
- tor_assert(key_len > 0);
- tor_assert(key_len <= (int) sizeof(buf));
- tor_assert((int)spec_and_key_len == spec_len + key_len);
- rv = secret_to_key_compute_key(buf, key_len,
- spec_and_key, spec_len,
- secret, secret_len, type);
- if (rv < 0)
- goto done;
-
- if (tor_memeq(buf, spec_and_key + spec_len, key_len))
- rv = S2K_OKAY;
- else
- rv = S2K_BAD_SECRET;
-
- done:
- memwipe(buf, 0, sizeof(buf));
- return rv;
-}
-
diff --git a/src/common/crypto_s2k.h b/src/common/crypto_s2k.h
deleted file mode 100644
index b270897b68..0000000000
--- a/src/common/crypto_s2k.h
+++ /dev/null
@@ -1,73 +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 */
-
-#ifndef TOR_CRYPTO_S2K_H_INCLUDED
-#define TOR_CRYPTO_S2K_H_INCLUDED
-
-#include <stdio.h>
-#include "lib/cc/torint.h"
-
-/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the
- * 9th describes how much iteration to do. */
-#define S2K_RFC2440_SPECIFIER_LEN 9
-void secret_to_key_rfc2440(
- char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier);
-
-/** Flag for secret-to-key function: do not use scrypt. */
-#define S2K_FLAG_NO_SCRYPT (1u<<0)
-/** Flag for secret-to-key functions: if using a memory-tuned s2k function,
- * assume that we have limited memory. */
-#define S2K_FLAG_LOW_MEM (1u<<1)
-/** Flag for secret-to-key functions: force use of pbkdf2. Without this, we
- * default to scrypt, then RFC2440. */
-#define S2K_FLAG_USE_PBKDF2 (1u<<2)
-
-/** Maximum possible output length from secret_to_key_new. */
-#define S2K_MAXLEN 64
-
-/** Error code from secret-to-key functions: all is well */
-#define S2K_OKAY 0
-/** Error code from secret-to-key functions: generic failure */
-#define S2K_FAILED -1
-/** Error code from secret-to-key functions: provided secret didn't match */
-#define S2K_BAD_SECRET -2
-/** Error code from secret-to-key functions: didn't recognize the algorithm */
-#define S2K_BAD_ALGORITHM -3
-/** Error code from secret-to-key functions: specifier wasn't valid */
-#define S2K_BAD_PARAMS -4
-/** Error code from secret-to-key functions: compiled without scrypt */
-#define S2K_NO_SCRYPT_SUPPORT -5
-/** Error code from secret-to-key functions: not enough space to write output.
- */
-#define S2K_TRUNCATED -6
-/** Error code from secret-to-key functions: Wrong length for specifier. */
-#define S2K_BAD_LEN -7
-
-int secret_to_key_new(uint8_t *buf,
- size_t buf_len,
- size_t *len_out,
- const char *secret, size_t secret_len,
- unsigned flags);
-
-int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags);
-
-int secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
- const char *secret, size_t secret_len);
-
-int secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len);
-
-#ifdef CRYPTO_S2K_PRIVATE
-STATIC int secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
- const uint8_t *spec, size_t spec_len,
- const char *secret, size_t secret_len,
- int type);
-#endif /* defined(CRYPTO_S2K_PRIVATE) */
-
-#endif /* !defined(TOR_CRYPTO_S2K_H_INCLUDED) */
-
diff --git a/src/common/crypto_util.c b/src/common/crypto_util.c
deleted file mode 100644
index 71707d4bfb..0000000000
--- a/src/common/crypto_util.c
+++ /dev/null
@@ -1,130 +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_util.c
- *
- * \brief Common cryptographic utilities.
- **/
-
-#ifndef CRYPTO_UTIL_PRIVATE
-#define CRYPTO_UTIL_PRIVATE
-
-#include "common/crypto_util.h"
-
-#include <string.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <wincrypt.h>
-#endif /* defined(_WIN32) */
-
-#include "common/util.h"
-
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/err.h>
-#include <openssl/crypto.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#include "common/torlog.h"
-
-/**
- * Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
- * the value <b>byte</b>.
- * If <b>mem</b> is NULL or <b>sz</b> is zero, nothing happens.
- *
- * This function is preferable to memset, since many compilers will happily
- * optimize out memset() when they can convince themselves that the data being
- * cleared will never be read.
- *
- * Right now, our convention is to use this function when we are wiping data
- * that's about to become inaccessible, such as stack buffers that are about
- * to go out of scope or structures that are about to get freed. (In
- * practice, it appears that the compilers we're currently using will optimize
- * out the memset()s for stack-allocated buffers, but not those for
- * about-to-be-freed structures. That could change, though, so we're being
- * wary.) If there are live reads for the data, then you can just use
- * memset().
- */
-void
-memwipe(void *mem, uint8_t byte, size_t sz)
-{
- if (sz == 0) {
- return;
- }
- /* If sz is nonzero, then mem must not be NULL. */
- tor_assert(mem != NULL);
-
- /* Data this large is likely to be an underflow. */
- tor_assert(sz < SIZE_T_CEILING);
-
- /* Because whole-program-optimization exists, we may not be able to just
- * have this function call "memset". A smart compiler could inline it, then
- * eliminate dead memsets, and declare itself to be clever. */
-
-#if defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY)
- /* Here's what you do on windows. */
- SecureZeroMemory(mem,sz);
-#elif defined(HAVE_RTLSECUREZEROMEMORY)
- RtlSecureZeroMemory(mem,sz);
-#elif defined(HAVE_EXPLICIT_BZERO)
- /* The BSDs provide this. */
- explicit_bzero(mem, sz);
-#elif defined(HAVE_MEMSET_S)
- /* This is in the C99 standard. */
- memset_s(mem, sz, 0, sz);
-#else
- /* This is a slow and ugly function from OpenSSL that fills 'mem' with junk
- * based on the pointer value, then uses that junk to update a global
- * variable. It's an elaborate ruse to trick the compiler into not
- * optimizing out the "wipe this memory" code. Read it if you like zany
- * programming tricks! In later versions of Tor, we should look for better
- * not-optimized-out memory wiping stuff...
- *
- * ...or maybe not. In practice, there are pure-asm implementations of
- * OPENSSL_cleanse() on most platforms, which ought to do the job.
- **/
-
- OPENSSL_cleanse(mem, sz);
-#endif /* defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY) || ... */
-
- /* Just in case some caller of memwipe() is relying on getting a buffer
- * filled with a particular value, fill the buffer.
- *
- * If this function gets inlined, this memset might get eliminated, but
- * that's okay: We only care about this particular memset in the case where
- * the caller should have been using memset(), and the memset() wouldn't get
- * eliminated. In other words, this is here so that we won't break anything
- * if somebody accidentally calls memwipe() instead of memset().
- **/
- 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) */
-
diff --git a/src/common/crypto_util.h b/src/common/crypto_util.h
deleted file mode 100644
index 3ce34e6f23..0000000000
--- a/src/common/crypto_util.h
+++ /dev/null
@@ -1,30 +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_util.h
- *
- * \brief Common functions for cryptographic routines.
- **/
-
-#ifndef TOR_CRYPTO_UTIL_H
-#define TOR_CRYPTO_UTIL_H
-
-#include "lib/cc/torint.h"
-
-/** 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) */
-
diff --git a/src/common/include.am b/src/common/include.am
index 2869c2ac9d..fb5472f3b9 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -1,13 +1,11 @@
noinst_LIBRARIES += \
src/common/libor.a \
- src/common/libor-crypto.a \
src/common/libor-event.a
if UNITTESTS_ENABLED
noinst_LIBRARIES += \
src/common/libor-testing.a \
- src/common/libor-crypto-testing.a \
src/common/libor-event-testing.a
endif
@@ -83,24 +81,6 @@ LIBOR_A_SRC = \
src/common/src_common_libor_testing_a-log.$(OBJEXT) \
src/common/log.$(OBJEXT): micro-revision.i
-LIBOR_CRYPTO_A_SRC = \
- src/common/aes.c \
- src/common/buffers_tls.c \
- src/common/crypto.c \
- src/common/crypto_dh.c \
- src/common/crypto_digest.c \
- src/common/crypto_format.c \
- src/common/crypto_hkdf.c \
- src/common/crypto_openssl_mgt.c \
- src/common/crypto_pwbox.c \
- src/common/crypto_rand.c \
- src/common/crypto_rsa.c \
- src/common/crypto_s2k.c \
- src/common/crypto_util.c \
- src/common/tortls.c \
- src/common/crypto_curve25519.c \
- src/common/crypto_ed25519.c
-
LIBOR_EVENT_A_SRC = \
src/common/compat_libevent.c \
src/common/procmon.c \
@@ -108,53 +88,31 @@ LIBOR_EVENT_A_SRC = \
src/ext/timeouts/timeout.c
src_common_libor_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
src_common_libor_event_a_SOURCES = $(LIBOR_EVENT_A_SRC)
if UNITTESTS_ENABLED
src_common_libor_testing_a_SOURCES = $(LIBOR_A_SRC)
-src_common_libor_crypto_testing_a_SOURCES = $(LIBOR_CRYPTO_A_SRC)
src_common_libor_event_testing_a_SOURCES = $(LIBOR_EVENT_A_SRC)
else
src_common_libor_testing_a_SOURCES =
-src_common_libor_crypto_testing_a_SOURCES =
src_common_libor_event_testing_a_SOURCES =
endif
src_common_libor_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
-src_common_libor_crypto_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_common_libor_event_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_common_libor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_common_libor_crypto_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
COMMONHEADERS = \
src/common/address.h \
src/common/address_set.h \
src/common/buffers.h \
- src/common/buffers_tls.h \
- src/common/aes.h \
- src/common/ciphers.inc \
src/common/compat.h \
src/common/compat_libevent.h \
- src/common/compat_openssl.h \
src/common/compat_threads.h \
src/common/compat_time.h \
src/common/confline.h \
src/common/container.h \
- src/common/crypto.h \
- src/common/crypto_dh.h \
- src/common/crypto_digest.h \
- src/common/crypto_curve25519.h \
- src/common/crypto_ed25519.h \
- src/common/crypto_format.h \
- src/common/crypto_hkdf.h \
- src/common/crypto_openssl_mgt.h \
- src/common/crypto_pwbox.h \
- src/common/crypto_rand.h \
- src/common/crypto_rsa.h \
- src/common/crypto_s2k.h \
- src/common/crypto_util.h \
src/common/handles.h \
src/common/memarea.h \
src/common/linux_syscalls.inc \
@@ -165,7 +123,6 @@ COMMONHEADERS = \
src/common/timers.h \
src/common/token_bucket.h \
src/common/torlog.h \
- src/common/tortls.h \
src/common/util.h \
src/common/util_bug.h \
src/common/util_format.h \
diff --git a/src/common/tortls.c b/src/common/tortls.c
deleted file mode 100644
index 419d9c9316..0000000000
--- a/src/common/tortls.c
+++ /dev/null
@@ -1,2663 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file tortls.c
- * \brief Wrapper functions to present a consistent interface to
- * TLS, SSL, and X.509 functions from OpenSSL.
- **/
-
-/* (Unlike other tor functions, these
- * are prefixed with tor_ in order to avoid conflicting with OpenSSL
- * functions and variables.)
- */
-
-#include "orconfig.h"
-
-#define TORTLS_PRIVATE
-#define TORTLS_OPENSSL_PRIVATE
-
-#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#endif
-
-#include "common/crypto.h"
-#include "common/crypto_rand.h"
-#include "common/crypto_dh.h"
-#include "common/crypto_util.h"
-#include "common/compat.h"
-
-/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
- * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
-
-#include <openssl/opensslv.h>
-
-#ifdef OPENSSL_NO_EC
-#error "We require OpenSSL with ECC support"
-#endif
-
-#include <openssl/ssl.h>
-#include <openssl/ssl3.h>
-#include <openssl/err.h>
-#include <openssl/tls1.h>
-#include <openssl/asn1.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-
-ENABLE_GCC_WARNING(redundant-decls)
-
-#define TORTLS_PRIVATE
-#include "common/tortls.h"
-#include "common/util.h"
-#include "common/torlog.h"
-#include "common/container.h"
-#include <string.h>
-
-#ifdef OPENSSL_1_1_API
-#define X509_get_notBefore_const(cert) \
- X509_get0_notBefore(cert)
-#define X509_get_notAfter_const(cert) \
- X509_get0_notAfter(cert)
-#ifndef X509_get_notBefore
-#define X509_get_notBefore(cert) \
- X509_getm_notBefore(cert)
-#endif
-#ifndef X509_get_notAfter
-#define X509_get_notAfter(cert) \
- X509_getm_notAfter(cert)
-#endif
-#else /* ! OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
-#define X509_get_notBefore_const(cert) \
- ((const ASN1_TIME*) X509_get_notBefore((X509 *)cert))
-#define X509_get_notAfter_const(cert) \
- ((const ASN1_TIME*) X509_get_notAfter((X509 *)cert))
-#endif
-
-/* Copied from or.h */
-#define LEGAL_NICKNAME_CHARACTERS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-/** How long do identity certificates live? (sec) */
-#define IDENTITY_CERT_LIFETIME (365*24*60*60)
-
-#define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer")
-
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f')
-/* This is a version of OpenSSL before 1.0.0f. It does not have
- * the CVE-2011-4576 fix, and as such it can't use RELEASE_BUFFERS and
- * SSL3 safely at the same time.
- */
-#define DISABLE_SSL3_HANDSHAKE
-#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') */
-
-/* We redefine these so that we can run correctly even if the vendor gives us
- * a version of OpenSSL that does not match its header files. (Apple: I am
- * looking at you.)
- */
-#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
-#endif
-#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010
-#endif
-
-/** Return values for tor_tls_classify_client_ciphers.
- *
- * @{
- */
-/** An error occurred when examining the client ciphers */
-#define CIPHERS_ERR -1
-/** The client cipher list indicates that a v1 handshake was in use. */
-#define CIPHERS_V1 1
-/** The client cipher list indicates that the client is using the v2 or the
- * v3 handshake, but that it is (probably!) lying about what ciphers it
- * supports */
-#define CIPHERS_V2 2
-/** The client cipher list indicates that the client is using the v2 or the
- * v3 handshake, and that it is telling the truth about what ciphers it
- * supports */
-#define CIPHERS_UNRESTRICTED 3
-/** @} */
-
-/** The ex_data index in which we store a pointer to an SSL object's
- * corresponding tor_tls_t object. */
-STATIC int tor_tls_object_ex_data_index = -1;
-
-/** Helper: Allocate tor_tls_object_ex_data_index. */
-STATIC void
-tor_tls_allocate_tor_tls_object_ex_data_index(void)
-{
- if (tor_tls_object_ex_data_index == -1) {
- tor_tls_object_ex_data_index =
- SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- tor_assert(tor_tls_object_ex_data_index != -1);
- }
-}
-
-/** Helper: given a SSL* pointer, return the tor_tls_t object using that
- * pointer. */
-STATIC tor_tls_t *
-tor_tls_get_by_ssl(const SSL *ssl)
-{
- tor_tls_t *result = SSL_get_ex_data(ssl, tor_tls_object_ex_data_index);
- if (result)
- tor_assert(result->magic == TOR_TLS_MAGIC);
- return result;
-}
-
-static void tor_tls_context_decref(tor_tls_context_t *ctx);
-static void tor_tls_context_incref(tor_tls_context_t *ctx);
-
-static int check_cert_lifetime_internal(int severity, const X509 *cert,
- time_t now,
- int past_tolerance, int future_tolerance);
-
-/** Global TLS contexts. We keep them here because nobody else needs
- * to touch them.
- *
- * @{ */
-STATIC tor_tls_context_t *server_tls_context = NULL;
-STATIC tor_tls_context_t *client_tls_context = NULL;
-/**@}*/
-
-/** True iff tor_tls_init() has been called. */
-static int tls_library_is_initialized = 0;
-
-/* Module-internal error codes. */
-#define TOR_TLS_SYSCALL_ (MIN_TOR_TLS_ERROR_VAL_ - 2)
-#define TOR_TLS_ZERORETURN_ (MIN_TOR_TLS_ERROR_VAL_ - 1)
-
-/** Write a description of the current state of <b>tls</b> into the
- * <b>sz</b>-byte buffer at <b>buf</b>. */
-void
-tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz)
-{
- const char *ssl_state;
- const char *tortls_state;
-
- if (PREDICT_UNLIKELY(!tls || !tls->ssl)) {
- strlcpy(buf, "(No SSL object)", sz);
- return;
- }
-
- ssl_state = SSL_state_string_long(tls->ssl);
- switch (tls->state) {
-#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break
- CASE(HANDSHAKE);
- CASE(OPEN);
- CASE(GOTCLOSE);
- CASE(SENTCLOSE);
- CASE(CLOSED);
- CASE(RENEGOTIATE);
-#undef CASE
- case TOR_TLS_ST_BUFFEREVENT:
- tortls_state = "";
- break;
- default:
- tortls_state = " in unknown TLS state";
- break;
- }
-
- tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state);
-}
-
-/** Log a single error <b>err</b> as returned by ERR_get_error(), which was
- * received while performing an operation <b>doing</b> on <b>tls</b>. Log
- * the message at <b>severity</b>, in log domain <b>domain</b>. */
-void
-tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
- int severity, int domain, const char *doing)
-{
- const char *state = NULL, *addr;
- const char *msg, *lib, *func;
-
- state = (tls && tls->ssl)?SSL_state_string_long(tls->ssl):"---";
-
- addr = tls ? tls->address : NULL;
-
- /* Some errors are known-benign, meaning they are the fault of the other
- * side of the connection. The caller doesn't know this, so override the
- * priority for those cases. */
- switch (ERR_GET_REASON(err)) {
- case SSL_R_HTTP_REQUEST:
- case SSL_R_HTTPS_PROXY_REQUEST:
- case SSL_R_RECORD_LENGTH_MISMATCH:
-#ifndef OPENSSL_1_1_API
- case SSL_R_RECORD_TOO_LARGE:
-#endif
- case SSL_R_UNKNOWN_PROTOCOL:
- case SSL_R_UNSUPPORTED_PROTOCOL:
- severity = LOG_INFO;
- break;
- default:
- break;
- }
-
- 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 (doing) {
- tor_log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
- doing, addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- } else {
- tor_log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
- addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- }
-}
-
-/** Log all pending tls errors at level <b>severity</b> in log domain
- * <b>domain</b>. Use <b>doing</b> to describe our current activities.
- */
-STATIC void
-tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
-{
- unsigned long err;
-
- while ((err = ERR_get_error()) != 0) {
- tor_tls_log_one_error(tls, err, severity, domain, doing);
- }
-}
-
-/** Convert an errno (or a WSAerrno on windows) into a TOR_TLS_* error
- * code. */
-STATIC int
-tor_errno_to_tls_error(int e)
-{
- switch (e) {
- case SOCK_ERRNO(ECONNRESET): // most common
- return TOR_TLS_ERROR_CONNRESET;
- case SOCK_ERRNO(ETIMEDOUT):
- return TOR_TLS_ERROR_TIMEOUT;
- case SOCK_ERRNO(EHOSTUNREACH):
- case SOCK_ERRNO(ENETUNREACH):
- return TOR_TLS_ERROR_NO_ROUTE;
- case SOCK_ERRNO(ECONNREFUSED):
- return TOR_TLS_ERROR_CONNREFUSED; // least common
- default:
- return TOR_TLS_ERROR_MISC;
- }
-}
-
-/** Given a TOR_TLS_* error code, return a string equivalent. */
-const char *
-tor_tls_err_to_string(int err)
-{
- if (err >= 0)
- return "[Not an error.]";
- switch (err) {
- case TOR_TLS_ERROR_MISC: return "misc error";
- case TOR_TLS_ERROR_IO: return "unexpected close";
- case TOR_TLS_ERROR_CONNREFUSED: return "connection refused";
- case TOR_TLS_ERROR_CONNRESET: return "connection reset";
- case TOR_TLS_ERROR_NO_ROUTE: return "host unreachable";
- case TOR_TLS_ERROR_TIMEOUT: return "connection timed out";
- case TOR_TLS_CLOSE: return "closed";
- case TOR_TLS_WANTREAD: return "want to read";
- case TOR_TLS_WANTWRITE: return "want to write";
- default: return "(unknown error code)";
- }
-}
-
-#define CATCH_SYSCALL 1
-#define CATCH_ZERO 2
-
-/** Given a TLS object and the result of an SSL_* call, use
- * SSL_get_error to determine whether an error has occurred, and if so
- * which one. Return one of TOR_TLS_{DONE|WANTREAD|WANTWRITE|ERROR}.
- * If extra&CATCH_SYSCALL is true, return TOR_TLS_SYSCALL_ instead of
- * reporting syscall errors. If extra&CATCH_ZERO is true, return
- * TOR_TLS_ZERORETURN_ instead of reporting zero-return errors.
- *
- * If an error has occurred, log it at level <b>severity</b> and describe the
- * current action as <b>doing</b>.
- */
-STATIC int
-tor_tls_get_error(tor_tls_t *tls, int r, int extra,
- const char *doing, int severity, int domain)
-{
- int err = SSL_get_error(tls->ssl, r);
- int tor_error = TOR_TLS_ERROR_MISC;
- switch (err) {
- case SSL_ERROR_NONE:
- return TOR_TLS_DONE;
- case SSL_ERROR_WANT_READ:
- return TOR_TLS_WANTREAD;
- case SSL_ERROR_WANT_WRITE:
- return TOR_TLS_WANTWRITE;
- case SSL_ERROR_SYSCALL:
- if (extra&CATCH_SYSCALL)
- return TOR_TLS_SYSCALL_;
- if (r == 0) {
- tor_log(severity, LD_NET, "TLS error: unexpected close while %s (%s)",
- doing, SSL_state_string_long(tls->ssl));
- tor_error = TOR_TLS_ERROR_IO;
- } else {
- int e = tor_socket_errno(tls->socket);
- tor_log(severity, LD_NET,
- "TLS error: <syscall error while %s> (errno=%d: %s; state=%s)",
- doing, e, tor_socket_strerror(e),
- SSL_state_string_long(tls->ssl));
- tor_error = tor_errno_to_tls_error(e);
- }
- tls_log_errors(tls, severity, domain, doing);
- return tor_error;
- case SSL_ERROR_ZERO_RETURN:
- if (extra&CATCH_ZERO)
- return TOR_TLS_ZERORETURN_;
- tor_log(severity, LD_NET, "TLS connection closed while %s in state %s",
- doing, SSL_state_string_long(tls->ssl));
- tls_log_errors(tls, severity, domain, doing);
- return TOR_TLS_CLOSE;
- default:
- tls_log_errors(tls, severity, domain, doing);
- return TOR_TLS_ERROR_MISC;
- }
-}
-
-/** Initialize OpenSSL, unless it has already been initialized.
- */
-static void
-tor_tls_init(void)
-{
- check_no_tls_errors();
-
- if (!tls_library_is_initialized) {
-#ifdef OPENSSL_1_1_API
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
-#else
- SSL_library_init();
- SSL_load_error_strings();
-#endif
-
-#if (SIZEOF_VOID_P >= 8 && \
- OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1))
- long version = OpenSSL_version_num();
-
- /* LCOV_EXCL_START : we can't test these lines on the same machine */
- if (version >= OPENSSL_V_SERIES(1,0,1)) {
- /* Warn if we could *almost* be running with much faster ECDH.
- If we're built for a 64-bit target, using OpenSSL 1.0.1, but we
- don't have one of the built-in __uint128-based speedups, we are
- just one build operation away from an accelerated handshake.
-
- (We could be looking at OPENSSL_NO_EC_NISTP_64_GCC_128 instead of
- doing this test, but that gives compile-time options, not runtime
- behavior.)
- */
- EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- const EC_GROUP *g = key ? EC_KEY_get0_group(key) : NULL;
- const EC_METHOD *m = g ? EC_GROUP_method_of(g) : NULL;
- const int warn = (m == EC_GFp_simple_method() ||
- m == EC_GFp_mont_method() ||
- m == EC_GFp_nist_method());
- EC_KEY_free(key);
-
- if (warn)
- log_notice(LD_GENERAL, "We were built to run on a 64-bit CPU, with "
- "OpenSSL 1.0.1 or later, but with a version of OpenSSL "
- "that apparently lacks accelerated support for the NIST "
- "P-224 and P-256 groups. Building openssl with such "
- "support (using the enable-ec_nistp_64_gcc_128 option "
- "when configuring it) would make ECDH much faster.");
- }
- /* LCOV_EXCL_STOP */
-#endif /* (SIZEOF_VOID_P >= 8 && ... */
-
- tor_tls_allocate_tor_tls_object_ex_data_index();
-
- tls_library_is_initialized = 1;
- }
-}
-
-/** Free all global TLS structures. */
-void
-tor_tls_free_all(void)
-{
- check_no_tls_errors();
-
- if (server_tls_context) {
- tor_tls_context_t *ctx = server_tls_context;
- server_tls_context = NULL;
- tor_tls_context_decref(ctx);
- }
- if (client_tls_context) {
- tor_tls_context_t *ctx = client_tls_context;
- client_tls_context = NULL;
- tor_tls_context_decref(ctx);
- }
-}
-
-/** We need to give OpenSSL a callback to verify certificates. This is
- * it: We always accept peer certs and complete the handshake. We
- * don't validate them until later.
- */
-STATIC int
-always_accept_verify_cb(int preverify_ok,
- X509_STORE_CTX *x509_ctx)
-{
- (void) preverify_ok;
- (void) x509_ctx;
- return 1;
-}
-
-/** Return a newly allocated X509 name with commonName <b>cname</b>. */
-static X509_NAME *
-tor_x509_name_new(const char *cname)
-{
- int nid;
- X509_NAME *name;
- /* LCOV_EXCL_BR_START : these branches will only fail on OOM errors */
- if (!(name = X509_NAME_new()))
- return NULL;
- if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
- if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
- (unsigned char*)cname, -1, -1, 0)))
- goto error;
- /* LCOV_EXCL_BR_STOP */
- return name;
-
- /* LCOV_EXCL_START : these lines will only execute on out of memory errors*/
- error:
- X509_NAME_free(name);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Generate and sign an X509 certificate with the public key <b>rsa</b>,
- * signed by the private key <b>rsa_sign</b>. The commonName of the
- * certificate will be <b>cname</b>; the commonName of the issuer will be
- * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b>
- * seconds, starting from some time in the past.
- *
- * Return a certificate on success, NULL on failure.
- */
-MOCK_IMPL(STATIC X509 *,
-tor_tls_create_certificate,(crypto_pk_t *rsa,
- crypto_pk_t *rsa_sign,
- const char *cname,
- const char *cname_sign,
- unsigned int cert_lifetime))
-{
- /* OpenSSL generates self-signed certificates with random 64-bit serial
- * numbers, so let's do that too. */
-#define SERIAL_NUMBER_SIZE 8
-
- time_t start_time, end_time;
- BIGNUM *serial_number = NULL;
- unsigned char serial_tmp[SERIAL_NUMBER_SIZE];
- EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
- X509 *x509 = NULL;
- X509_NAME *name = NULL, *name_issuer=NULL;
-
- tor_tls_init();
-
- /* Make sure we're part-way through the certificate lifetime, rather
- * than having it start right now. Don't choose quite uniformly, since
- * then we might pick a time where we're about to expire. Lastly, be
- * sure to start on a day boundary. */
- time_t now = time(NULL);
- /* Our certificate lifetime will be cert_lifetime no matter what, but if we
- * start cert_lifetime in the past, we'll have 0 real lifetime. instead we
- * start up to (cert_lifetime - min_real_lifetime - start_granularity) in
- * the past. */
- const time_t min_real_lifetime = 24*3600;
- const time_t start_granularity = 24*3600;
- time_t earliest_start_time;
- /* Don't actually start in the future! */
- if (cert_lifetime <= min_real_lifetime + start_granularity) {
- earliest_start_time = now - 1;
- } else {
- earliest_start_time = now + min_real_lifetime + start_granularity
- - cert_lifetime;
- }
- start_time = crypto_rand_time_range(earliest_start_time, now);
- /* Round the start time back to the start of a day. */
- start_time -= start_time % start_granularity;
-
- end_time = start_time + cert_lifetime;
-
- tor_assert(rsa);
- tor_assert(cname);
- tor_assert(rsa_sign);
- tor_assert(cname_sign);
- if (!(sign_pkey = crypto_pk_get_evp_pkey_(rsa_sign,1)))
- goto error;
- if (!(pkey = crypto_pk_get_evp_pkey_(rsa,0)))
- goto error;
- if (!(x509 = X509_new()))
- goto error;
- if (!(X509_set_version(x509, 2)))
- goto error;
-
- { /* our serial number is 8 random bytes. */
- crypto_rand((char *)serial_tmp, sizeof(serial_tmp));
- if (!(serial_number = BN_bin2bn(serial_tmp, sizeof(serial_tmp), NULL)))
- goto error;
- if (!(BN_to_ASN1_INTEGER(serial_number, X509_get_serialNumber(x509))))
- goto error;
- }
-
- if (!(name = tor_x509_name_new(cname)))
- goto error;
- if (!(X509_set_subject_name(x509, name)))
- goto error;
- if (!(name_issuer = tor_x509_name_new(cname_sign)))
- goto error;
- if (!(X509_set_issuer_name(x509, name_issuer)))
- goto error;
-
- if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
- goto error;
- if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
- goto error;
- if (!X509_set_pubkey(x509, pkey))
- goto error;
-
- if (!X509_sign(x509, sign_pkey, EVP_sha256()))
- goto error;
-
- goto done;
- error:
- if (x509) {
- X509_free(x509);
- x509 = NULL;
- }
- done:
- tls_log_errors(NULL, LOG_WARN, LD_NET, "generating certificate");
- if (sign_pkey)
- EVP_PKEY_free(sign_pkey);
- if (pkey)
- EVP_PKEY_free(pkey);
- if (serial_number)
- BN_clear_free(serial_number);
- if (name)
- X509_NAME_free(name);
- if (name_issuer)
- X509_NAME_free(name_issuer);
- return x509;
-
-#undef SERIAL_NUMBER_SIZE
-}
-
-/** List of ciphers that servers should select from when the client might be
- * claiming extra unsupported ciphers in order to avoid fingerprinting. */
-static const char SERVER_CIPHER_LIST[] =
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- /* This one can never actually get selected, since if the client lists it,
- * we will assume that the client is honest, and not use this list.
- * Nonetheless we list it if it's available, so that the server doesn't
- * conclude that it has no valid ciphers if it's running with TLS1.3.
- */
- TLS1_3_TXT_AES_128_GCM_SHA256 ":"
-#endif
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":"
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA;
-
-/** List of ciphers that servers should select from when we actually have
- * our choice of what cipher to use. */
-static const char UNRESTRICTED_SERVER_CIPHER_LIST[] =
- /* Here are the TLS 1.3 ciphers we like, in the order we prefer. */
-#ifdef TLS1_3_TXT_AES_256_GCM_SHA384
- TLS1_3_TXT_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256
- TLS1_3_TXT_CHACHA20_POLY1305_SHA256 ":"
-#endif
-#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
- TLS1_3_TXT_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_3_TXT_AES_128_CCM_SHA256
- TLS1_3_TXT_AES_128_CCM_SHA256 ":"
-#endif
-
- /* This list is autogenerated with the gen_server_ciphers.py script;
- * don't hand-edit it. */
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA ":"
-#endif
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_CCM
- TLS1_TXT_DHE_RSA_WITH_AES_256_CCM ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_CCM
- TLS1_TXT_DHE_RSA_WITH_AES_128_CCM ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 ":"
-#endif
- /* Required */
- TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":"
- /* Required */
- TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":"
-#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 ":"
-#endif
-#ifdef TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305
- TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305
-#endif
- ;
-
-/* Note: to set up your own private testing network with link crypto
- * disabled, set your Tors' cipher list to
- * (SSL3_TXT_RSA_NULL_SHA). If you do this, you won't be able to communicate
- * with any of the "real" Tors, though. */
-
-#define CIPHER(id, name) name ":"
-#define XCIPHER(id, name)
-/** List of ciphers that clients should advertise, omitting items that
- * our OpenSSL doesn't know about. */
-static const char CLIENT_CIPHER_LIST[] =
-#include "ciphers.inc"
- /* Tell it not to use SSLv2 ciphers, so that it can select an SSLv3 version
- * of any cipher we say. */
- "!SSLv2"
- ;
-#undef CIPHER
-#undef XCIPHER
-
-/** Free all storage held in <b>cert</b> */
-void
-tor_x509_cert_free_(tor_x509_cert_t *cert)
-{
- if (! cert)
- return;
- if (cert->cert)
- X509_free(cert->cert);
- tor_free(cert->encoded);
- memwipe(cert, 0x03, sizeof(*cert));
- /* LCOV_EXCL_BR_START since cert will never be NULL here */
- tor_free(cert);
- /* LCOV_EXCL_BR_STOP */
-}
-
-/**
- * Allocate a new tor_x509_cert_t to hold the certificate "x509_cert".
- *
- * Steals a reference to x509_cert.
- */
-MOCK_IMPL(STATIC tor_x509_cert_t *,
-tor_x509_cert_new,(X509 *x509_cert))
-{
- tor_x509_cert_t *cert;
- EVP_PKEY *pkey;
- RSA *rsa;
- int length;
- unsigned char *buf = NULL;
-
- if (!x509_cert)
- return NULL;
-
- length = i2d_X509(x509_cert, &buf);
- cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
- if (length <= 0 || buf == NULL) {
- goto err;
- }
- cert->encoded_len = (size_t) length;
- cert->encoded = tor_malloc(length);
- memcpy(cert->encoded, buf, length);
- OPENSSL_free(buf);
-
- cert->cert = x509_cert;
-
- crypto_common_digests(&cert->cert_digests,
- (char*)cert->encoded, cert->encoded_len);
-
- if ((pkey = X509_get_pubkey(x509_cert)) &&
- (rsa = EVP_PKEY_get1_RSA(pkey))) {
- crypto_pk_t *pk = crypto_new_pk_from_rsa_(rsa);
- if (crypto_pk_get_common_digests(pk, &cert->pkey_digests) < 0) {
- crypto_pk_free(pk);
- EVP_PKEY_free(pkey);
- goto err;
- }
-
- cert->pkey_digests_set = 1;
- crypto_pk_free(pk);
- EVP_PKEY_free(pkey);
- }
-
- return cert;
- err:
- /* LCOV_EXCL_START for the same reason as the exclusion above */
- tor_free(cert);
- log_err(LD_CRYPTO, "Couldn't wrap encoded X509 certificate.");
- X509_free(x509_cert);
- return NULL;
- /* LCOV_EXCL_STOP */
-}
-
-/** Return a new copy of <b>cert</b>. */
-tor_x509_cert_t *
-tor_x509_cert_dup(const tor_x509_cert_t *cert)
-{
- tor_assert(cert);
- X509 *x509 = cert->cert;
- return tor_x509_cert_new(X509_dup(x509));
-}
-
-/** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>,
- * from a <b>certificate</b>. Return a newly allocated tor_x509_cert_t on
- * success and NULL on failure. */
-tor_x509_cert_t *
-tor_x509_cert_decode(const uint8_t *certificate, size_t certificate_len)
-{
- X509 *x509;
- const unsigned char *cp = (const unsigned char *)certificate;
- tor_x509_cert_t *newcert;
- tor_assert(certificate);
- check_no_tls_errors();
-
- if (certificate_len > INT_MAX)
- goto err;
-
- x509 = d2i_X509(NULL, &cp, (int)certificate_len);
-
- if (!x509)
- goto err; /* Couldn't decode */
- if (cp - certificate != (int)certificate_len) {
- X509_free(x509);
- goto err; /* Didn't use all the bytes */
- }
- newcert = tor_x509_cert_new(x509);
- if (!newcert) {
- goto err;
- }
- if (newcert->encoded_len != certificate_len ||
- fast_memneq(newcert->encoded, certificate, certificate_len)) {
- /* Cert wasn't in DER */
- tor_x509_cert_free(newcert);
- goto err;
- }
- return newcert;
- err:
- tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "decoding a certificate");
- return NULL;
-}
-
-/** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER
- * representation and length, respectively. */
-void
-tor_x509_cert_get_der(const tor_x509_cert_t *cert,
- const uint8_t **encoded_out, size_t *size_out)
-{
- tor_assert(cert);
- tor_assert(encoded_out);
- tor_assert(size_out);
- *encoded_out = cert->encoded;
- *size_out = cert->encoded_len;
-}
-
-/** Return a set of digests for the public key in <b>cert</b>, or NULL if this
- * cert's public key is not one we know how to take the digest of. */
-const common_digests_t *
-tor_x509_cert_get_id_digests(const tor_x509_cert_t *cert)
-{
- if (cert->pkey_digests_set)
- return &cert->pkey_digests;
- else
- return NULL;
-}
-
-/** Return a set of digests for the public key in <b>cert</b>. */
-const common_digests_t *
-tor_x509_cert_get_cert_digests(const tor_x509_cert_t *cert)
-{
- return &cert->cert_digests;
-}
-
-/** Remove a reference to <b>ctx</b>, and free it if it has no more
- * references. */
-static void
-tor_tls_context_decref(tor_tls_context_t *ctx)
-{
- tor_assert(ctx);
- if (--ctx->refcnt == 0) {
- SSL_CTX_free(ctx->ctx);
- tor_x509_cert_free(ctx->my_link_cert);
- tor_x509_cert_free(ctx->my_id_cert);
- tor_x509_cert_free(ctx->my_auth_cert);
- crypto_pk_free(ctx->link_key);
- crypto_pk_free(ctx->auth_key);
- /* LCOV_EXCL_BR_START since ctx will never be NULL here */
- tor_free(ctx);
- /* LCOV_EXCL_BR_STOP */
- }
-}
-
-/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
- * and ID certificate that we're currently using for our V3 in-protocol
- * handshake's certificate chain. If <b>server</b> is true, provide the certs
- * that we use in server mode (auth, ID); otherwise, provide the certs that we
- * use in client mode. (link, ID) */
-int
-tor_tls_get_my_certs(int server,
- const tor_x509_cert_t **link_cert_out,
- const tor_x509_cert_t **id_cert_out)
-{
- tor_tls_context_t *ctx = server ? server_tls_context : client_tls_context;
- if (! ctx)
- return -1;
- if (link_cert_out)
- *link_cert_out = server ? ctx->my_link_cert : ctx->my_auth_cert;
- if (id_cert_out)
- *id_cert_out = ctx->my_id_cert;
- return 0;
-}
-
-/**
- * Return the authentication key that we use to authenticate ourselves as a
- * client in the V3 in-protocol handshake.
- */
-crypto_pk_t *
-tor_tls_get_my_client_auth_key(void)
-{
- if (! client_tls_context)
- return NULL;
- return client_tls_context->auth_key;
-}
-
-/**
- * Return a newly allocated copy of the public key that a certificate
- * certifies. Watch out! This returns NULL if the cert's key is not RSA.
- */
-crypto_pk_t *
-tor_tls_cert_get_key(tor_x509_cert_t *cert)
-{
- crypto_pk_t *result = NULL;
- EVP_PKEY *pkey = X509_get_pubkey(cert->cert);
- RSA *rsa;
- if (!pkey)
- return NULL;
- rsa = EVP_PKEY_get1_RSA(pkey);
- if (!rsa) {
- EVP_PKEY_free(pkey);
- return NULL;
- }
- result = crypto_new_pk_from_rsa_(rsa);
- EVP_PKEY_free(pkey);
- return result;
-}
-
-/** Return true iff the other side of <b>tls</b> has authenticated to us, and
- * the key certified in <b>cert</b> is the same as the key they used to do it.
- */
-MOCK_IMPL(int,
-tor_tls_cert_matches_key,(const tor_tls_t *tls, const tor_x509_cert_t *cert))
-{
- X509 *peercert = SSL_get_peer_certificate(tls->ssl);
- EVP_PKEY *link_key = NULL, *cert_key = NULL;
- int result;
-
- if (!peercert)
- return 0;
- link_key = X509_get_pubkey(peercert);
- cert_key = X509_get_pubkey(cert->cert);
-
- result = link_key && cert_key && EVP_PKEY_cmp(cert_key, link_key) == 1;
-
- X509_free(peercert);
- if (link_key)
- EVP_PKEY_free(link_key);
- if (cert_key)
- EVP_PKEY_free(cert_key);
-
- return result;
-}
-
-/** Check whether <b>cert</b> is well-formed, currently live, and correctly
- * signed by the public key in <b>signing_cert</b>. If <b>check_rsa_1024</b>,
- * make sure that it has an RSA key with 1024 bits; otherwise, just check that
- * the key is long enough. Return 1 if the cert is good, and 0 if it's bad or
- * we couldn't check it. */
-int
-tor_tls_cert_is_valid(int severity,
- const tor_x509_cert_t *cert,
- const tor_x509_cert_t *signing_cert,
- time_t now,
- int check_rsa_1024)
-{
- check_no_tls_errors();
- EVP_PKEY *cert_key;
- int r, key_ok = 0;
-
- if (!signing_cert || !cert)
- goto bad;
-
- EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert);
- if (!signing_key)
- goto bad;
- r = X509_verify(cert->cert, signing_key);
- EVP_PKEY_free(signing_key);
- if (r <= 0)
- goto bad;
-
- /* okay, the signature checked out right. Now let's check the check the
- * lifetime. */
- if (check_cert_lifetime_internal(severity, cert->cert, now,
- 48*60*60, 30*24*60*60) < 0)
- goto bad;
-
- cert_key = X509_get_pubkey(cert->cert);
- if (check_rsa_1024 && cert_key) {
- RSA *rsa = EVP_PKEY_get1_RSA(cert_key);
-#ifdef OPENSSL_1_1_API
- if (rsa && RSA_bits(rsa) == 1024)
-#else
- if (rsa && BN_num_bits(rsa->n) == 1024)
-#endif
- key_ok = 1;
- if (rsa)
- RSA_free(rsa);
- } else if (cert_key) {
- int min_bits = 1024;
-#ifdef EVP_PKEY_EC
- if (EVP_PKEY_base_id(cert_key) == EVP_PKEY_EC)
- min_bits = 128;
-#endif
- if (EVP_PKEY_bits(cert_key) >= min_bits)
- key_ok = 1;
- }
- EVP_PKEY_free(cert_key);
- if (!key_ok)
- goto bad;
-
- /* XXXX compare DNs or anything? */
-
- return 1;
- bad:
- tls_log_errors(NULL, LOG_INFO, LD_CRYPTO, "checking a certificate");
- return 0;
-}
-
-/** Increase the reference count of <b>ctx</b>. */
-static void
-tor_tls_context_incref(tor_tls_context_t *ctx)
-{
- ++ctx->refcnt;
-}
-
-/** Create new global client and server TLS contexts.
- *
- * If <b>server_identity</b> is NULL, this will not generate a server
- * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
- * the same TLS context for incoming and outgoing connections, and
- * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256}
- * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use
- * the default ECDHE group. */
-int
-tor_tls_context_init(unsigned flags,
- crypto_pk_t *client_identity,
- crypto_pk_t *server_identity,
- unsigned int key_lifetime)
-{
- int rv1 = 0;
- int rv2 = 0;
- const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER;
- check_no_tls_errors();
-
- if (is_public_server) {
- tor_tls_context_t *new_ctx;
- tor_tls_context_t *old_ctx;
-
- tor_assert(server_identity != NULL);
-
- rv1 = tor_tls_context_init_one(&server_tls_context,
- server_identity,
- key_lifetime, flags, 0);
-
- if (rv1 >= 0) {
- new_ctx = server_tls_context;
- tor_tls_context_incref(new_ctx);
- old_ctx = client_tls_context;
- client_tls_context = new_ctx;
-
- if (old_ctx != NULL) {
- tor_tls_context_decref(old_ctx);
- }
- }
- } else {
- if (server_identity != NULL) {
- rv1 = tor_tls_context_init_one(&server_tls_context,
- server_identity,
- key_lifetime,
- flags,
- 0);
- } else {
- tor_tls_context_t *old_ctx = server_tls_context;
- server_tls_context = NULL;
-
- if (old_ctx != NULL) {
- tor_tls_context_decref(old_ctx);
- }
- }
-
- rv2 = tor_tls_context_init_one(&client_tls_context,
- client_identity,
- key_lifetime,
- flags,
- 1);
- }
-
- tls_log_errors(NULL, LOG_WARN, LD_CRYPTO, "constructing a TLS context");
- return MIN(rv1, rv2);
-}
-
-/** Create a new global TLS context.
- *
- * You can call this function multiple times. Each time you call it,
- * it generates new certificates; all new connections will use
- * the new SSL context.
- */
-STATIC int
-tor_tls_context_init_one(tor_tls_context_t **ppcontext,
- crypto_pk_t *identity,
- unsigned int key_lifetime,
- unsigned int flags,
- int is_client)
-{
- tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
- key_lifetime,
- flags,
- is_client);
- tor_tls_context_t *old_ctx = *ppcontext;
-
- if (new_ctx != NULL) {
- *ppcontext = new_ctx;
-
- /* Free the old context if one existed. */
- if (old_ctx != NULL) {
- /* This is safe even if there are open connections: we reference-
- * count tor_tls_context_t objects. */
- tor_tls_context_decref(old_ctx);
- }
- }
-
- return ((new_ctx != NULL) ? 0 : -1);
-}
-
-/** The group we should use for ecdhe when none was selected. */
-#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1
-
-#define RSA_LINK_KEY_BITS 2048
-
-/** Create a new TLS context for use with Tor TLS handshakes.
- * <b>identity</b> should be set to the identity key used to sign the
- * certificate.
- */
-STATIC tor_tls_context_t *
-tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
- unsigned flags, int is_client)
-{
- crypto_pk_t *rsa = NULL, *rsa_auth = NULL;
- EVP_PKEY *pkey = NULL;
- tor_tls_context_t *result = NULL;
- X509 *cert = NULL, *idcert = NULL, *authcert = NULL;
- char *nickname = NULL, *nn2 = NULL;
-
- tor_tls_init();
- nickname = crypto_random_hostname(8, 20, "www.", ".net");
-#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
- nn2 = crypto_random_hostname(8, 20, "www.", ".net");
-#else
- nn2 = crypto_random_hostname(8, 20, "www.", ".com");
-#endif
-
- /* Generate short-term RSA key for use with TLS. */
- if (!(rsa = crypto_pk_new()))
- goto error;
- if (crypto_pk_generate_key_with_bits(rsa, RSA_LINK_KEY_BITS)<0)
- goto error;
- if (!is_client) {
- /* Generate short-term RSA key for use in the in-protocol ("v3")
- * authentication handshake. */
- if (!(rsa_auth = crypto_pk_new()))
- goto error;
- if (crypto_pk_generate_key(rsa_auth)<0)
- goto error;
- /* Create a link certificate signed by identity key. */
- cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
- key_lifetime);
- /* Create self-signed certificate for identity key. */
- idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
- IDENTITY_CERT_LIFETIME);
- /* Create an authentication certificate signed by identity key. */
- authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2,
- key_lifetime);
- if (!cert || !idcert || !authcert) {
- log_warn(LD_CRYPTO, "Error creating certificate");
- goto error;
- }
- }
-
- result = tor_malloc_zero(sizeof(tor_tls_context_t));
- result->refcnt = 1;
- if (!is_client) {
- result->my_link_cert = tor_x509_cert_new(X509_dup(cert));
- result->my_id_cert = tor_x509_cert_new(X509_dup(idcert));
- result->my_auth_cert = tor_x509_cert_new(X509_dup(authcert));
- if (!result->my_link_cert || !result->my_id_cert || !result->my_auth_cert)
- goto error;
- result->link_key = crypto_pk_dup_key(rsa);
- result->auth_key = crypto_pk_dup_key(rsa_auth);
- }
-
-#if 0
- /* Tell OpenSSL to only use TLS1. This may have subtly different results
- * from SSLv23_method() with SSLv2 and SSLv3 disabled, so we need to do some
- * investigation before we consider adjusting it. It should be compatible
- * with existing Tors. */
- if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
- goto error;
-#endif /* 0 */
-
- /* Tell OpenSSL to use TLS 1.0 or later but not SSL2 or SSL3. */
-#ifdef HAVE_TLS_METHOD
- if (!(result->ctx = SSL_CTX_new(TLS_method())))
- goto error;
-#else
- if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
- goto error;
-#endif /* defined(HAVE_TLS_METHOD) */
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3);
-
- /* Prefer the server's ordering of ciphers: the client's ordering has
- * historically been chosen for fingerprinting resistance. */
- SSL_CTX_set_options(result->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
-
- /* Disable TLS tickets if they're supported. We never want to use them;
- * using them can make our perfect forward secrecy a little worse, *and*
- * create an opportunity to fingerprint us (since it's unusual to use them
- * with TLS sessions turned off).
- *
- * In 0.2.4, clients advertise support for them though, to avoid a TLS
- * distinguishability vector. This can give us worse PFS, though, if we
- * get a server that doesn't set SSL_OP_NO_TICKET. With luck, there will
- * be few such servers by the time 0.2.4 is more stable.
- */
-#ifdef SSL_OP_NO_TICKET
- if (! is_client) {
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_TICKET);
- }
-#endif
-
- SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE);
- SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_ECDH_USE);
-
-#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
- SSL_CTX_set_options(result->ctx,
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-#endif
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data.
- */
- {
- SSL_CTX_set_options(result->ctx,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
- }
-
- /* Don't actually allow compression; it uses RAM and time, it makes TLS
- * vulnerable to CRIME-style attacks, and most of the data we transmit over
- * TLS is encrypted (and therefore uncompressible) anyway. */
-#ifdef SSL_OP_NO_COMPRESSION
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_COMPRESSION);
-#endif
-#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
-#ifndef OPENSSL_NO_COMP
- if (result->ctx->comp_methods)
- result->ctx->comp_methods = NULL;
-#endif
-#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) */
-
-#ifdef SSL_MODE_RELEASE_BUFFERS
- SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
- if (! is_client) {
- if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
- goto error;
- X509_free(cert); /* We just added a reference to cert. */
- cert=NULL;
- if (idcert) {
- X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
- tor_assert(s);
- X509_STORE_add_cert(s, idcert);
- X509_free(idcert); /* The context now owns the reference to idcert */
- idcert = NULL;
- }
- }
- SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
- if (!is_client) {
- tor_assert(rsa);
- if (!(pkey = crypto_pk_get_evp_pkey_(rsa,1)))
- goto error;
- if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
- goto error;
- EVP_PKEY_free(pkey);
- pkey = NULL;
- if (!SSL_CTX_check_private_key(result->ctx))
- goto error;
- }
- {
- crypto_dh_t *dh = crypto_dh_new(DH_TYPE_TLS);
- tor_assert(dh);
- SSL_CTX_set_tmp_dh(result->ctx, crypto_dh_get_dh_(dh));
- crypto_dh_free(dh);
- }
- if (! is_client) {
- int nid;
- EC_KEY *ec_key;
- if (flags & TOR_TLS_CTX_USE_ECDHE_P224)
- nid = NID_secp224r1;
- else if (flags & TOR_TLS_CTX_USE_ECDHE_P256)
- nid = NID_X9_62_prime256v1;
- else
- nid = NID_tor_default_ecdhe_group;
- /* Use P-256 for ECDHE. */
- ec_key = EC_KEY_new_by_curve_name(nid);
- if (ec_key != NULL) /*XXXX Handle errors? */
- SSL_CTX_set_tmp_ecdh(result->ctx, ec_key);
- EC_KEY_free(ec_key);
- }
- SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER,
- always_accept_verify_cb);
- /* let us realloc bufs that we're writing from */
- SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
-
- if (rsa)
- crypto_pk_free(rsa);
- if (rsa_auth)
- crypto_pk_free(rsa_auth);
- X509_free(authcert);
- tor_free(nickname);
- tor_free(nn2);
- return result;
-
- error:
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating TLS context");
- tor_free(nickname);
- tor_free(nn2);
- if (pkey)
- EVP_PKEY_free(pkey);
- if (rsa)
- crypto_pk_free(rsa);
- if (rsa_auth)
- crypto_pk_free(rsa_auth);
- if (result)
- tor_tls_context_decref(result);
- if (cert)
- X509_free(cert);
- if (idcert)
- X509_free(idcert);
- if (authcert)
- X509_free(authcert);
- return NULL;
-}
-
-/** Invoked when a TLS state changes: log the change at severity 'debug' */
-STATIC void
-tor_tls_debug_state_callback(const SSL *ssl, int type, int val)
-{
- /* LCOV_EXCL_START since this depends on whether debug is captured or not */
- log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].",
- ssl, SSL_state_string_long(ssl), type, val);
- /* LCOV_EXCL_STOP */
-}
-
-/* Return the name of the negotiated ciphersuite in use on <b>tls</b> */
-const char *
-tor_tls_get_ciphersuite_name(tor_tls_t *tls)
-{
- return SSL_get_cipher(tls->ssl);
-}
-
-/* Here's the old V2 cipher list we sent from 0.2.1.1-alpha up to
- * 0.2.3.17-beta. If a client is using this list, we can't believe the ciphers
- * that it claims to support. We'll prune this list to remove the ciphers
- * *we* don't recognize. */
-STATIC uint16_t v2_cipher_list[] = {
- 0xc00a, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */
- 0xc014, /* TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA */
- 0x0039, /* TLS1_TXT_DHE_RSA_WITH_AES_256_SHA */
- 0x0038, /* TLS1_TXT_DHE_DSS_WITH_AES_256_SHA */
- 0xc00f, /* TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA */
- 0xc005, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA */
- 0x0035, /* TLS1_TXT_RSA_WITH_AES_256_SHA */
- 0xc007, /* TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA */
- 0xc009, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */
- 0xc011, /* TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA */
- 0xc013, /* TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA */
- 0x0033, /* TLS1_TXT_DHE_RSA_WITH_AES_128_SHA */
- 0x0032, /* TLS1_TXT_DHE_DSS_WITH_AES_128_SHA */
- 0xc00c, /* TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA */
- 0xc00e, /* TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA */
- 0xc002, /* TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA */
- 0xc004, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA */
- 0x0004, /* SSL3_TXT_RSA_RC4_128_MD5 */
- 0x0005, /* SSL3_TXT_RSA_RC4_128_SHA */
- 0x002f, /* TLS1_TXT_RSA_WITH_AES_128_SHA */
- 0xc008, /* TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA */
- 0xc012, /* TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA */
- 0x0016, /* SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA */
- 0x0013, /* SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA */
- 0xc00d, /* TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA */
- 0xc003, /* TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA */
- 0xfeff, /* SSL3_TXT_RSA_FIPS_WITH_3DES_EDE_CBC_SHA */
- 0x000a, /* SSL3_TXT_RSA_DES_192_CBC3_SHA */
- 0
-};
-/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */
-static int v2_cipher_list_pruned = 0;
-
-/** Return 0 if <b>m</b> does not support the cipher with ID <b>cipher</b>;
- * return 1 if it does support it, or if we have no way to tell. */
-STATIC int
-find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
-{
- const SSL_CIPHER *c;
-#ifdef HAVE_SSL_CIPHER_FIND
- (void) m;
- {
- unsigned char cipherid[3];
- tor_assert(ssl);
- set_uint16(cipherid, htons(cipher));
- cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
- * with a two-byte 'cipherid', it may look for a v2
- * cipher with the appropriate 3 bytes. */
- c = SSL_CIPHER_find((SSL*)ssl, cipherid);
- if (c)
- tor_assert((SSL_CIPHER_get_id(c) & 0xffff) == cipher);
- return c != NULL;
- }
-#else /* !(defined(HAVE_SSL_CIPHER_FIND)) */
-
-# if defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR)
- if (m && m->get_cipher_by_char) {
- unsigned char cipherid[3];
- set_uint16(cipherid, htons(cipher));
- cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
- * with a two-byte 'cipherid', it may look for a v2
- * cipher with the appropriate 3 bytes. */
- c = m->get_cipher_by_char(cipherid);
- if (c)
- tor_assert((c->id & 0xffff) == cipher);
- return c != NULL;
- }
-#endif /* defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR) */
-# ifndef OPENSSL_1_1_API
- if (m && m->get_cipher && m->num_ciphers) {
- /* It would seem that some of the "let's-clean-up-openssl" forks have
- * removed the get_cipher_by_char function. Okay, so now you get a
- * quadratic search.
- */
- int i;
- for (i = 0; i < m->num_ciphers(); ++i) {
- c = m->get_cipher(i);
- if (c && (c->id & 0xffff) == cipher) {
- return 1;
- }
- }
- return 0;
- }
-#endif /* !defined(OPENSSL_1_1_API) */
- (void) ssl;
- (void) m;
- (void) cipher;
- return 1; /* No way to search */
-#endif /* defined(HAVE_SSL_CIPHER_FIND) */
-}
-
-/** Remove from v2_cipher_list every cipher that we don't support, so that
- * comparing v2_cipher_list to a client's cipher list will give a sensible
- * result. */
-static void
-prune_v2_cipher_list(const SSL *ssl)
-{
- uint16_t *inp, *outp;
-#ifdef HAVE_TLS_METHOD
- const SSL_METHOD *m = TLS_method();
-#else
- const SSL_METHOD *m = SSLv23_method();
-#endif
-
- inp = outp = v2_cipher_list;
- while (*inp) {
- if (find_cipher_by_id(ssl, m, *inp)) {
- *outp++ = *inp++;
- } else {
- inp++;
- }
- }
- *outp = 0;
-
- v2_cipher_list_pruned = 1;
-}
-
-/** Examine the client cipher list in <b>ssl</b>, and determine what kind of
- * client it is. Return one of CIPHERS_ERR, CIPHERS_V1, CIPHERS_V2,
- * CIPHERS_UNRESTRICTED.
- **/
-STATIC int
-tor_tls_classify_client_ciphers(const SSL *ssl,
- STACK_OF(SSL_CIPHER) *peer_ciphers)
-{
- int i, res;
- tor_tls_t *tor_tls;
- if (PREDICT_UNLIKELY(!v2_cipher_list_pruned))
- prune_v2_cipher_list(ssl);
-
- tor_tls = tor_tls_get_by_ssl(ssl);
- if (tor_tls && tor_tls->client_cipher_list_type)
- return tor_tls->client_cipher_list_type;
-
- /* If we reached this point, we just got a client hello. See if there is
- * a cipher list. */
- if (!peer_ciphers) {
- log_info(LD_NET, "No ciphers on session");
- res = CIPHERS_ERR;
- goto done;
- }
- /* Now we need to see if there are any ciphers whose presence means we're
- * dealing with an updated Tor. */
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- const char *ciphername = SSL_CIPHER_get_name(cipher);
- if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) &&
- strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) &&
- strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) &&
- strcmp(ciphername, "(NONE)")) {
- log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername);
- // return 1;
- goto v2_or_higher;
- }
- }
- res = CIPHERS_V1;
- goto done;
- v2_or_higher:
- {
- const uint16_t *v2_cipher = v2_cipher_list;
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- uint16_t id = SSL_CIPHER_get_id(cipher) & 0xffff;
- if (id == 0x00ff) /* extended renegotiation indicator. */
- continue;
- if (!id || id != *v2_cipher) {
- res = CIPHERS_UNRESTRICTED;
- goto dump_ciphers;
- }
- ++v2_cipher;
- }
- if (*v2_cipher != 0) {
- res = CIPHERS_UNRESTRICTED;
- goto dump_ciphers;
- }
- res = CIPHERS_V2;
- }
-
- dump_ciphers:
- {
- smartlist_t *elts = smartlist_new();
- char *s;
- for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
- const char *ciphername = SSL_CIPHER_get_name(cipher);
- smartlist_add(elts, (char*)ciphername);
- }
- s = smartlist_join_strings(elts, ":", 0, NULL);
- log_debug(LD_NET, "Got a %s V2/V3 cipher list from %s. It is: '%s'",
- (res == CIPHERS_V2) ? "fictitious" : "real", ADDR(tor_tls), s);
- tor_free(s);
- smartlist_free(elts);
- }
- done:
- if (tor_tls)
- return tor_tls->client_cipher_list_type = res;
-
- return res;
-}
-
-/** Return true iff the cipher list suggested by the client for <b>ssl</b> is
- * a list that indicates that the client knows how to do the v2 TLS connection
- * handshake. */
-STATIC int
-tor_tls_client_is_using_v2_ciphers(const SSL *ssl)
-{
- STACK_OF(SSL_CIPHER) *ciphers;
-#ifdef HAVE_SSL_GET_CLIENT_CIPHERS
- ciphers = SSL_get_client_ciphers(ssl);
-#else
- SSL_SESSION *session;
- if (!(session = SSL_get_session((SSL *)ssl))) {
- log_info(LD_NET, "No session on TLS?");
- return CIPHERS_ERR;
- }
- ciphers = session->ciphers;
-#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */
-
- return tor_tls_classify_client_ciphers(ssl, ciphers) >= CIPHERS_V2;
-}
-
-/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
- * changes state. We use this:
- * <ul><li>To alter the state of the handshake partway through, so we
- * do not send or request extra certificates in v2 handshakes.</li>
- * <li>To detect renegotiation</li></ul>
- */
-STATIC void
-tor_tls_server_info_callback(const SSL *ssl, int type, int val)
-{
- tor_tls_t *tls;
- (void) val;
-
- IF_BUG_ONCE(ssl == NULL) {
- return; // LCOV_EXCL_LINE
- }
-
- tor_tls_debug_state_callback(ssl, type, val);
-
- if (type != SSL_CB_ACCEPT_LOOP)
- return;
-
- OSSL_HANDSHAKE_STATE ssl_state = SSL_get_state(ssl);
- if (! STATE_IS_SW_SERVER_HELLO(ssl_state))
- return;
- tls = tor_tls_get_by_ssl(ssl);
- if (tls) {
- /* Check whether we're watching for renegotiates. If so, this is one! */
- if (tls->negotiated_callback)
- tls->got_renegotiate = 1;
- if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
- ++tls->server_handshake_count;
- } else {
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- return;
- }
-
- /* Now check the cipher list. */
- if (tor_tls_client_is_using_v2_ciphers(ssl)) {
- if (tls->wasV2Handshake)
- return; /* We already turned this stuff off for the first handshake;
- * This is a renegotiation. */
-
- /* Yes, we're casting away the const from ssl. This is very naughty of us.
- * Let's hope openssl doesn't notice! */
-
- /* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */
- SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN);
- /* Don't send a hello request. */
- SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL);
-
- if (tls) {
- tls->wasV2Handshake = 1;
- } else {
- /* LCOV_EXCL_START this line is not reachable */
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- /* LCOV_EXCL_STOP */
- }
- }
-}
-
-/** Callback to get invoked on a server after we've read the list of ciphers
- * the client supports, but before we pick our own ciphersuite.
- *
- * We can't abuse an info_cb for this, since by the time one of the
- * client_hello info_cbs is called, we've already picked which ciphersuite to
- * use.
- *
- * Technically, this function is an abuse of this callback, since the point of
- * a session_secret_cb is to try to set up and/or verify a shared-secret for
- * authentication on the fly. But as long as we return 0, we won't actually be
- * setting up a shared secret, and all will be fine.
- */
-STATIC int
-tor_tls_session_secret_cb(SSL *ssl, void *secret, int *secret_len,
- STACK_OF(SSL_CIPHER) *peer_ciphers,
- CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
- void *arg)
-{
- (void) secret;
- (void) secret_len;
- (void) peer_ciphers;
- (void) cipher;
- (void) arg;
-
- if (tor_tls_classify_client_ciphers(ssl, peer_ciphers) ==
- CIPHERS_UNRESTRICTED) {
- SSL_set_cipher_list(ssl, UNRESTRICTED_SERVER_CIPHER_LIST);
- }
-
- SSL_set_session_secret_cb(ssl, NULL, NULL);
-
- return 0;
-}
-static void
-tor_tls_setup_session_secret_cb(tor_tls_t *tls)
-{
- SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL);
-}
-
-/** Create a new TLS object from a file descriptor, and a flag to
- * determine whether it is functioning as a server.
- */
-tor_tls_t *
-tor_tls_new(int sock, int isServer)
-{
- BIO *bio = NULL;
- tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
- tor_tls_context_t *context = isServer ? server_tls_context :
- client_tls_context;
- result->magic = TOR_TLS_MAGIC;
-
- check_no_tls_errors();
- tor_assert(context); /* make sure somebody made it first */
- if (!(result->ssl = SSL_new(context->ctx))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object");
- tor_free(result);
- goto err;
- }
-
-#ifdef SSL_set_tlsext_host_name
- /* Browsers use the TLS hostname extension, so we should too. */
- if (!isServer) {
- char *fake_hostname = crypto_random_hostname(4,25, "www.",".com");
- SSL_set_tlsext_host_name(result->ssl, fake_hostname);
- tor_free(fake_hostname);
- }
-#endif /* defined(SSL_set_tlsext_host_name) */
-
- if (!SSL_set_cipher_list(result->ssl,
- isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers");
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(result->ssl, NULL);
-#endif
- SSL_free(result->ssl);
- tor_free(result);
- goto err;
- }
- result->socket = sock;
- bio = BIO_new_socket(sock, BIO_NOCLOSE);
- if (! bio) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "opening BIO");
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(result->ssl, NULL);
-#endif
- SSL_free(result->ssl);
- tor_free(result);
- goto err;
- }
- {
- int set_worked =
- SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
- if (!set_worked) {
- log_warn(LD_BUG,
- "Couldn't set the tls for an SSL*; connection will fail");
- }
- }
- SSL_set_bio(result->ssl, bio, bio);
- tor_tls_context_incref(context);
- result->context = context;
- result->state = TOR_TLS_ST_HANDSHAKE;
- result->isServer = isServer;
- result->wantwrite_n = 0;
- result->last_write_count = (unsigned long) BIO_number_written(bio);
- result->last_read_count = (unsigned long) BIO_number_read(bio);
- if (result->last_write_count || result->last_read_count) {
- log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu",
- result->last_read_count, result->last_write_count);
- }
- if (isServer) {
- SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
- }
-
- if (isServer)
- tor_tls_setup_session_secret_cb(result);
-
- goto done;
- err:
- result = NULL;
- done:
- /* Not expected to get called. */
- tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
- return result;
-}
-
-/** Make future log messages about <b>tls</b> display the address
- * <b>address</b>.
- */
-void
-tor_tls_set_logged_address(tor_tls_t *tls, const char *address)
-{
- tor_assert(tls);
- tor_free(tls->address);
- tls->address = tor_strdup(address);
-}
-
-/** Set <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b>
- * next gets a client-side renegotiate in the middle of a read. Do not
- * invoke this function until <em>after</em> initial handshaking is done!
- */
-void
-tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg)
-{
- tls->negotiated_callback = cb;
- tls->callback_arg = arg;
- tls->got_renegotiate = 0;
- if (cb) {
- SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
- }
-}
-
-/** If this version of openssl requires it, turn on renegotiation on
- * <b>tls</b>.
- */
-void
-tor_tls_unblock_renegotiation(tor_tls_t *tls)
-{
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data. */
- SSL_set_options(tls->ssl,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
-}
-
-/** If this version of openssl supports it, turn off renegotiation on
- * <b>tls</b>. (Our protocol never requires this for security, but it's nice
- * to use belt-and-suspenders here.)
- */
-void
-tor_tls_block_renegotiation(tor_tls_t *tls)
-{
-#ifdef SUPPORT_UNSAFE_RENEGOTIATION_FLAG
- tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-#else
- (void) tls;
-#endif
-}
-
-/** Assert that the flags that allow legacy renegotiation are still set */
-void
-tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
-{
-#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && \
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION != 0
- long options = SSL_get_options(tls->ssl);
- tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
-#else
- (void) tls;
-#endif /* defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && ... */
-}
-
-/** Return whether this tls initiated the connect (client) or
- * received it (server). */
-int
-tor_tls_is_server(tor_tls_t *tls)
-{
- tor_assert(tls);
- return tls->isServer;
-}
-
-/** Release resources associated with a TLS object. Does not close the
- * underlying file descriptor.
- */
-void
-tor_tls_free_(tor_tls_t *tls)
-{
- if (!tls)
- return;
- tor_assert(tls->ssl);
- {
- size_t r,w;
- tor_tls_get_n_raw_bytes(tls,&r,&w); /* ensure written_by_tls is updated */
- }
-#ifdef SSL_set_tlsext_host_name
- SSL_set_tlsext_host_name(tls->ssl, NULL);
-#endif
- SSL_free(tls->ssl);
- tls->ssl = NULL;
- tls->negotiated_callback = NULL;
- if (tls->context)
- tor_tls_context_decref(tls->context);
- tor_free(tls->address);
- tls->magic = 0x99999999;
- tor_free(tls);
-}
-
-/** Underlying function for TLS reading. Reads up to <b>len</b>
- * characters from <b>tls</b> into <b>cp</b>. On success, returns the
- * number of characters read. On failure, returns TOR_TLS_ERROR,
- * TOR_TLS_CLOSE, TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
- */
-MOCK_IMPL(int,
-tor_tls_read,(tor_tls_t *tls, char *cp, size_t len))
-{
- int r, err;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_OPEN);
- tor_assert(len<INT_MAX);
- r = SSL_read(tls->ssl, cp, (int)len);
- if (r > 0) {
- if (tls->got_renegotiate) {
- /* Renegotiation happened! */
- log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
- if (tls->negotiated_callback)
- tls->negotiated_callback(tls, tls->callback_arg);
- tls->got_renegotiate = 0;
- }
- return r;
- }
- err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
- if (err == TOR_TLS_ZERORETURN_ || err == TOR_TLS_CLOSE) {
- log_debug(LD_NET,"read returned r=%d; TLS is closed",r);
- tls->state = TOR_TLS_ST_CLOSED;
- return TOR_TLS_CLOSE;
- } else {
- tor_assert(err != TOR_TLS_DONE);
- log_debug(LD_NET,"read returned r=%d, err=%d",r,err);
- return err;
- }
-}
-
-/** Total number of bytes that we've used TLS to send. Used to track TLS
- * overhead. */
-STATIC uint64_t total_bytes_written_over_tls = 0;
-/** Total number of bytes that TLS has put on the network for us. Used to
- * track TLS overhead. */
-STATIC uint64_t total_bytes_written_by_tls = 0;
-
-/** Underlying function for TLS writing. Write up to <b>n</b>
- * characters from <b>cp</b> onto <b>tls</b>. On success, returns the
- * number of characters written. On failure, returns TOR_TLS_ERROR,
- * TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_write(tor_tls_t *tls, const char *cp, size_t n)
-{
- int r, err;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_OPEN);
- tor_assert(n < INT_MAX);
- if (n == 0)
- return 0;
- if (tls->wantwrite_n) {
- /* if WANTWRITE last time, we must use the _same_ n as before */
- tor_assert(n >= tls->wantwrite_n);
- log_debug(LD_NET,"resuming pending-write, (%d to flush, reusing %d)",
- (int)n, (int)tls->wantwrite_n);
- n = tls->wantwrite_n;
- tls->wantwrite_n = 0;
- }
- r = SSL_write(tls->ssl, cp, (int)n);
- err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET);
- if (err == TOR_TLS_DONE) {
- total_bytes_written_over_tls += r;
- return r;
- }
- if (err == TOR_TLS_WANTWRITE || err == TOR_TLS_WANTREAD) {
- tls->wantwrite_n = n;
- }
- return err;
-}
-
-/** Perform initial handshake on <b>tls</b>. When finished, returns
- * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
- * or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_handshake(tor_tls_t *tls)
-{
- int r;
- tor_assert(tls);
- tor_assert(tls->ssl);
- tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE);
-
- check_no_tls_errors();
-
- OSSL_HANDSHAKE_STATE oldstate = SSL_get_state(tls->ssl);
-
- if (tls->isServer) {
- log_debug(LD_HANDSHAKE, "About to call SSL_accept on %p (%s)", tls,
- SSL_state_string_long(tls->ssl));
- r = SSL_accept(tls->ssl);
- } else {
- log_debug(LD_HANDSHAKE, "About to call SSL_connect on %p (%s)", tls,
- SSL_state_string_long(tls->ssl));
- r = SSL_connect(tls->ssl);
- }
-
- OSSL_HANDSHAKE_STATE newstate = SSL_get_state(tls->ssl);
-
- if (oldstate != newstate)
- log_debug(LD_HANDSHAKE, "After call, %p was in state %s",
- tls, SSL_state_string_long(tls->ssl));
- /* We need to call this here and not earlier, since OpenSSL has a penchant
- * for clearing its flags when you say accept or connect. */
- tor_tls_unblock_renegotiation(tls);
- r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE);
- if (ERR_peek_error() != 0) {
- tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE,
- "handshaking");
- return TOR_TLS_ERROR_MISC;
- }
- if (r == TOR_TLS_DONE) {
- tls->state = TOR_TLS_ST_OPEN;
- return tor_tls_finish_handshake(tls);
- }
- return r;
-}
-
-/** Perform the final part of the initial TLS handshake on <b>tls</b>. This
- * should be called for the first handshake only: it determines whether the v1
- * or the v2 handshake was used, and adjusts things for the renegotiation
- * handshake as appropriate.
- *
- * tor_tls_handshake() calls this on its own; you only need to call this if
- * bufferevent is doing the handshake for you.
- */
-int
-tor_tls_finish_handshake(tor_tls_t *tls)
-{
- int r = TOR_TLS_DONE;
- check_no_tls_errors();
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN);
- if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
- " for renegotiation.");
- } else {
- tls->wasV2Handshake = 0;
- }
- } else {
- /* Client-side */
- tls->wasV2Handshake = 1;
- /* XXXX this can move, probably? -NM */
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
- }
- tls_log_errors(NULL, LOG_WARN, LD_NET, "finishing the handshake");
- return r;
-}
-
-/** Shut down an open tls connection <b>tls</b>. When finished, returns
- * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
- * or TOR_TLS_WANTWRITE.
- */
-int
-tor_tls_shutdown(tor_tls_t *tls)
-{
- int r, err;
- char buf[128];
- tor_assert(tls);
- tor_assert(tls->ssl);
- check_no_tls_errors();
-
- while (1) {
- if (tls->state == TOR_TLS_ST_SENTCLOSE) {
- /* If we've already called shutdown once to send a close message,
- * we read until the other side has closed too.
- */
- do {
- r = SSL_read(tls->ssl, buf, 128);
- } while (r>0);
- err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down",
- LOG_INFO, LD_NET);
- if (err == TOR_TLS_ZERORETURN_) {
- tls->state = TOR_TLS_ST_GOTCLOSE;
- /* fall through... */
- } else {
- return err;
- }
- }
-
- r = SSL_shutdown(tls->ssl);
- if (r == 1) {
- /* If shutdown returns 1, the connection is entirely closed. */
- tls->state = TOR_TLS_ST_CLOSED;
- return TOR_TLS_DONE;
- }
- err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down",
- LOG_INFO, LD_NET);
- if (err == TOR_TLS_SYSCALL_) {
- /* The underlying TCP connection closed while we were shutting down. */
- tls->state = TOR_TLS_ST_CLOSED;
- return TOR_TLS_DONE;
- } else if (err == TOR_TLS_ZERORETURN_) {
- /* The TLS connection says that it sent a shutdown record, but
- * isn't done shutting down yet. Make sure that this hasn't
- * happened before, then go back to the start of the function
- * and try to read.
- */
- if (tls->state == TOR_TLS_ST_GOTCLOSE ||
- tls->state == TOR_TLS_ST_SENTCLOSE) {
- log_warn(LD_NET,
- "TLS returned \"half-closed\" value while already half-closed");
- return TOR_TLS_ERROR_MISC;
- }
- tls->state = TOR_TLS_ST_SENTCLOSE;
- /* fall through ... */
- } else {
- return err;
- }
- } /* end loop */
-}
-
-/** Return true iff this TLS connection is authenticated.
- */
-int
-tor_tls_peer_has_cert(tor_tls_t *tls)
-{
- X509 *cert;
- cert = SSL_get_peer_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
- if (!cert)
- return 0;
- X509_free(cert);
- return 1;
-}
-
-/** Return a newly allocated copy of the peer certificate, or NULL if there
- * isn't one. */
-MOCK_IMPL(tor_x509_cert_t *,
-tor_tls_get_peer_cert,(tor_tls_t *tls))
-{
- X509 *cert;
- cert = SSL_get_peer_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
- if (!cert)
- return NULL;
- return tor_x509_cert_new(cert);
-}
-
-/** Return a newly allocated copy of the cerficate we used on the connection,
- * or NULL if somehow we didn't use one. */
-MOCK_IMPL(tor_x509_cert_t *,
-tor_tls_get_own_cert,(tor_tls_t *tls))
-{
- X509 *cert = SSL_get_certificate(tls->ssl);
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE,
- "getting own-connection certificate");
- if (!cert)
- return NULL;
- /* Fun inconsistency: SSL_get_peer_certificate increments the reference
- * count, but SSL_get_certificate does not. */
- X509 *duplicate = X509_dup(cert);
- if (BUG(duplicate == NULL))
- return NULL;
- return tor_x509_cert_new(duplicate);
-}
-
-/** Warn that a certificate lifetime extends through a certain range. */
-static void
-log_cert_lifetime(int severity, const X509 *cert, const char *problem,
- time_t now)
-{
- BIO *bio = NULL;
- BUF_MEM *buf;
- char *s1=NULL, *s2=NULL;
- char mytime[33];
- struct tm tm;
- size_t n;
-
- if (problem)
- tor_log(severity, LD_GENERAL,
- "Certificate %s. Either their clock is set wrong, or your clock "
- "is wrong.",
- problem);
-
- if (!(bio = BIO_new(BIO_s_mem()))) {
- log_warn(LD_GENERAL, "Couldn't allocate BIO!"); goto end;
- }
- if (!(ASN1_TIME_print(bio, X509_get_notBefore_const(cert)))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime");
- goto end;
- }
- BIO_get_mem_ptr(bio, &buf);
- s1 = tor_strndup(buf->data, buf->length);
-
- (void)BIO_reset(bio);
- if (!(ASN1_TIME_print(bio, X509_get_notAfter_const(cert)))) {
- tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime");
- goto end;
- }
- BIO_get_mem_ptr(bio, &buf);
- s2 = tor_strndup(buf->data, buf->length);
-
- n = strftime(mytime, 32, "%b %d %H:%M:%S %Y UTC", tor_gmtime_r(&now, &tm));
- if (n > 0) {
- tor_log(severity, LD_GENERAL,
- "(certificate lifetime runs from %s through %s. Your time is %s.)",
- s1,s2,mytime);
- } else {
- tor_log(severity, LD_GENERAL,
- "(certificate lifetime runs from %s through %s. "
- "Couldn't get your time.)",
- s1, s2);
- }
-
- end:
- /* Not expected to get invoked */
- tls_log_errors(NULL, LOG_WARN, LD_NET, "getting certificate lifetime");
- if (bio)
- BIO_free(bio);
- tor_free(s1);
- tor_free(s2);
-}
-
-/** Helper function: try to extract a link certificate and an identity
- * certificate from <b>tls</b>, and store them in *<b>cert_out</b> and
- * *<b>id_cert_out</b> respectively. Log all messages at level
- * <b>severity</b>.
- *
- * Note that a reference is added to cert_out, so it needs to be
- * freed. id_cert_out doesn't. */
-MOCK_IMPL(STATIC void,
-try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls,
- X509 **cert_out, X509 **id_cert_out))
-{
- X509 *cert = NULL, *id_cert = NULL;
- STACK_OF(X509) *chain = NULL;
- int num_in_chain, i;
- *cert_out = *id_cert_out = NULL;
- if (!(cert = SSL_get_peer_certificate(tls->ssl)))
- return;
- *cert_out = cert;
- if (!(chain = SSL_get_peer_cert_chain(tls->ssl)))
- return;
- num_in_chain = sk_X509_num(chain);
- /* 1 means we're receiving (server-side), and it's just the id_cert.
- * 2 means we're connecting (client-side), and it's both the link
- * cert and the id_cert.
- */
- if (num_in_chain < 1) {
- log_fn(severity,LD_PROTOCOL,
- "Unexpected number of certificates in chain (%d)",
- num_in_chain);
- return;
- }
- for (i=0; i<num_in_chain; ++i) {
- id_cert = sk_X509_value(chain, i);
- if (X509_cmp(id_cert, cert) != 0)
- break;
- }
- *id_cert_out = id_cert;
-}
-
-/** If the provided tls connection is authenticated and has a
- * certificate chain that is currently valid and signed, then set
- * *<b>identity_key</b> to the identity certificate's key and return
- * 0. Else, return -1 and log complaints with log-level <b>severity</b>.
- */
-int
-tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key)
-{
- X509 *cert = NULL, *id_cert = NULL;
- EVP_PKEY *id_pkey = NULL;
- RSA *rsa;
- int r = -1;
-
- check_no_tls_errors();
- *identity_key = NULL;
-
- try_to_extract_certs_from_tls(severity, tls, &cert, &id_cert);
- if (!cert)
- goto done;
- if (!id_cert) {
- log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
- goto done;
- }
- tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
-
- if (!(id_pkey = X509_get_pubkey(id_cert)) ||
- X509_verify(cert, id_pkey) <= 0) {
- log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
- tls_log_errors(tls, severity, LD_HANDSHAKE, "verifying certificate");
- goto done;
- }
-
- rsa = EVP_PKEY_get1_RSA(id_pkey);
- if (!rsa)
- goto done;
- *identity_key = crypto_new_pk_from_rsa_(rsa);
-
- r = 0;
-
- done:
- if (cert)
- X509_free(cert);
- if (id_pkey)
- EVP_PKEY_free(id_pkey);
-
- /* This should never get invoked, but let's make sure in case OpenSSL
- * acts unexpectedly. */
- tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "finishing tor_tls_verify");
-
- return r;
-}
-
-/** Check whether the certificate set on the connection <b>tls</b> is expired
- * give or take <b>past_tolerance</b> seconds, or not-yet-valid give or take
- * <b>future_tolerance</b> seconds. Return 0 for valid, -1 for failure.
- *
- * NOTE: you should call tor_tls_verify before tor_tls_check_lifetime.
- */
-int
-tor_tls_check_lifetime(int severity, tor_tls_t *tls,
- time_t now,
- int past_tolerance, int future_tolerance)
-{
- X509 *cert;
- int r = -1;
-
- if (!(cert = SSL_get_peer_certificate(tls->ssl)))
- goto done;
-
- if (check_cert_lifetime_internal(severity, cert, now,
- past_tolerance, future_tolerance) < 0)
- goto done;
-
- r = 0;
- done:
- if (cert)
- X509_free(cert);
- /* Not expected to get invoked */
- tls_log_errors(tls, LOG_WARN, LD_NET, "checking certificate lifetime");
-
- return r;
-}
-
-/** Helper: check whether <b>cert</b> is expired give or take
- * <b>past_tolerance</b> seconds, or not-yet-valid give or take
- * <b>future_tolerance</b> seconds. (Relative to the current time
- * <b>now</b>.) If it is live, return 0. If it is not live, log a message
- * and return -1. */
-static int
-check_cert_lifetime_internal(int severity, const X509 *cert,
- time_t now,
- int past_tolerance, int future_tolerance)
-{
- time_t t;
-
- t = now + future_tolerance;
- if (X509_cmp_time(X509_get_notBefore_const(cert), &t) > 0) {
- log_cert_lifetime(severity, cert, "not yet valid", now);
- return -1;
- }
- t = now - past_tolerance;
- if (X509_cmp_time(X509_get_notAfter_const(cert), &t) < 0) {
- log_cert_lifetime(severity, cert, "already expired", now);
- return -1;
- }
-
- return 0;
-}
-
-#ifdef TOR_UNIT_TESTS
-/* Testing only: return a new x509 cert with the same contents as <b>inp</b>,
- but with the expiration time <b>new_expiration_time</b>, signed with
- <b>signing_key</b>. */
-STATIC tor_x509_cert_t *
-tor_x509_cert_replace_expiration(const tor_x509_cert_t *inp,
- time_t new_expiration_time,
- crypto_pk_t *signing_key)
-{
- X509 *newc = X509_dup(inp->cert);
- X509_time_adj(X509_get_notAfter(newc), 0, &new_expiration_time);
- EVP_PKEY *pk = crypto_pk_get_evp_pkey_(signing_key, 1);
- tor_assert(X509_sign(newc, pk, EVP_sha256()));
- EVP_PKEY_free(pk);
- return tor_x509_cert_new(newc);
-}
-#endif /* defined(TOR_UNIT_TESTS) */
-
-/** Return the number of bytes available for reading from <b>tls</b>.
- */
-int
-tor_tls_get_pending_bytes(tor_tls_t *tls)
-{
- tor_assert(tls);
- return SSL_pending(tls->ssl);
-}
-
-/** If <b>tls</b> requires that the next write be of a particular size,
- * return that size. Otherwise, return 0. */
-size_t
-tor_tls_get_forced_write_size(tor_tls_t *tls)
-{
- return tls->wantwrite_n;
-}
-
-/** Sets n_read and n_written to the number of bytes read and written,
- * respectively, on the raw socket used by <b>tls</b> since the last time this
- * function was called on <b>tls</b>. */
-void
-tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written)
-{
- BIO *wbio, *tmpbio;
- unsigned long r, w;
- r = (unsigned long) BIO_number_read(SSL_get_rbio(tls->ssl));
- /* We want the number of bytes actually for real written. Unfortunately,
- * sometimes OpenSSL replaces the wbio on tls->ssl with a buffering bio,
- * which makes the answer turn out wrong. Let's cope with that. Note
- * that this approach will fail if we ever replace tls->ssl's BIOs with
- * buffering bios for reasons of our own. As an alternative, we could
- * save the original BIO for tls->ssl in the tor_tls_t structure, but
- * that would be tempting fate. */
- wbio = SSL_get_wbio(tls->ssl);
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)
- /* BIO structure is opaque as of OpenSSL 1.1.0-pre5-dev. Again, not
- * supposed to use this form of the version macro, but the OpenSSL developers
- * introduced major API changes in the pre-release stage.
- */
- if (BIO_method_type(wbio) == BIO_TYPE_BUFFER &&
- (tmpbio = BIO_next(wbio)) != NULL)
- wbio = tmpbio;
-#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)) */
- if (wbio->method == BIO_f_buffer() && (tmpbio = BIO_next(wbio)) != NULL)
- wbio = tmpbio;
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) */
- w = (unsigned long) BIO_number_written(wbio);
-
- /* We are ok with letting these unsigned ints go "negative" here:
- * If we wrapped around, this should still give us the right answer, unless
- * we wrapped around by more than ULONG_MAX since the last time we called
- * this function.
- */
- *n_read = (size_t)(r - tls->last_read_count);
- *n_written = (size_t)(w - tls->last_write_count);
- if (*n_read > INT_MAX || *n_written > INT_MAX) {
- log_warn(LD_BUG, "Preposterously large value in tor_tls_get_n_raw_bytes. "
- "r=%lu, last_read=%lu, w=%lu, last_written=%lu",
- r, tls->last_read_count, w, tls->last_write_count);
- }
- total_bytes_written_by_tls += *n_written;
- tls->last_read_count = r;
- tls->last_write_count = w;
-}
-
-/** Return a ratio of the bytes that TLS has sent to the bytes that we've told
- * it to send. Used to track whether our TLS records are getting too tiny. */
-MOCK_IMPL(double,
-tls_get_write_overhead_ratio,(void))
-{
- if (total_bytes_written_over_tls == 0)
- return 1.0;
-
- return U64_TO_DBL(total_bytes_written_by_tls) /
- U64_TO_DBL(total_bytes_written_over_tls);
-}
-
-/** Implement check_no_tls_errors: If there are any pending OpenSSL
- * errors, log an error message. */
-void
-check_no_tls_errors_(const char *fname, int line)
-{
- if (ERR_peek_error() == 0)
- return;
- log_warn(LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ",
- tor_fix_source_file(fname), line);
- tls_log_errors(NULL, LOG_WARN, LD_NET, NULL);
-}
-
-/** Return true iff the initial TLS connection at <b>tls</b> did not use a v2
- * TLS handshake. Output is undefined if the handshake isn't finished. */
-int
-tor_tls_used_v1_handshake(tor_tls_t *tls)
-{
- return ! tls->wasV2Handshake;
-}
-
-/** Return the number of server handshakes that we've noticed doing on
- * <b>tls</b>. */
-int
-tor_tls_get_num_server_handshakes(tor_tls_t *tls)
-{
- return tls->server_handshake_count;
-}
-
-/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
- * request it was waiting for. */
-int
-tor_tls_server_got_renegotiate(tor_tls_t *tls)
-{
- return tls->got_renegotiate;
-}
-
-#ifndef HAVE_SSL_GET_CLIENT_RANDOM
-static size_t
-SSL_get_client_random(SSL *s, uint8_t *out, size_t len)
-{
- if (len == 0)
- return SSL3_RANDOM_SIZE;
- tor_assert(len == SSL3_RANDOM_SIZE);
- tor_assert(s->s3);
- memcpy(out, s->s3->client_random, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_GET_CLIENT_RANDOM) */
-
-#ifndef HAVE_SSL_GET_SERVER_RANDOM
-static size_t
-SSL_get_server_random(SSL *s, uint8_t *out, size_t len)
-{
- if (len == 0)
- return SSL3_RANDOM_SIZE;
- tor_assert(len == SSL3_RANDOM_SIZE);
- tor_assert(s->s3);
- memcpy(out, s->s3->server_random, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_GET_SERVER_RANDOM) */
-
-#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
-STATIC size_t
-SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out, size_t len)
-{
- tor_assert(s);
- if (len == 0)
- return s->master_key_length;
- tor_assert(len == (size_t)s->master_key_length);
- tor_assert(out);
- memcpy(out, s->master_key, len);
- return len;
-}
-#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */
-
-/** Set the DIGEST256_LEN buffer at <b>secrets_out</b> to the value used in
- * the v3 handshake to prove that the client knows the TLS secrets for the
- * connection <b>tls</b>. Return 0 on success, -1 on failure.
- */
-MOCK_IMPL(int,
-tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out))
-{
-#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
- uint8_t buf[128];
- size_t len;
- tor_assert(tls);
-
- SSL *const ssl = tls->ssl;
- SSL_SESSION *const session = SSL_get_session(ssl);
-
- tor_assert(ssl);
- tor_assert(session);
-
- const size_t server_random_len = SSL_get_server_random(ssl, NULL, 0);
- const size_t client_random_len = SSL_get_client_random(ssl, NULL, 0);
- const size_t master_key_len = SSL_SESSION_get_master_key(session, NULL, 0);
-
- tor_assert(server_random_len);
- tor_assert(client_random_len);
- tor_assert(master_key_len);
-
- len = client_random_len + server_random_len + strlen(TLSSECRET_MAGIC) + 1;
- tor_assert(len <= sizeof(buf));
-
- {
- size_t r = SSL_get_client_random(ssl, buf, client_random_len);
- tor_assert(r == client_random_len);
- }
-
- {
- size_t r = SSL_get_server_random(ssl,
- buf+client_random_len,
- server_random_len);
- tor_assert(r == server_random_len);
- }
-
- uint8_t *master_key = tor_malloc_zero(master_key_len);
- {
- size_t r = SSL_SESSION_get_master_key(session, master_key, master_key_len);
- tor_assert(r == master_key_len);
- }
-
- uint8_t *nextbuf = buf + client_random_len + server_random_len;
- memcpy(nextbuf, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1);
-
- /*
- The value is an HMAC, using the TLS master key as the HMAC key, of
- client_random | server_random | TLSSECRET_MAGIC
- */
- crypto_hmac_sha256((char*)secrets_out,
- (char*)master_key,
- master_key_len,
- (char*)buf, len);
- memwipe(buf, 0, sizeof(buf));
- memwipe(master_key, 0, master_key_len);
- tor_free(master_key);
-
- return 0;
-}
-
-/** Using the RFC5705 key material exporting construction, and the
- * provided <b>context</b> (<b>context_len</b> bytes long) and
- * <b>label</b> (a NUL-terminated string), compute a 32-byte secret in
- * <b>secrets_out</b> that only the parties to this TLS session can
- * compute. Return 0 on success and -1 on failure.
- */
-MOCK_IMPL(int,
-tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out,
- const uint8_t *context,
- size_t context_len,
- const char *label))
-{
- tor_assert(tls);
- tor_assert(tls->ssl);
-
- int r = SSL_export_keying_material(tls->ssl,
- secrets_out, DIGEST256_LEN,
- label, strlen(label),
- context, context_len, 1);
- return (r == 1) ? 0 : -1;
-}
-
-/** Examine the amount of memory used and available for buffers in <b>tls</b>.
- * Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
- * buffer and *<b>rbuf_bytes</b> to the amount actually used.
- * Set *<b>wbuf_capacity</b> to the amount of storage allocated for the write
- * buffer and *<b>wbuf_bytes</b> to the amount actually used.
- *
- * Return 0 on success, -1 on failure.*/
-int
-tor_tls_get_buffer_sizes(tor_tls_t *tls,
- size_t *rbuf_capacity, size_t *rbuf_bytes,
- size_t *wbuf_capacity, size_t *wbuf_bytes)
-{
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
- (void)tls;
- (void)rbuf_capacity;
- (void)rbuf_bytes;
- (void)wbuf_capacity;
- (void)wbuf_bytes;
-
- return -1;
-#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)) */
- if (tls->ssl->s3->rbuf.buf)
- *rbuf_capacity = tls->ssl->s3->rbuf.len;
- else
- *rbuf_capacity = 0;
- if (tls->ssl->s3->wbuf.buf)
- *wbuf_capacity = tls->ssl->s3->wbuf.len;
- else
- *wbuf_capacity = 0;
- *rbuf_bytes = tls->ssl->s3->rbuf.left;
- *wbuf_bytes = tls->ssl->s3->wbuf.left;
- return 0;
-#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
-}
-
-/** Check whether the ECC group requested is supported by the current OpenSSL
- * library instance. Return 1 if the group is supported, and 0 if not.
- */
-int
-evaluate_ecgroup_for_tls(const char *ecgroup)
-{
- EC_KEY *ec_key;
- int nid;
- int ret;
-
- if (!ecgroup)
- nid = NID_tor_default_ecdhe_group;
- else if (!strcasecmp(ecgroup, "P256"))
- nid = NID_X9_62_prime256v1;
- else if (!strcasecmp(ecgroup, "P224"))
- nid = NID_secp224r1;
- else
- return 0;
-
- ec_key = EC_KEY_new_by_curve_name(nid);
- ret = (ec_key != NULL);
- EC_KEY_free(ec_key);
-
- return ret;
-}
-
diff --git a/src/common/tortls.h b/src/common/tortls.h
deleted file mode 100644
index c7b319761d..0000000000
--- a/src/common/tortls.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/* Copyright (c) 2003, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_TORTLS_H
-#define TOR_TORTLS_H
-
-/**
- * \file tortls.h
- * \brief Headers for tortls.c
- **/
-
-#include "common/crypto_rsa.h"
-#include "common/compat_openssl.h"
-#include "common/compat.h"
-#include "common/testsupport.h"
-
-/* Opaque structure to hold a TLS connection. */
-typedef struct tor_tls_t tor_tls_t;
-
-/* Opaque structure to hold an X509 certificate. */
-typedef struct tor_x509_cert_t tor_x509_cert_t;
-
-/* Possible return values for most tor_tls_* functions. */
-#define MIN_TOR_TLS_ERROR_VAL_ -9
-#define TOR_TLS_ERROR_MISC -9
-/* Rename to unexpected close or something. XXXX */
-#define TOR_TLS_ERROR_IO -8
-#define TOR_TLS_ERROR_CONNREFUSED -7
-#define TOR_TLS_ERROR_CONNRESET -6
-#define TOR_TLS_ERROR_NO_ROUTE -5
-#define TOR_TLS_ERROR_TIMEOUT -4
-#define TOR_TLS_CLOSE -3
-#define TOR_TLS_WANTREAD -2
-#define TOR_TLS_WANTWRITE -1
-#define TOR_TLS_DONE 0
-
-/** Collection of case statements for all TLS errors that are not due to
- * underlying IO failure. */
-#define CASE_TOR_TLS_ERROR_ANY_NONIO \
- case TOR_TLS_ERROR_MISC: \
- case TOR_TLS_ERROR_CONNREFUSED: \
- case TOR_TLS_ERROR_CONNRESET: \
- case TOR_TLS_ERROR_NO_ROUTE: \
- case TOR_TLS_ERROR_TIMEOUT
-
-/** Use this macro in a switch statement to catch _any_ TLS error. That way,
- * if more errors are added, your switches will still work. */
-#define CASE_TOR_TLS_ERROR_ANY \
- CASE_TOR_TLS_ERROR_ANY_NONIO: \
- case TOR_TLS_ERROR_IO
-
-#define TOR_TLS_IS_ERROR(rv) ((rv) < TOR_TLS_CLOSE)
-
-#ifdef TORTLS_PRIVATE
-#define TOR_TLS_MAGIC 0x71571571
-
-typedef enum {
- TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
- TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
- TOR_TLS_ST_BUFFEREVENT
-} tor_tls_state_t;
-#define tor_tls_state_bitfield_t ENUM_BF(tor_tls_state_t)
-
-struct x509_st;
-struct ssl_st;
-struct ssl_ctx_st;
-struct ssl_session_st;
-
-/** Holds a SSL_CTX object and related state used to configure TLS
- * connections.
- */
-typedef struct tor_tls_context_t {
- int refcnt;
- struct ssl_ctx_st *ctx;
- tor_x509_cert_t *my_link_cert;
- tor_x509_cert_t *my_id_cert;
- tor_x509_cert_t *my_auth_cert;
- crypto_pk_t *link_key;
- crypto_pk_t *auth_key;
-} tor_tls_context_t;
-
-/** Structure that we use for a single certificate. */
-struct tor_x509_cert_t {
- struct x509_st *cert;
- uint8_t *encoded;
- size_t encoded_len;
- unsigned pkey_digests_set : 1;
- common_digests_t cert_digests;
- common_digests_t pkey_digests;
-};
-
-/** Holds a SSL object and its associated data. Members are only
- * accessed from within tortls.c.
- */
-struct tor_tls_t {
- uint32_t magic;
- tor_tls_context_t *context; /** A link to the context object for this tls. */
- struct ssl_st *ssl; /**< An OpenSSL SSL object. */
- int socket; /**< The underlying file descriptor for this TLS connection. */
- char *address; /**< An address to log when describing this connection. */
- tor_tls_state_bitfield_t state : 3; /**< The current SSL state,
- * depending on which operations
- * have completed successfully. */
- unsigned int isServer:1; /**< True iff this is a server-side connection */
- unsigned int wasV2Handshake:1; /**< True iff the original handshake for
- * this connection used the updated version
- * of the connection protocol (client sends
- * different cipher list, server sends only
- * one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
- unsigned int got_renegotiate:1;
- /** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't
- * called that function yet. */
- int8_t client_cipher_list_type;
- /** Incremented every time we start the server side of a handshake. */
- uint8_t server_handshake_count;
- size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
- * time. */
- /** Last values retrieved from BIO_number_read()/write(); see
- * tor_tls_get_n_raw_bytes() for usage.
- */
- unsigned long last_write_count;
- unsigned long last_read_count;
- /** If set, a callback to invoke whenever the client tries to renegotiate
- * the handshake. */
- void (*negotiated_callback)(tor_tls_t *tls, void *arg);
- /** Argument to pass to negotiated_callback. */
- void *callback_arg;
-};
-
-STATIC int tor_errno_to_tls_error(int e);
-STATIC int tor_tls_get_error(tor_tls_t *tls, int r, int extra,
- const char *doing, int severity, int domain);
-STATIC tor_tls_t *tor_tls_get_by_ssl(const struct ssl_st *ssl);
-STATIC void tor_tls_allocate_tor_tls_object_ex_data_index(void);
-#ifdef TORTLS_OPENSSL_PRIVATE
-STATIC int always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx);
-STATIC int tor_tls_classify_client_ciphers(const struct ssl_st *ssl,
- STACK_OF(SSL_CIPHER) *peer_ciphers);
-#endif
-STATIC int tor_tls_client_is_using_v2_ciphers(const struct ssl_st *ssl);
-MOCK_DECL(STATIC void, try_to_extract_certs_from_tls,
- (int severity, tor_tls_t *tls, struct x509_st **cert_out,
- struct x509_st **id_cert_out));
-#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
-STATIC size_t SSL_SESSION_get_master_key(struct ssl_session_st *s,
- uint8_t *out,
- size_t len);
-#endif
-STATIC void tor_tls_debug_state_callback(const struct ssl_st *ssl,
- int type, int val);
-STATIC void tor_tls_server_info_callback(const struct ssl_st *ssl,
- int type, int val);
-#ifdef TORTLS_OPENSSL_PRIVATE
-STATIC int tor_tls_session_secret_cb(struct ssl_st *ssl, void *secret,
- int *secret_len,
- STACK_OF(SSL_CIPHER) *peer_ciphers,
- CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
- void *arg);
-STATIC int find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m,
- uint16_t cipher);
-#endif /* defined(TORTLS_OPENSSL_PRIVATE) */
-MOCK_DECL(STATIC struct x509_st *, tor_tls_create_certificate,
- (crypto_pk_t *rsa,
- crypto_pk_t *rsa_sign,
- const char *cname,
- const char *cname_sign,
- unsigned int cert_lifetime));
-STATIC tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity,
- unsigned int key_lifetime, unsigned flags, int is_client);
-MOCK_DECL(STATIC tor_x509_cert_t *, tor_x509_cert_new,
- (struct x509_st *x509_cert));
-STATIC int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
- crypto_pk_t *identity,
- unsigned int key_lifetime,
- unsigned int flags,
- int is_client);
-STATIC void tls_log_errors(tor_tls_t *tls, int severity, int domain,
- const char *doing);
-
-#ifdef TOR_UNIT_TESTS
-extern int tor_tls_object_ex_data_index;
-extern tor_tls_context_t *server_tls_context;
-extern tor_tls_context_t *client_tls_context;
-extern uint16_t v2_cipher_list[];
-extern uint64_t total_bytes_written_over_tls;
-extern uint64_t total_bytes_written_by_tls;
-
-STATIC tor_x509_cert_t *tor_x509_cert_replace_expiration(
- const tor_x509_cert_t *inp,
- time_t new_expiration_time,
- crypto_pk_t *signing_key);
-#endif /* defined(TOR_UNIT_TESTS) */
-
-#endif /* defined(TORTLS_PRIVATE) */
-
-tor_x509_cert_t *tor_x509_cert_dup(const tor_x509_cert_t *cert);
-const char *tor_tls_err_to_string(int err);
-void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
-
-void tor_tls_free_all(void);
-
-#define TOR_TLS_CTX_IS_PUBLIC_SERVER (1u<<0)
-#define TOR_TLS_CTX_USE_ECDHE_P256 (1u<<1)
-#define TOR_TLS_CTX_USE_ECDHE_P224 (1u<<2)
-
-int tor_tls_context_init(unsigned flags,
- crypto_pk_t *client_identity,
- crypto_pk_t *server_identity,
- unsigned int key_lifetime);
-tor_tls_t *tor_tls_new(int sock, int is_server);
-void tor_tls_set_logged_address(tor_tls_t *tls, const char *address);
-void tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg);
-int tor_tls_is_server(tor_tls_t *tls);
-void tor_tls_free_(tor_tls_t *tls);
-#define tor_tls_free(tls) FREE_AND_NULL(tor_tls_t, tor_tls_free_, (tls))
-int tor_tls_peer_has_cert(tor_tls_t *tls);
-MOCK_DECL(tor_x509_cert_t *,tor_tls_get_peer_cert,(tor_tls_t *tls));
-MOCK_DECL(tor_x509_cert_t *,tor_tls_get_own_cert,(tor_tls_t *tls));
-int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity);
-int tor_tls_check_lifetime(int severity,
- tor_tls_t *tls, time_t now,
- int past_tolerance,
- int future_tolerance);
-MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len));
-int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
-int tor_tls_handshake(tor_tls_t *tls);
-int tor_tls_finish_handshake(tor_tls_t *tls);
-void tor_tls_unblock_renegotiation(tor_tls_t *tls);
-void tor_tls_block_renegotiation(tor_tls_t *tls);
-void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls);
-int tor_tls_shutdown(tor_tls_t *tls);
-int tor_tls_get_pending_bytes(tor_tls_t *tls);
-size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
-
-void tor_tls_get_n_raw_bytes(tor_tls_t *tls,
- size_t *n_read, size_t *n_written);
-
-int tor_tls_get_buffer_sizes(tor_tls_t *tls,
- size_t *rbuf_capacity, size_t *rbuf_bytes,
- size_t *wbuf_capacity, size_t *wbuf_bytes);
-
-MOCK_DECL(double, tls_get_write_overhead_ratio, (void));
-
-int tor_tls_used_v1_handshake(tor_tls_t *tls);
-int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
-int tor_tls_server_got_renegotiate(tor_tls_t *tls);
-MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out));
-MOCK_DECL(int,tor_tls_export_key_material,(
- tor_tls_t *tls, uint8_t *secrets_out,
- const uint8_t *context,
- size_t context_len,
- const char *label));
-
-/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
- */
-#define check_no_tls_errors() check_no_tls_errors_(__FILE__,__LINE__)
-
-void check_no_tls_errors_(const char *fname, int line);
-void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
- int severity, int domain, const char *doing);
-
-void tor_x509_cert_free_(tor_x509_cert_t *cert);
-#define tor_x509_cert_free(c) \
- FREE_AND_NULL(tor_x509_cert_t, tor_x509_cert_free_, (c))
-tor_x509_cert_t *tor_x509_cert_decode(const uint8_t *certificate,
- size_t certificate_len);
-void tor_x509_cert_get_der(const tor_x509_cert_t *cert,
- const uint8_t **encoded_out, size_t *size_out);
-const common_digests_t *tor_x509_cert_get_id_digests(
- const tor_x509_cert_t *cert);
-const common_digests_t *tor_x509_cert_get_cert_digests(
- const tor_x509_cert_t *cert);
-int tor_tls_get_my_certs(int server,
- const tor_x509_cert_t **link_cert_out,
- const tor_x509_cert_t **id_cert_out);
-crypto_pk_t *tor_tls_get_my_client_auth_key(void);
-crypto_pk_t *tor_tls_cert_get_key(tor_x509_cert_t *cert);
-MOCK_DECL(int,tor_tls_cert_matches_key,(const tor_tls_t *tls,
- const tor_x509_cert_t *cert));
-int tor_tls_cert_is_valid(int severity,
- const tor_x509_cert_t *cert,
- const tor_x509_cert_t *signing_cert,
- time_t now,
- int check_rsa_1024);
-const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls);
-
-int evaluate_ecgroup_for_tls(const char *ecgroup);
-
-#endif /* !defined(TOR_TORTLS_H) */
-