Merge branch 'maint-0.3.0'

This commit is contained in:
Nick Mathewson 2017-06-05 15:52:06 -04:00
commit e3b1573be6
14 changed files with 190 additions and 47 deletions

16
changes/bug22460_case1 Normal file
View File

@ -0,0 +1,16 @@
o Major bugfixes (relays, key management):
- Regenerate link and authentication certificates whenever the key that
signs them changes; also, regenerate link certificates whenever the
signed key changes. Previously, these processes were only weakly
coupled, and we relays could (for minutes to hours) wind up with an
inconsistent set of keys and certificates, which other relays
would not accept. Fixes two cases of bug 22460; bugfix on
0.3.0.1-alpha.
- When sending an Ed25519 signing->link certificate in a CERTS cell,
send the certificate that matches the x509 certificate that we used
on the TLS connection. Previously, there was a race condition if
the TLS context rotated after we began the TLS handshake but
before we sent the CERTS cell. Fixes a case of bug 22460; bugfix
on 0.3.0.1-alpha.

8
changes/bug22460_case2 Normal file
View File

@ -0,0 +1,8 @@
o Major bugfixes (relay, link handshake):
- When performing the v3 link handshake on a TLS connection, report that
we have the x509 certificate that we actually used on that connection,
even if we have changed certificates since that connection was first
opened. Previously, we would claim to have used our most recent x509
link certificate, which would sometimes make the link handshake fail.
Fixes one case of bug 22460; bugfix on 0.2.3.6-alpha.

View File

