mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Merge remote-tracking branch 'public/bug15760_hard_026_v2'
Conflicts: src/common/tortls.c
This commit is contained in:
commit
0030765e04
18
configure.ac
18
configure.ac
@ -610,10 +610,28 @@ else
|
|||||||
fi
|
fi
|
||||||
AC_SUBST(TOR_OPENSSL_LIBS)
|
AC_SUBST(TOR_OPENSSL_LIBS)
|
||||||
|
|
||||||
|
dnl Now check for particular openssl functions.
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
save_LDFLAGS="$LDFLAGS"
|
||||||
|
save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
LIBS="$TOR_OPENSSL_LIBS $LIBS"
|
||||||
|
LDFLAGS="$TOR_LDFLAGS_openssl $LDFLAGS"
|
||||||
|
CPPFLAGS="$TOR_CPPFLAGS_openssl $CPPFLAGS"
|
||||||
AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
|
AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
|
||||||
[#include <openssl/ssl.h>
|
[#include <openssl/ssl.h>
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS([ \
|
||||||
|
SSL_SESSION_get_master_key \
|
||||||
|
SSL_get_server_random \
|
||||||
|
SSL_get_client_ciphers \
|
||||||
|
SSL_get_client_random \
|
||||||
|
SSL_CIPHER_find \
|
||||||
|
])
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
LDFLAGS="$save_LDFLAGS"
|
||||||
|
CPPFLAGS="$save_CPPFLAGS"
|
||||||
|
|
||||||
dnl ------------------------------------------------------
|
dnl ------------------------------------------------------
|
||||||
dnl Where do you live, zlib? And how do we call you?
|
dnl Where do you live, zlib? And how do we call you?
|
||||||
|
|
||||||
|
@ -205,16 +205,6 @@ struct tor_tls_t {
|
|||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef V2_HANDSHAKE_CLIENT
|
|
||||||
/** An array of fake SSL_CIPHER objects that we use in order to trick OpenSSL
|
|
||||||
* in client mode into advertising the ciphers we want. See
|
|
||||||
* rectify_client_ciphers() for details. */
|
|
||||||
static SSL_CIPHER *CLIENT_CIPHER_DUMMIES = NULL;
|
|
||||||
/** A stack of SSL_CIPHER objects, some real, some fake.
|
|
||||||
* See rectify_client_ciphers() for details. */
|
|
||||||
static STACK_OF(SSL_CIPHER) *CLIENT_CIPHER_STACK = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** The ex_data index in which we store a pointer to an SSL object's
|
/** The ex_data index in which we store a pointer to an SSL object's
|
||||||
* corresponding tor_tls_t object. */
|
* corresponding tor_tls_t object. */
|
||||||
static int tor_tls_object_ex_data_index = -1;
|
static int tor_tls_object_ex_data_index = -1;
|
||||||
@ -531,12 +521,6 @@ tor_tls_free_all(void)
|
|||||||
client_tls_context = NULL;
|
client_tls_context = NULL;
|
||||||
tor_tls_context_decref(ctx);
|
tor_tls_context_decref(ctx);
|
||||||
}
|
}
|
||||||
#ifdef V2_HANDSHAKE_CLIENT
|
|
||||||
if (CLIENT_CIPHER_DUMMIES)
|
|
||||||
tor_free(CLIENT_CIPHER_DUMMIES);
|
|
||||||
if (CLIENT_CIPHER_STACK)
|
|
||||||
sk_SSL_CIPHER_free(CLIENT_CIPHER_STACK);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** We need to give OpenSSL a callback to verify certificates. This is
|
/** We need to give OpenSSL a callback to verify certificates. This is
|
||||||
@ -727,7 +711,6 @@ const char UNRESTRICTED_SERVER_CIPHER_LIST[] =
|
|||||||
* (SSL3_TXT_RSA_NULL_SHA). If you do this, you won't be able to communicate
|
* (SSL3_TXT_RSA_NULL_SHA). If you do this, you won't be able to communicate
|
||||||
* with any of the "real" Tors, though. */
|
* with any of the "real" Tors, though. */
|
||||||
|
|
||||||
#ifdef V2_HANDSHAKE_CLIENT
|
|
||||||
#define CIPHER(id, name) name ":"
|
#define CIPHER(id, name) name ":"
|
||||||
#define XCIPHER(id, name)
|
#define XCIPHER(id, name)
|
||||||
/** List of ciphers that clients should advertise, omitting items that
|
/** List of ciphers that clients should advertise, omitting items that
|
||||||
@ -741,28 +724,6 @@ static const char CLIENT_CIPHER_LIST[] =
|
|||||||
#undef CIPHER
|
#undef CIPHER
|
||||||
#undef XCIPHER
|
#undef XCIPHER
|
||||||
|
|
||||||
/** Holds a cipher that we want to advertise, and its 2-byte ID. */
|
|
||||||
typedef struct cipher_info_t { unsigned id; const char *name; } cipher_info_t;
|
|
||||||
/** A list of all the ciphers that clients should advertise, including items
|
|
||||||
* that OpenSSL might not know about. */
|
|
||||||
static const cipher_info_t CLIENT_CIPHER_INFO_LIST[] = {
|
|
||||||
#define CIPHER(id, name) { id, name },
|
|
||||||
#define XCIPHER(id, name) { id, #name },
|
|
||||||
#include "ciphers.inc"
|
|
||||||
#undef CIPHER
|
|
||||||
#undef XCIPHER
|
|
||||||
};
|
|
||||||
|
|
||||||
/** The length of CLIENT_CIPHER_INFO_LIST and CLIENT_CIPHER_DUMMIES. */
|
|
||||||
static const int N_CLIENT_CIPHERS = ARRAY_LENGTH(CLIENT_CIPHER_INFO_LIST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef V2_HANDSHAKE_CLIENT
|
|
||||||
#undef CLIENT_CIPHER_LIST
|
|
||||||
#define CLIENT_CIPHER_LIST (TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \
|
|
||||||
SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Free all storage held in <b>cert</b> */
|
/** Free all storage held in <b>cert</b> */
|
||||||
void
|
void
|
||||||
tor_x509_cert_free(tor_x509_cert_t *cert)
|
tor_x509_cert_free(tor_x509_cert_t *cert)
|
||||||
@ -1440,7 +1401,7 @@ static int
|
|||||||
find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
|
find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
|
||||||
{
|
{
|
||||||
const SSL_CIPHER *c;
|
const SSL_CIPHER *c;
|
||||||
#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,2)
|
#ifdef HAVE_SSL_CIPHER_FIND
|
||||||
{
|
{
|
||||||
unsigned char cipherid[3];
|
unsigned char cipherid[3];
|
||||||
tor_assert(ssl);
|
tor_assert(ssl);
|
||||||
@ -1597,13 +1558,19 @@ tor_tls_classify_client_ciphers(const SSL *ssl,
|
|||||||
static int
|
static int
|
||||||
tor_tls_client_is_using_v2_ciphers(const SSL *ssl)
|
tor_tls_client_is_using_v2_ciphers(const SSL *ssl)
|
||||||
{
|
{
|
||||||
|
STACK_OF(SSL_CIPHER) *ciphers;
|
||||||
|
#ifdef HAVE_SSL_GET_CLIENT_CIPHERS
|
||||||
|
ciphers = SSL_get_ciphers(ssl);
|
||||||
|
#else
|
||||||
SSL_SESSION *session;
|
SSL_SESSION *session;
|
||||||
if (!(session = SSL_get_session((SSL *)ssl))) {
|
if (!(session = SSL_get_session((SSL *)ssl))) {
|
||||||
log_info(LD_NET, "No session on TLS?");
|
log_info(LD_NET, "No session on TLS?");
|
||||||
return CIPHERS_ERR;
|
return CIPHERS_ERR;
|
||||||
}
|
}
|
||||||
|
ciphers = session->ciphers;
|
||||||
|
#endif
|
||||||
|
|
||||||
return tor_tls_classify_client_ciphers(ssl, session->ciphers) >= CIPHERS_V2;
|
return tor_tls_classify_client_ciphers(ssl, ciphers) >= CIPHERS_V2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
|
/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
|
||||||
@ -1702,150 +1669,6 @@ tor_tls_setup_session_secret_cb(tor_tls_t *tls)
|
|||||||
SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL);
|
SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Explain which ciphers we're missing. */
|
|
||||||
static void
|
|
||||||
log_unsupported_ciphers(smartlist_t *unsupported)
|
|
||||||
{
|
|
||||||
char *joined;
|
|
||||||
|
|
||||||
log_notice(LD_NET, "We weren't able to find support for all of the "
|
|
||||||
"TLS ciphersuites that we wanted to advertise. This won't "
|
|
||||||
"hurt security, but it might make your Tor (if run as a client) "
|
|
||||||
"more easy for censors to block.");
|
|
||||||
|
|
||||||
if (SSLeay() < 0x10000000L) {
|
|
||||||
log_notice(LD_NET, "To correct this, use a more recent OpenSSL, "
|
|
||||||
"built without disabling any secure ciphers or features.");
|
|
||||||
} else {
|
|
||||||
log_notice(LD_NET, "To correct this, use a version of OpenSSL "
|
|
||||||
"built with none of its ciphers disabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
joined = smartlist_join_strings(unsupported, ":", 0, NULL);
|
|
||||||
log_info(LD_NET, "The unsupported ciphers were: %s", joined);
|
|
||||||
tor_free(joined);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_ssl_ciphers_to_list(SSL *ssl, STACK_OF(SSL_CIPHER) *stack)
|
|
||||||
{
|
|
||||||
STACK_OF(SSL_CIPHER) *ciphers;
|
|
||||||
|
|
||||||
int r, i;
|
|
||||||
/* #1: ensure that the ssl object has its own list of ciphers. Otherwise we
|
|
||||||
* might be about to stomp the SSL_CTX ciphers list. */
|
|
||||||
r = SSL_set_cipher_list(ssl, "HIGH");
|
|
||||||
tor_assert(r);
|
|
||||||
|
|
||||||
/* #2: Grab ssl_ciphers and clear it. */
|
|
||||||
ciphers = SSL_get_ciphers(ssl);
|
|
||||||
tor_assert(ciphers);
|
|
||||||
sk_SSL_CIPHER_zero(ciphers);
|
|
||||||
|
|
||||||
/* #3: Copy the elements from stack. */
|
|
||||||
for (i = 0; i < sk_SSL_CIPHER_num(stack); ++i) {
|
|
||||||
SSL_CIPHER *c = sk_SSL_CIPHER_value(stack, i);
|
|
||||||
sk_SSL_CIPHER_push(ciphers, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Replace the ciphers on <b>ssl</b> with a new list of SSL ciphersuites:
|
|
||||||
* specifically, a list designed to mimic a common web browser. We might not
|
|
||||||
* be able to do that if OpenSSL doesn't support all the ciphers we want.
|
|
||||||
* Some of the ciphers in the list won't actually be implemented by OpenSSL:
|
|
||||||
* that's okay so long as the server doesn't select them.
|
|
||||||
*
|
|
||||||
* [If the server <b>does</b> select a bogus cipher, we won't crash or
|
|
||||||
* anything; we'll just fail later when we try to look up the cipher in
|
|
||||||
* ssl->cipher_list_by_id.]
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
rectify_client_ciphers(SSL *ssl)
|
|
||||||
{
|
|
||||||
#ifdef V2_HANDSHAKE_CLIENT
|
|
||||||
if (PREDICT_UNLIKELY(!CLIENT_CIPHER_STACK)) {
|
|
||||||
STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
|
|
||||||
|
|
||||||
/* We need to set CLIENT_CIPHER_STACK to an array of the ciphers
|
|
||||||
* we want to use/advertise. */
|
|
||||||
int i = 0, j = 0;
|
|
||||||
smartlist_t *unsupported = smartlist_new();
|
|
||||||
|
|
||||||
/* First, create a dummy SSL_CIPHER for every cipher. */
|
|
||||||
CLIENT_CIPHER_DUMMIES =
|
|
||||||
tor_malloc_zero(sizeof(SSL_CIPHER)*N_CLIENT_CIPHERS);
|
|
||||||
for (i=0; i < N_CLIENT_CIPHERS; ++i) {
|
|
||||||
CLIENT_CIPHER_DUMMIES[i].valid = 1;
|
|
||||||
/* The "3<<24" here signifies that the cipher is supposed to work with
|
|
||||||
* SSL3 and TLS1. */
|
|
||||||
CLIENT_CIPHER_DUMMIES[i].id = CLIENT_CIPHER_INFO_LIST[i].id | (3<<24);
|
|
||||||
CLIENT_CIPHER_DUMMIES[i].name = CLIENT_CIPHER_INFO_LIST[i].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLIENT_CIPHER_STACK = sk_SSL_CIPHER_new_null();
|
|
||||||
tor_assert(CLIENT_CIPHER_STACK);
|
|
||||||
|
|
||||||
log_debug(LD_NET, "List was: %s", CLIENT_CIPHER_LIST);
|
|
||||||
for (j = 0; j < sk_SSL_CIPHER_num(ciphers); ++j) {
|
|
||||||
SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, j);
|
|
||||||
log_debug(LD_NET, "Cipher %d: %lx %s", j,
|
|
||||||
SSL_CIPHER_get_id(cipher), SSL_CIPHER_get_name(cipher));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then copy as many ciphers as we can from the good list, inserting
|
|
||||||
* dummies as needed. Let j be an index into list of ciphers we have
|
|
||||||
* (ciphers) and let i be an index into the ciphers we want
|
|
||||||
* (CLIENT_INFO_CIPHER_LIST). We are building a list of ciphers in
|
|
||||||
* CLIENT_CIPHER_STACK.
|
|
||||||
*/
|
|
||||||
for (i = j = 0; i < N_CLIENT_CIPHERS; ) {
|
|
||||||
SSL_CIPHER *cipher = NULL;
|
|
||||||
if (j < sk_SSL_CIPHER_num(ciphers))
|
|
||||||
cipher = sk_SSL_CIPHER_value(ciphers, j);
|
|
||||||
if (cipher && ((SSL_CIPHER_get_id(cipher) >> 24) & 0xff) != 3) {
|
|
||||||
/* Skip over non-v3 ciphers entirely. (This should no longer be
|
|
||||||
* needed, thanks to saying !SSLv2 above.) */
|
|
||||||
log_debug(LD_NET, "Skipping v%d cipher %s",
|
|
||||||
(int)((SSL_CIPHER_get_id(cipher)>>24) & 0xff),
|
|
||||||
SSL_CIPHER_get_name(cipher));
|
|
||||||
++j;
|
|
||||||
} else if (cipher &&
|
|
||||||
(SSL_CIPHER_get_id(cipher) & 0xffff) ==
|
|
||||||
CLIENT_CIPHER_INFO_LIST[i].id) {
|
|
||||||
/* "cipher" is the cipher we expect. Put it on the list. */
|
|
||||||
log_debug(LD_NET, "Found cipher %s", SSL_CIPHER_get_name(cipher));
|
|
||||||
sk_SSL_CIPHER_push(CLIENT_CIPHER_STACK, cipher);
|
|
||||||
++j;
|
|
||||||
++i;
|
|
||||||
} else if (!strcmp(CLIENT_CIPHER_DUMMIES[i].name,
|
|
||||||
"SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA")) {
|
|
||||||
/* We found bogus cipher 0xfeff, which OpenSSL doesn't support and
|
|
||||||
* never has. For this one, we need a dummy. */
|
|
||||||
log_debug(LD_NET, "Inserting fake %s", CLIENT_CIPHER_DUMMIES[i].name);
|
|
||||||
sk_SSL_CIPHER_push(CLIENT_CIPHER_STACK, &CLIENT_CIPHER_DUMMIES[i]);
|
|
||||||
++i;
|
|
||||||
} else {
|
|
||||||
/* OpenSSL doesn't have this one. */
|
|
||||||
log_debug(LD_NET, "Completely omitting unsupported cipher %s",
|
|
||||||
CLIENT_CIPHER_INFO_LIST[i].name);
|
|
||||||
smartlist_add(unsupported, (char*) CLIENT_CIPHER_INFO_LIST[i].name);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (smartlist_len(unsupported))
|
|
||||||
log_unsupported_ciphers(unsupported);
|
|
||||||
|
|
||||||
smartlist_free(unsupported);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_ssl_ciphers_to_list(ssl, CLIENT_CIPHER_STACK);
|
|
||||||
|
|
||||||
#else
|
|
||||||
(void)ciphers;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a new TLS object from a file descriptor, and a flag to
|
/** Create a new TLS object from a file descriptor, and a flag to
|
||||||
* determine whether it is functioning as a server.
|
* determine whether it is functioning as a server.
|
||||||
*/
|
*/
|
||||||
@ -1885,8 +1708,6 @@ tor_tls_new(int sock, int isServer)
|
|||||||
tor_free(result);
|
tor_free(result);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!isServer)
|
|
||||||
rectify_client_ciphers(result->ssl);
|
|
||||||
result->socket = sock;
|
result->socket = sock;
|
||||||
bio = BIO_new_socket(sock, BIO_NOCLOSE);
|
bio = BIO_new_socket(sock, BIO_NOCLOSE);
|
||||||
if (! bio) {
|
if (! bio) {
|
||||||
@ -2769,6 +2590,46 @@ tor_tls_server_got_renegotiate(tor_tls_t *tls)
|
|||||||
return tls->got_renegotiate;
|
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
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
|
||||||
|
static size_t
|
||||||
|
SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out, size_t len)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
return s->master_key_length;
|
||||||
|
tor_assert(len == (size_t)s->master_key_length);
|
||||||
|
tor_assert(s->master_key);
|
||||||
|
memcpy(out, s->master_key, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/** Set the DIGEST256_LEN buffer at <b>secrets_out</b> to the value used in
|
/** 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
|
* 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.
|
* connection <b>tls</b>. Return 0 on success, -1 on failure.
|
||||||
@ -2777,25 +2638,57 @@ MOCK_IMPL(int,
|
|||||||
tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out))
|
tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out))
|
||||||
{
|
{
|
||||||
#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
|
#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
|
||||||
char buf[128];
|
uint8_t buf[128];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
tor_assert(tls);
|
tor_assert(tls);
|
||||||
tor_assert(tls->ssl);
|
|
||||||
tor_assert(tls->ssl->s3);
|
SSL *const ssl = tls->ssl;
|
||||||
tor_assert(tls->ssl->session);
|
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
|
The value is an HMAC, using the TLS master key as the HMAC key, of
|
||||||
client_random | server_random | TLSSECRET_MAGIC
|
client_random | server_random | TLSSECRET_MAGIC
|
||||||
*/
|
*/
|
||||||
memcpy(buf + 0, tls->ssl->s3->client_random, 32);
|
|
||||||
memcpy(buf + 32, tls->ssl->s3->server_random, 32);
|
|
||||||
memcpy(buf + 64, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1);
|
|
||||||
len = 64 + strlen(TLSSECRET_MAGIC) + 1;
|
|
||||||
crypto_hmac_sha256((char*)secrets_out,
|
crypto_hmac_sha256((char*)secrets_out,
|
||||||
(char*)tls->ssl->session->master_key,
|
(char*)master_key,
|
||||||
tls->ssl->session->master_key_length,
|
master_key_len,
|
||||||
buf, len);
|
(char*)buf, len);
|
||||||
memwipe(buf, 0, sizeof(buf));
|
memwipe(buf, 0, sizeof(buf));
|
||||||
|
memwipe(master_key, 0, master_key_len);
|
||||||
|
tor_free(master_key);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user