diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-06-01 09:26:24 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-06-01 09:26:24 -0400 |
commit | 34a6755b94015fcbc838b46b54667899c238ac04 (patch) | |
tree | 5e904e93310020615cb0e0351e4effe05ab3d7f8 /src/or | |
parent | a9be768959c189846178723d5fe44d3b59b0d983 (diff) | |
download | tor-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.c | 6 | ||||
-rw-r--r-- | src/or/or.h | 6 |
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. * |