summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-06-01 09:26:24 -0400
committerNick Mathewson <nickm@torproject.org>2017-06-01 09:26:24 -0400
commit34a6755b94015fcbc838b46b54667899c238ac04 (patch)
tree5e904e93310020615cb0e0351e4effe05ab3d7f8 /src/or
parenta9be768959c189846178723d5fe44d3b59b0d983 (diff)
downloadtor-34a6755b94015fcbc838b46b54667899c238ac04.tar.gz
tor-34a6755b94015fcbc838b46b54667899c238ac04.zip
Fix ed25519 link certificate race on tls context rotation
Whenever we rotate our TLS context, we change our Ed25519 Signing->Link certificate. But if we've already started a TLS connection, then we've already sent the old X509 link certificate, so the new Ed25519 Signing->Link certificate won't match it. To fix this, we now store a copy of the Signing->Link certificate when we initialize the handshake state, and send that certificate as part of our CERTS cell. Fixes one case of bug22460; bugfix on 0.3.0.1-alpha.
Diffstat (limited to 'src/or')
-rw-r--r--src/or/connection_or.c6
-rw-r--r--src/or/or.h6
2 files changed, 11 insertions, 1 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index cefe42c4db..0966ec8acb 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1855,6 +1855,9 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
s->started_here = started_here ? 1 : 0;
s->digest_sent_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->started_here = s->started_here;
return 0;
@@ -1869,6 +1872,7 @@ or_handshake_state_free(or_handshake_state_t *state)
crypto_digest_free(state->digest_sent);
crypto_digest_free(state->digest_received);
or_handshake_certs_free(state->certs);
+ tor_cert_free(state->own_link_cert);
memwipe(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
@@ -2311,7 +2315,7 @@ connection_or_send_certs_cell(or_connection_t *conn)
if (conn_in_server_mode) {
add_ed25519_cert(certs_cell,
CERTTYPE_ED_SIGN_LINK,
- get_current_link_cert_cert());
+ conn->handshake_state->own_link_cert);
} else {
add_ed25519_cert(certs_cell,
CERTTYPE_ED_SIGN_AUTH,
diff --git a/src/or/or.h b/src/or/or.h
index 0db9f23604..50e6e3e71b 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1449,6 +1449,12 @@ typedef struct or_handshake_state_t {
/* True iff we have sent a netinfo cell */
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
* digest_received respectively.
*