@ -705,11 +705,13 @@ tor_x509_cert_new,(X509 *x509_cert))
return cert; return cert;
} }
/** Return a copy of <b>cert</b> */ /** Return a new copy of <b>cert</b>. */
tor_x509_cert_t * tor_x509_cert_t *
tor_x509_cert_dup(const tor_x509_cert_t *cert) tor_x509_cert_dup(const tor_x509_cert_t *cert)
{ {
return tor_x509_cert_new(X509_dup(cert->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>, /** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>,
@ -2047,7 +2049,8 @@ tor_tls_peer_has_cert(tor_tls_t *tls)
return 1; return 1;
} }
/** Return the peer certificate, or NULL if there isn't one. */ /** Return a newly allocated copy of the peer certificate, or NULL if there
* isn't one. */
MOCK_IMPL(tor_x509_cert_t *, MOCK_IMPL(tor_x509_cert_t *,
tor_tls_get_peer_cert,(tor_tls_t *tls)) tor_tls_get_peer_cert,(tor_tls_t *tls))
{ {
@ -2059,6 +2062,24 @@ tor_tls_get_peer_cert,(tor_tls_t *tls))
return tor_x509_cert_new(cert); 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. */ /** Warn that a certificate lifetime extends through a certain range. */
static void static void
log_cert_lifetime(int severity, const X509 *cert, const char *problem, log_cert_lifetime(int severity, const X509 *cert, const char *problem,

View File

@ -219,6 +219,7 @@ int tor_tls_is_server(tor_tls_t *tls);
void tor_tls_free(tor_tls_t *tls); void tor_tls_free(tor_tls_t *tls);
int tor_tls_peer_has_cert(tor_tls_t *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_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_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity);
int tor_tls_check_lifetime(int severity, int tor_tls_check_lifetime(int severity,
tor_tls_t *tls, time_t now, tor_tls_t *tls, time_t now,

View File

@ -1838,6 +1838,9 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
s->started_here = started_here ? 1 : 0; s->started_here = started_here ? 1 : 0;
s->digest_sent_data = 1; s->digest_sent_data = 1;
s->digest_received_data = 1; s->digest_received_data = 1;
if (! started_here && get_current_link_cert_cert()) {
s->own_link_cert = tor_cert_dup(get_current_link_cert_cert());
}
s->certs = or_handshake_certs_new(); s->certs = or_handshake_certs_new();
s->certs->started_here = s->started_here; s->certs->started_here = s->started_here;
return 0; return 0;
@ -1852,6 +1855,7 @@ or_handshake_state_free(or_handshake_state_t *state)
crypto_digest_free(state->digest_sent); crypto_digest_free(state->digest_sent);
crypto_digest_free(state->digest_received); crypto_digest_free(state->digest_received);
or_handshake_certs_free(state->certs); or_handshake_certs_free(state->certs);
tor_cert_free(state->own_link_cert);
memwipe(state, 0xBE, sizeof(or_handshake_state_t)); memwipe(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state); tor_free(state);
} }
@ -2228,7 +2232,8 @@ add_certs_cell_cert_helper(certs_cell_t *certs_cell,
/** Add an encoded X509 cert (stored as <b>cert_len</b> bytes at /** Add an encoded X509 cert (stored as <b>cert_len</b> bytes at
* <b>cert_encoded</b>) to the trunnel certs_cell_t object that we are * <b>cert_encoded</b>) to the trunnel certs_cell_t object that we are
* building in <b>certs_cell</b>. Set its type field to <b>cert_type</b>. */ * building in <b>certs_cell</b>. Set its type field to <b>cert_type</b>.
* (If <b>cert</b> is NULL, take no action.) */
static void static void
add_x509_cert(certs_cell_t *certs_cell, add_x509_cert(certs_cell_t *certs_cell,
uint8_t cert_type, uint8_t cert_type,
@ -2246,7 +2251,7 @@ add_x509_cert(certs_cell_t *certs_cell,
/** Add an Ed25519 cert from <b>cert</b> to the trunnel certs_cell_t object /** Add an Ed25519 cert from <b>cert</b> to the trunnel certs_cell_t object
* that we are building in <b>certs_cell</b>. Set its type field to * that we are building in <b>certs_cell</b>. Set its type field to
* <b>cert_type</b>. */ * <b>cert_type</b>. (If <b>cert</b> is NULL, take no action.) */
static void static void
add_ed25519_cert(certs_cell_t *certs_cell, add_ed25519_cert(certs_cell_t *certs_cell,
uint8_t cert_type, uint8_t cert_type,
@ -2259,12 +2264,19 @@ add_ed25519_cert(certs_cell_t *certs_cell,
cert->encoded, cert->encoded_len); cert->encoded, cert->encoded_len);
} }
#ifdef TOR_UNIT_TESTS
int certs_cell_ed25519_disabled_for_testing = 0;
#else
#define certs_cell_ed25519_disabled_for_testing 0
#endif
/** Send a CERTS cell on the connection <b>conn</b>. Return 0 on success, -1 /** Send a CERTS cell on the connection <b>conn</b>. Return 0 on success, -1
* on failure. */ * on failure. */
int int
connection_or_send_certs_cell(or_connection_t *conn) connection_or_send_certs_cell(or_connection_t *conn)
{ {
const tor_x509_cert_t *link_cert = NULL, *id_cert = NULL; const tor_x509_cert_t *global_link_cert = NULL, *id_cert = NULL;
tor_x509_cert_t *own_link_cert = NULL;
var_cell_t *cell; var_cell_t *cell;
certs_cell_t *certs_cell = NULL; certs_cell_t *certs_cell = NULL;
@ -2277,21 +2289,26 @@ connection_or_send_certs_cell(or_connection_t *conn)
const int conn_in_server_mode = ! conn->handshake_state->started_here; const int conn_in_server_mode = ! conn->handshake_state->started_here;
/* Get the encoded values of the X509 certificates */ /* Get the encoded values of the X509 certificates */
if (tor_tls_get_my_certs(conn_in_server_mode, &link_cert, &id_cert) < 0) if (tor_tls_get_my_certs(conn_in_server_mode,
&global_link_cert, &id_cert) < 0)
return -1; return -1;
tor_assert(link_cert); if (conn_in_server_mode) {
own_link_cert = tor_tls_get_own_cert(conn->tls);
}
tor_assert(id_cert); tor_assert(id_cert);
certs_cell = certs_cell_new(); certs_cell = certs_cell_new();
/* Start adding certs. First the link cert or auth1024 cert. */ /* Start adding certs. First the link cert or auth1024 cert. */
if (conn_in_server_mode) { if (conn_in_server_mode) {
tor_assert_nonfatal(own_link_cert);
add_x509_cert(certs_cell, add_x509_cert(certs_cell,
OR_CERT_TYPE_TLS_LINK, link_cert); OR_CERT_TYPE_TLS_LINK, own_link_cert);
} else { } else {
tor_assert(global_link_cert);
add_x509_cert(certs_cell, add_x509_cert(certs_cell,
OR_CERT_TYPE_AUTH_1024, link_cert); OR_CERT_TYPE_AUTH_1024, global_link_cert);
} }
/* Next the RSA->RSA ID cert */ /* Next the RSA->RSA ID cert */
@ -2303,9 +2320,11 @@ connection_or_send_certs_cell(or_connection_t *conn)
CERTTYPE_ED_ID_SIGN, CERTTYPE_ED_ID_SIGN,
get_master_signing_key_cert()); get_master_signing_key_cert());
if (conn_in_server_mode) { if (conn_in_server_mode) {
tor_assert_nonfatal(conn->handshake_state->own_link_cert ||
certs_cell_ed25519_disabled_for_testing);
add_ed25519_cert(certs_cell, add_ed25519_cert(certs_cell,
CERTTYPE_ED_SIGN_LINK, CERTTYPE_ED_SIGN_LINK,
get_current_link_cert_cert()); conn->handshake_state->own_link_cert);
} else { } else {
add_ed25519_cert(certs_cell, add_ed25519_cert(certs_cell,
CERTTYPE_ED_SIGN_AUTH, CERTTYPE_ED_SIGN_AUTH,
@ -2338,6 +2357,7 @@ connection_or_send_certs_cell(or_connection_t *conn)
connection_or_write_var_cell_to_buf(cell, conn); connection_or_write_var_cell_to_buf(cell, conn);
var_cell_free(cell); var_cell_free(cell);
certs_cell_free(certs_cell); certs_cell_free(certs_cell);
tor_x509_cert_free(own_link_cert);
return 0; return 0;
} }
@ -2478,10 +2498,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
memcpy(auth1_getarray_type(auth), authtype_str, 8); memcpy(auth1_getarray_type(auth), authtype_str, 8);
{ {
const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL; const tor_x509_cert_t *id_cert=NULL;
const common_digests_t *my_digests, *their_digests; const common_digests_t *my_digests, *their_digests;
const uint8_t *my_id, *their_id, *client_id, *server_id; const uint8_t *my_id, *their_id, *client_id, *server_id;
if (tor_tls_get_my_certs(server, &link_cert, &id_cert)) if (tor_tls_get_my_certs(server, NULL, &id_cert))
goto err; goto err;
my_digests = tor_x509_cert_get_id_digests(id_cert); my_digests = tor_x509_cert_get_id_digests(id_cert);
their_digests = their_digests =
@ -2536,13 +2556,11 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
{ {
/* Digest of cert used on TLS link : 32 octets. */ /* Digest of cert used on TLS link : 32 octets. */
const tor_x509_cert_t *cert = NULL; tor_x509_cert_t *cert = NULL;
tor_x509_cert_t *freecert = NULL;
if (server) { if (server) {
tor_tls_get_my_certs(1, &cert, NULL); cert = tor_tls_get_own_cert(conn->tls);
} else { } else {
freecert = tor_tls_get_peer_cert(conn->tls); cert = tor_tls_get_peer_cert(conn->tls);
cert = freecert;
} }
if (!cert) { if (!cert) {
log_warn(LD_OR, "Unable to find cert when making %s data.", log_warn(LD_OR, "Unable to find cert when making %s data.",
@ -2553,8 +2571,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
memcpy(auth->scert, memcpy(auth->scert,
tor_x509_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32); tor_x509_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32);
if (freecert) tor_x509_cert_free(cert);
tor_x509_cert_free(freecert);
} }
/* HMAC of clientrandom and serverrandom using master key : 32 octets */ /* HMAC of clientrandom and serverrandom using master key : 32 octets */

View File

@ -114,5 +114,9 @@ void var_cell_free(var_cell_t *cell);
void connection_or_group_set_badness_(smartlist_t *group, int force); void connection_or_group_set_badness_(smartlist_t *group, int force);
#ifdef TOR_UNIT_TESTS
extern int certs_cell_ed25519_disabled_for_testing;
#endif
#endif #endif

View File

@ -1551,8 +1551,9 @@ check_ed_keys_callback(time_t now, const or_options_t *options)
{ {
if (server_mode(options)) { if (server_mode(options)) {
if (should_make_new_ed_keys(options, now)) { if (should_make_new_ed_keys(options, now)) {
if (load_ed_keys(options, now) < 0 || int new_signing_key = load_ed_keys(options, now);
generate_ed_link_cert(options, now)) { if (new_signing_key < 0 ||
generate_ed_link_cert(options, now, new_signing_key > 0)) {
log_err(LD_OR, "Unable to update Ed25519 keys! Exiting."); log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
tor_cleanup(); tor_cleanup();
exit(0); exit(0);
@ -1604,6 +1605,11 @@ rotate_x509_certificate_callback(time_t now, const or_options_t *options)
log_err(LD_BUG, "Error reinitializing TLS context"); log_err(LD_BUG, "Error reinitializing TLS context");
tor_assert_unreached(); tor_assert_unreached();
} }
if (generate_ed_link_cert(options, now, 1)) {
log_err(LD_OR, "Unable to update Ed25519->TLS link certificate for "
"new TLS context.");
tor_assert_unreached();
}
/* We also make sure to rotate the TLS connections themselves if they've /* We also make sure to rotate the TLS connections themselves if they've
* been up for too long -- but that's done via is_bad_for_new_circs in * been up for too long -- but that's done via is_bad_for_new_circs in
@ -2376,8 +2382,9 @@ do_hup(void)
/* Maybe we've been given a new ed25519 key or certificate? /* Maybe we've been given a new ed25519 key or certificate?
*/ */
time_t now = approx_time(); time_t now = approx_time();
if (load_ed_keys(options, now) < 0 || int new_signing_key = load_ed_keys(options, now);
generate_ed_link_cert(options, now)) { if (new_signing_key < 0 ||
generate_ed_link_cert(options, now, new_signing_key > 0)) {
log_warn(LD_OR, "Problem reloading Ed25519 keys; still using old keys."); log_warn(LD_OR, "Problem reloading Ed25519 keys; still using old keys.");
} }
@ -3745,7 +3752,7 @@ tor_main(int argc, char *argv[])
result = do_main_loop(); result = do_main_loop();
break; break;
case CMD_KEYGEN: case CMD_KEYGEN:
result = load_ed_keys(get_options(), time(NULL)); result = load_ed_keys(get_options(), time(NULL)) < 0;
break; break;
case CMD_LIST_FINGERPRINT: case CMD_LIST_FINGERPRINT:
result = do_list_fingerprint(); result = do_list_fingerprint();

View File

@ -1471,6 +1471,12 @@ typedef struct or_handshake_state_t {
/* True iff we have sent a netinfo cell */ /* True iff we have sent a netinfo cell */
unsigned int sent_netinfo : 1; unsigned int sent_netinfo : 1;
/** The signing->ed25519 link certificate corresponding to the x509
* certificate we used on the TLS connection (if this is a server-side
* connection). We make a copy of this here to prevent a race condition
* caused by TLS context rotation. */
struct tor_cert_st *own_link_cert;
/** True iff we should feed outgoing cells into digest_sent and /** True iff we should feed outgoing cells into digest_sent and
* digest_received respectively. * digest_received respectively.
* *

View File

@ -986,7 +986,8 @@ init_keys(void)
} }
/* 1d. Load all ed25519 keys */ /* 1d. Load all ed25519 keys */
if (load_ed_keys(options,now) < 0) const int new_signing_key = load_ed_keys(options,now);
if (new_signing_key < 0)
return -1; return -1;
/* 2. Read onion key. Make it if none is found. */ /* 2. Read onion key. Make it if none is found. */
@ -1056,7 +1057,7 @@ init_keys(void)
/* 3b. Get an ed25519 link certificate. Note that we need to do this /* 3b. Get an ed25519 link certificate. Note that we need to do this
* after we set up the TLS context */ * after we set up the TLS context */
if (generate_ed_link_cert(options, now) < 0) { if (generate_ed_link_cert(options, now, new_signing_key > 0) < 0) {
log_err(LD_GENERAL,"Couldn't make link cert"); log_err(LD_GENERAL,"Couldn't make link cert");
return -1; return -1;
} }

View File

@ -673,6 +673,9 @@ static time_t rsa_ed_crosscert_expiration = 0;
/** /**
* Running as a server: load, reload, or refresh our ed25519 keys and * Running as a server: load, reload, or refresh our ed25519 keys and
* certificates, creating and saving new ones as needed. * certificates, creating and saving new ones as needed.
*
* Return -1 on failure; 0 on success if the signing key was not replaced;
* and 1 on success if the signing key was replaced.
*/ */
int int
load_ed_keys(const or_options_t *options, time_t now) load_ed_keys(const or_options_t *options, time_t now)
@ -685,6 +688,7 @@ load_ed_keys(const or_options_t *options, time_t now)
const tor_cert_t *check_signing_cert = NULL; const tor_cert_t *check_signing_cert = NULL;
tor_cert_t *sign_cert = NULL; tor_cert_t *sign_cert = NULL;
tor_cert_t *auth_cert = NULL; tor_cert_t *auth_cert = NULL;
int signing_key_changed = 0;
// It is later than 1972, since otherwise there would be no C compilers. // It is later than 1972, since otherwise there would be no C compilers.
// (Try to diagnose #22466.) // (Try to diagnose #22466.)
@ -726,7 +730,23 @@ load_ed_keys(const or_options_t *options, time_t now)
use_signing = sign; use_signing = sign;
} }
if (use_signing) {
/* We loaded a signing key with its certificate. */
if (! master_signing_key) {
/* We didn't know one before! */
signing_key_changed = 1;
} else if (! ed25519_pubkey_eq(&use_signing->pubkey,
&master_signing_key->pubkey) ||
! tor_memeq(use_signing->seckey.seckey,
master_signing_key->seckey.seckey,
ED25519_SECKEY_LEN)) {
/* We loaded a different signing key than the one we knew before. */
signing_key_changed = 1;
}
}
if (!use_signing && master_signing_key) { if (!use_signing && master_signing_key) {
/* We couldn't load a signing key, but we already had one loaded */
check_signing_cert = signing_key_cert; check_signing_cert = signing_key_cert;
use_signing = master_signing_key; use_signing = master_signing_key;
} }
@ -886,6 +906,7 @@ load_ed_keys(const or_options_t *options, time_t now)
if (!sign) if (!sign)
FAIL("Missing signing key"); FAIL("Missing signing key");
use_signing = sign; use_signing = sign;
signing_key_changed = 1;
tor_assert(sign_cert->signing_key_included); tor_assert(sign_cert->signing_key_included);
tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey)); tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey));
@ -922,6 +943,7 @@ load_ed_keys(const or_options_t *options, time_t now)
} }
if (!current_auth_key || if (!current_auth_key ||
signing_key_changed ||
EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop)) { EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop)) {
auth = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT, auth = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT,
now, now,
@ -949,7 +971,7 @@ load_ed_keys(const or_options_t *options, time_t now)
SET_CERT(auth_key_cert, auth_cert); SET_CERT(auth_key_cert, auth_cert);
} }
return 0; return signing_key_changed;
err: err:
ed25519_keypair_free(id); ed25519_keypair_free(id);
ed25519_keypair_free(sign); ed25519_keypair_free(sign);
@ -963,16 +985,18 @@ load_ed_keys(const or_options_t *options, time_t now)
* Retrieve our currently-in-use Ed25519 link certificate and id certificate, * Retrieve our currently-in-use Ed25519 link certificate and id certificate,
* and, if they would expire soon (based on the time <b>now</b>, generate new * and, if they would expire soon (based on the time <b>now</b>, generate new
* certificates (without embedding the public part of the signing key inside). * certificates (without embedding the public part of the signing key inside).
* If <b>force</b> is true, always generate a new certificate.
* *
* The signed_key from the expiring certificate will be used to sign the new * The signed_key from the current id->signing certificate will be used to
* key within newly generated X509 certificate. * sign the new key within newly generated X509 certificate.
* *
* Returns -1 upon error. Otherwise, returns 0 upon success (either when the * Returns -1 upon error. Otherwise, returns 0 upon success (either when the
* current certificate is still valid, or when a new certificate was * current certificate is still valid, or when a new certificate was
* successfully generated). * successfully generated).
*/ */
int int
generate_ed_link_cert(const or_options_t *options, time_t now) generate_ed_link_cert(const or_options_t *options, time_t now,
int force)
{ {
const tor_x509_cert_t *link_ = NULL, *id = NULL; const tor_x509_cert_t *link_ = NULL, *id = NULL;
tor_cert_t *link_cert = NULL; tor_cert_t *link_cert = NULL;
@ -984,7 +1008,8 @@ generate_ed_link_cert(const or_options_t *options, time_t now)
const common_digests_t *digests = tor_x509_cert_get_cert_digests(link_); const common_digests_t *digests = tor_x509_cert_get_cert_digests(link_);
if (link_cert_cert && if (force == 0 &&
link_cert_cert &&
! EXPIRES_SOON(link_cert_cert, options->TestingLinkKeySlop) && ! EXPIRES_SOON(link_cert_cert, options->TestingLinkKeySlop) &&
fast_memeq(digests->d[DIGEST_SHA256], link_cert_cert->signed_key.pubkey, fast_memeq(digests->d[DIGEST_SHA256], link_cert_cert->signed_key.pubkey,
DIGEST256_LEN)) { DIGEST256_LEN)) {
@ -1086,7 +1111,7 @@ init_mock_ed_keys(const crypto_pk_t *rsa_identity_key)
MAKECERT(auth_key_cert, MAKECERT(auth_key_cert,
master_signing_key, current_auth_key, CERT_TYPE_SIGNING_AUTH, 0); master_signing_key, current_auth_key, CERT_TYPE_SIGNING_AUTH, 0);
if (generate_ed_link_cert(get_options(), time(NULL)) < 0) { if (generate_ed_link_cert(get_options(), time(NULL), 0) < 0) {
log_warn(LD_BUG, "Couldn't make link certificate"); log_warn(LD_BUG, "Couldn't make link certificate");
goto err; goto err;
} }

View File

@ -66,7 +66,7 @@ MOCK_DECL(int, check_tap_onion_key_crosscert,(const uint8_t *crosscert,
int load_ed_keys(const or_options_t *options, time_t now); int load_ed_keys(const or_options_t *options, time_t now);
int should_make_new_ed_keys(const or_options_t *options, const time_t now); int should_make_new_ed_keys(const or_options_t *options, const time_t now);
int generate_ed_link_cert(const or_options_t *options, time_t now); int generate_ed_link_cert(const or_options_t *options, time_t now, int force);
int read_encrypted_secret_key(ed25519_secret_key_t *out, int read_encrypted_secret_key(ed25519_secret_key_t *out,
const char *fname); const char *fname);

View File

@ -52,7 +52,7 @@ mock_get_peer_cert(tor_tls_t *tls)
if (mock_peer_cert_expect_tortls && if (mock_peer_cert_expect_tortls &&
mock_peer_cert_expect_tortls != tls) mock_peer_cert_expect_tortls != tls)
return NULL; return NULL;
return mock_peer_cert; return tor_x509_cert_dup(mock_peer_cert);
} }
static int mock_send_netinfo_called = 0; static int mock_send_netinfo_called = 0;
@ -98,6 +98,14 @@ mock_export_key_material(tor_tls_t *tls, uint8_t *secrets_out,
return 0; return 0;
} }
static tor_x509_cert_t *mock_own_cert = NULL;
static tor_x509_cert_t *
mock_get_own_cert(tor_tls_t *tls)
{
(void)tls;
return tor_x509_cert_dup(mock_own_cert);
}
/* Test good certs cells */ /* Test good certs cells */
static void static void
test_link_handshake_certs_ok(void *arg) test_link_handshake_certs_ok(void *arg)
@ -119,6 +127,7 @@ test_link_handshake_certs_ok(void *arg)
MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell);
MOCK(connection_or_send_netinfo, mock_send_netinfo); MOCK(connection_or_send_netinfo, mock_send_netinfo);
MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert);
MOCK(tor_tls_get_own_cert, mock_get_own_cert);
key1 = pk_generate(2); key1 = pk_generate(2);
key2 = pk_generate(3); key2 = pk_generate(3);
@ -133,9 +142,17 @@ test_link_handshake_certs_ok(void *arg)
/* If we're making a CERTS cell for an ed handshake, let's make sure we /* If we're making a CERTS cell for an ed handshake, let's make sure we
* have some Ed25519 certificates and keys. */ * have some Ed25519 certificates and keys. */
init_mock_ed_keys(key2); init_mock_ed_keys(key2);
} else {
certs_cell_ed25519_disabled_for_testing = 1;
} }
/* c1 has started_here == 1 */ /* c1 has started_here == 1 */
{
const tor_x509_cert_t *link = NULL;
tt_assert(!tor_tls_get_my_certs(1, &link, NULL));
mock_own_cert = tor_x509_cert_dup(link);
}
c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
c1->link_proto = 3; c1->link_proto = 3;
tt_int_op(connection_init_or_handshake_state(c1, 1), ==, 0); tt_int_op(connection_init_or_handshake_state(c1, 1), ==, 0);
@ -278,6 +295,9 @@ test_link_handshake_certs_ok(void *arg)
UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(connection_or_write_var_cell_to_buf);
UNMOCK(connection_or_send_netinfo); UNMOCK(connection_or_send_netinfo);
UNMOCK(tor_tls_get_peer_cert); UNMOCK(tor_tls_get_peer_cert);
UNMOCK(tor_tls_get_own_cert);
tor_x509_cert_free(mock_own_cert);
mock_own_cert = NULL;
memset(c1->identity_digest, 0, sizeof(c1->identity_digest)); memset(c1->identity_digest, 0, sizeof(c1->identity_digest));
memset(c2->identity_digest, 0, sizeof(c2->identity_digest)); memset(c2->identity_digest, 0, sizeof(c2->identity_digest));
connection_free_(TO_CONN(c1)); connection_free_(TO_CONN(c1));
@ -315,6 +335,7 @@ recv_certs_cleanup(const struct testcase_t *test, void *obj)
UNMOCK(connection_or_send_netinfo); UNMOCK(connection_or_send_netinfo);
UNMOCK(connection_or_close_for_error); UNMOCK(connection_or_close_for_error);
UNMOCK(tor_tls_get_peer_cert); UNMOCK(tor_tls_get_peer_cert);
UNMOCK(tor_tls_get_own_cert);
if (d) { if (d) {
tor_free(d->cell); tor_free(d->cell);
@ -880,6 +901,11 @@ test_link_handshake_send_authchallenge(void *arg)
or_connection_t *c1 = or_connection_new(CONN_TYPE_OR, AF_INET); or_connection_t *c1 = or_connection_new(CONN_TYPE_OR, AF_INET);
var_cell_t *cell1=NULL, *cell2=NULL; var_cell_t *cell1=NULL, *cell2=NULL;
crypto_pk_t *rsa0 = pk_generate(0), *rsa1 = pk_generate(1);
tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER,
rsa0, rsa1, 86400), ==, 0);
init_mock_ed_keys(rsa0);
MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell);
tt_int_op(connection_init_or_handshake_state(c1, 0), ==, 0); tt_int_op(connection_init_or_handshake_state(c1, 0), ==, 0);
@ -905,6 +931,8 @@ test_link_handshake_send_authchallenge(void *arg)
connection_free_(TO_CONN(c1)); connection_free_(TO_CONN(c1));
tor_free(cell1); tor_free(cell1);
tor_free(cell2); tor_free(cell2);
crypto_pk_free(rsa0);
crypto_pk_free(rsa1);
} }
typedef struct authchallenge_data_s { typedef struct authchallenge_data_s {
@ -1118,6 +1146,7 @@ authenticate_data_cleanup(const struct testcase_t *test, void *arg)
(void) test; (void) test;
UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(connection_or_write_var_cell_to_buf);
UNMOCK(tor_tls_get_peer_cert); UNMOCK(tor_tls_get_peer_cert);
UNMOCK(tor_tls_get_own_cert);
UNMOCK(tor_tls_get_tlssecrets); UNMOCK(tor_tls_get_tlssecrets);
UNMOCK(connection_or_close_for_error); UNMOCK(connection_or_close_for_error);
UNMOCK(channel_set_circid_type); UNMOCK(channel_set_circid_type);
@ -1135,7 +1164,11 @@ authenticate_data_cleanup(const struct testcase_t *test, void *arg)
crypto_pk_free(d->key2); crypto_pk_free(d->key2);
tor_free(d); tor_free(d);
} }
tor_x509_cert_free(mock_peer_cert);
tor_x509_cert_free(mock_own_cert);
mock_peer_cert = NULL; mock_peer_cert = NULL;
mock_own_cert = NULL;
return 1; return 1;
} }
@ -1149,6 +1182,7 @@ authenticate_data_setup(const struct testcase_t *test)
MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell);
MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert);
MOCK(tor_tls_get_own_cert, mock_get_own_cert);
MOCK(tor_tls_get_tlssecrets, mock_get_tlssecrets); MOCK(tor_tls_get_tlssecrets, mock_get_tlssecrets);
MOCK(connection_or_close_for_error, mock_close_for_err); MOCK(connection_or_close_for_error, mock_close_for_err);
MOCK(channel_set_circid_type, mock_set_circid_type); MOCK(channel_set_circid_type, mock_set_circid_type);
@ -1215,6 +1249,9 @@ authenticate_data_setup(const struct testcase_t *test)
mock_peer_cert = tor_x509_cert_decode(der, sz); mock_peer_cert = tor_x509_cert_decode(der, sz);
tt_assert(mock_peer_cert); tt_assert(mock_peer_cert);
mock_own_cert = tor_x509_cert_decode(der, sz);
tt_assert(mock_own_cert);
/* Make an authenticate cell ... */ /* Make an authenticate cell ... */
int authtype; int authtype;
if (is_ed) if (is_ed)

View File

@ -450,8 +450,8 @@ test_routerkeys_ed_keys_init_all(void *arg)
options->DataDirectory = dir; options->DataDirectory = dir;
tt_int_op(0, ==, load_ed_keys(options, now)); tt_int_op(1, ==, load_ed_keys(options, now));
tt_int_op(0, ==, generate_ed_link_cert(options, now)); tt_int_op(0, ==, generate_ed_link_cert(options, now, 0));
tt_assert(get_master_identity_key()); tt_assert(get_master_identity_key());
tt_assert(get_master_identity_key()); tt_assert(get_master_identity_key());
tt_assert(get_master_signing_keypair()); tt_assert(get_master_signing_keypair());
@ -466,7 +466,7 @@ test_routerkeys_ed_keys_init_all(void *arg)
/* Call load_ed_keys again, but nothing has changed. */ /* Call load_ed_keys again, but nothing has changed. */
tt_int_op(0, ==, load_ed_keys(options, now)); tt_int_op(0, ==, load_ed_keys(options, now));
tt_int_op(0, ==, generate_ed_link_cert(options, now)); tt_int_op(0, ==, generate_ed_link_cert(options, now, 0));
tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id));
tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign));
tt_mem_op(&auth, ==, get_current_auth_keypair(), sizeof(auth)); tt_mem_op(&auth, ==, get_current_auth_keypair(), sizeof(auth));
@ -474,8 +474,8 @@ test_routerkeys_ed_keys_init_all(void *arg)
/* Force a reload: we make new link/auth keys. */ /* Force a reload: we make new link/auth keys. */
routerkeys_free_all(); routerkeys_free_all();
tt_int_op(0, ==, load_ed_keys(options, now)); tt_int_op(1, ==, load_ed_keys(options, now));
tt_int_op(0, ==, generate_ed_link_cert(options, now)); tt_int_op(0, ==, generate_ed_link_cert(options, now, 0));
tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id));
tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign));
tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert()));
@ -489,7 +489,7 @@ test_routerkeys_ed_keys_init_all(void *arg)
/* Force a link/auth-key regeneration by advancing time. */ /* Force a link/auth-key regeneration by advancing time. */
tt_int_op(0, ==, load_ed_keys(options, now+3*86400)); tt_int_op(0, ==, load_ed_keys(options, now+3*86400));
tt_int_op(0, ==, generate_ed_link_cert(options, now+3*86400)); tt_int_op(0, ==, generate_ed_link_cert(options, now+3*86400, 0));
tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id));
tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign));
tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert()));
@ -502,8 +502,8 @@ test_routerkeys_ed_keys_init_all(void *arg)
memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); memcpy(&auth, get_current_auth_keypair(), sizeof(auth));
/* Force a signing-key regeneration by advancing time. */ /* Force a signing-key regeneration by advancing time. */
tt_int_op(0, ==, load_ed_keys(options, now+100*86400)); tt_int_op(1, ==, load_ed_keys(options, now+100*86400));
tt_int_op(0, ==, generate_ed_link_cert(options, now+100*86400)); tt_int_op(0, ==, generate_ed_link_cert(options, now+100*86400, 0));
tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id));
tt_mem_op(&sign, !=, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&sign, !=, get_master_signing_keypair(), sizeof(sign));
tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert()));
@ -520,8 +520,8 @@ test_routerkeys_ed_keys_init_all(void *arg)
routerkeys_free_all(); routerkeys_free_all();
unlink(get_fname("test_ed_keys_init_all/keys/" unlink(get_fname("test_ed_keys_init_all/keys/"
"ed25519_master_id_secret_key")); "ed25519_master_id_secret_key"));
tt_int_op(0, ==, load_ed_keys(options, now)); tt_int_op(1, ==, load_ed_keys(options, now));
tt_int_op(0, ==, generate_ed_link_cert(options, now)); tt_int_op(0, ==, generate_ed_link_cert(options, now, 0));
tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id)); tt_mem_op(&id, ==, get_master_identity_key(), sizeof(id));
tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&sign, ==, get_master_signing_keypair(), sizeof(sign));
tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert()));

View File

@ -48,7 +48,7 @@ init_authority_state(void)
mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
tt_assert(mock_cert); tt_assert(mock_cert);
options->AuthoritativeDir = 1; options->AuthoritativeDir = 1;
tt_int_op(0, ==, load_ed_keys(options, time(NULL))); tt_int_op(load_ed_keys(options, time(NULL)), OP_GE, 0);
sr_state_init(0, 0); sr_state_init(0, 0);
/* It's possible a commit has been generated in our state depending on /* It's possible a commit has been generated in our state depending on
* the phase we are currently in which uses "now" as the starting * the phase we are currently in which uses "now" as the starting
@ -286,7 +286,7 @@ test_sr_commit(void *arg)
tt_assert(auth_cert); tt_assert(auth_cert);
options->AuthoritativeDir = 1; options->AuthoritativeDir = 1;
tt_int_op(0, ==, load_ed_keys(options, now)); tt_int_op(load_ed_keys(options, time(NULL)), OP_GE, 0);
} }
/* Generate our commit object and validate it has the appropriate field /* Generate our commit object and validate it has the appropriate field