tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit 9afd8fb6252ec73829c4fc376a12bbf0f467642b
parent 7ae5e798d6f9d96de928370a1e7b6fdb0b03d394
Author: David Goulet <dgoulet@torproject.org>
Date:   Mon,  5 May 2025 14:38:52 +0000

Merge branch 'openssl_cleanup_part1' into 'main'

Remove support for clients < 0.2.3.17-beta

Closes #41031

See merge request tpo/core/tor!883
Diffstat:
Achanges/41031 | 8++++++++
Msrc/core/mainloop/connection.c | 17++++++-----------
Msrc/core/or/channeltls.c | 40++++------------------------------------
Msrc/core/or/connection_or.c | 207++++---------------------------------------------------------------------------
Msrc/core/or/connection_or.h | 1-
Msrc/core/or/orconn_event.h | 18+++++-------------
Msrc/core/or/protover.c | 2+-
Msrc/feature/control/btrack_orconn_cevent.c | 4----
Msrc/lib/tls/tortls.c | 42------------------------------------------
Msrc/lib/tls/tortls.h | 10----------
Msrc/lib/tls/tortls_internal.h | 14--------------
Msrc/lib/tls/tortls_nss.c | 81+------------------------------------------------------------------------------
Msrc/lib/tls/tortls_openssl.c | 564++++---------------------------------------------------------------------------
Msrc/lib/tls/tortls_st.h | 7-------
Msrc/test/test_protover.c | 6+++---
Msrc/test/test_tortls.c | 111-------------------------------------------------------------------------------
Msrc/test/test_tortls_openssl.c | 115-------------------------------------------------------------------------------
17 files changed, 60 insertions(+), 1187 deletions(-)

diff --git a/changes/41031 b/changes/41031 @@ -0,0 +1,8 @@ + o Removed features: + - Relays no longer support clients that require obsolete v1 and v2 + link handshakes. (The v3 link handshake has been supported since + 0.2.3.6-alpha). Part of ticket 41031. + - Relays no longer support clients that falsely advertise TLS + ciphers they don't really support. + (Clients have not done this since 0.2.3.17-beta). + Part of ticket 41031. diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c @@ -314,12 +314,8 @@ conn_state_to_string(int type, int state) case OR_CONN_STATE_CONNECTING: return "connect()ing"; case OR_CONN_STATE_PROXY_HANDSHAKING: return "handshaking (proxy)"; case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)"; - case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - return "renegotiating (TLS, v2 handshake)"; - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: - return "waiting for renegotiation or V3 handshake"; - case OR_CONN_STATE_OR_HANDSHAKING_V2: - return "handshaking (Tor, v2 handshake)"; + case OR_CONN_STATE_SERVER_VERSIONS_WAIT: + return "waiting for V3+ handshake"; case OR_CONN_STATE_OR_HANDSHAKING_V3: return "handshaking (Tor, v3 handshake)"; case OR_CONN_STATE_OPEN: return "open"; @@ -4163,8 +4159,7 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read, int pending; or_connection_t *or_conn = TO_OR_CONN(conn); size_t initial_size; - if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING || - conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { + if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING) { /* continue handshaking even if global token bucket is empty */ return connection_tls_continue_handshake(or_conn); } @@ -4206,6 +4201,7 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read, * again. Stop waiting for write events now, or else we'll * busy-loop until data arrives for us to read. * XXX: remove this when v2 handshakes support is dropped. */ + // XXXX Try to make sense of what is going on here. connection_stop_writing(conn); if (!connection_is_reading(conn)) connection_start_reading(conn); @@ -4493,8 +4489,7 @@ connection_handle_write_impl(connection_t *conn, int force) conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) { or_connection_t *or_conn = TO_OR_CONN(conn); size_t initial_size; - if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING || - conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { + if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING) { connection_stop_writing(conn); if (connection_tls_continue_handshake(or_conn) < 0) { /* Don't flush; connection is dead. */ @@ -4511,7 +4506,7 @@ connection_handle_write_impl(connection_t *conn, int force) return -1; } return 0; - } else if (conn->state == OR_CONN_STATE_TLS_SERVER_RENEGOTIATING) { + } else if (conn->state == OR_CONN_STATE_SERVER_VERSIONS_WAIT) { return connection_handle_read(conn); } diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c @@ -1238,26 +1238,6 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn) return; switch (TO_CONN(conn)->state) { - case OR_CONN_STATE_OR_HANDSHAKING_V2: - if (var_cell->command != CELL_VERSIONS) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received a cell with command %d in unexpected " - "orconn state \"%s\" [%d], channel state \"%s\" [%d]; " - "closing the connection.", - (int)(var_cell->command), - conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state), - TO_CONN(conn)->state, - channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), - (int)(TLS_CHAN_TO_BASE(chan)->state)); - /* - * The code in connection_or.c will tell channel_t to close for - * error; it will go to CHANNEL_STATE_CLOSING, and then to - * CHANNEL_STATE_ERROR when conn is closed. - */ - connection_or_close_for_error(conn, 0); - return; - } - break; case OR_CONN_STATE_TLS_HANDSHAKING: /* If we're using bufferevents, it's entirely possible for us to * notice "hey, data arrived!" before we notice "hey, the handshake @@ -1266,7 +1246,7 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn) /* But that should be happening any longer've disabled bufferevents. */ tor_assert_nonfatal_unreached_once(); FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL; - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + case OR_CONN_STATE_SERVER_VERSIONS_WAIT: if (!(command_allowed_before_handshake(var_cell->command))) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received a cell with command %d in unexpected " @@ -1436,14 +1416,13 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan) tor_assert(TO_CONN(chan->conn)->state == OR_CONN_STATE_TLS_HANDSHAKING || TO_CONN(chan->conn)->state == - OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); + OR_CONN_STATE_SERVER_VERSIONS_WAIT); if (started_here) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a cell while TLS-handshaking, not in " "OR_HANDSHAKING_V3, on a connection we originated."); } - connection_or_block_renegotiation(chan->conn); connection_or_change_state(chan->conn, OR_CONN_STATE_OR_HANDSHAKING_V3); if (connection_init_or_handshake_state(chan->conn, started_here) < 0) { connection_or_close_for_error(chan->conn, 0); @@ -1494,11 +1473,10 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) } switch (chan->conn->base_.state) { - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: break; case OR_CONN_STATE_TLS_HANDSHAKING: - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + case OR_CONN_STATE_SERVER_VERSIONS_WAIT: default: log_fn(LOG_PROTOCOL_WARN, LD_OR, "VERSIONS cell while in unexpected state"); @@ -1537,15 +1515,6 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) "handshake. Closing connection."); connection_or_close_for_error(chan->conn, 0); return; - } else if (highest_supported_version != 2 && - chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V2) { - /* XXXX This should eventually be a log_protocol_warn */ - log_fn(LOG_WARN, LD_OR, - "Negotiated link with non-2 protocol after doing a v2 TLS " - "handshake with %s. Closing connection.", - connection_describe_peer(TO_CONN(chan->conn))); - connection_or_close_for_error(chan->conn, 0); - return; } rep_hist_note_negotiated_link_proto(highest_supported_version, started_here); @@ -1733,8 +1702,7 @@ can_process_netinfo_cell(const channel_tls_t *chan) } /* Can't process a NETINFO cell if the connection is not handshaking. */ - if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 && - chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) { + if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a NETINFO cell on non-handshaking connection; dropping."); return false; diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c @@ -83,14 +83,8 @@ #include "core/or/orconn_event.h" -static int connection_tls_finish_handshake(or_connection_t *conn); static int connection_or_launch_v3_or_handshake(or_connection_t *conn); static int connection_or_process_cells_from_inbuf(or_connection_t *conn); -static int connection_or_check_valid_tls_handshake(or_connection_t *conn, - int started_here, - char *digest_rcvd_out); - -static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn); static unsigned int connection_or_is_bad_for_new_circs(or_connection_t *or_conn); @@ -602,9 +596,8 @@ connection_or_process_inbuf(or_connection_t *conn) } return ret; - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: case OR_CONN_STATE_OPEN: - case OR_CONN_STATE_OR_HANDSHAKING_V2: + case OR_CONN_STATE_SERVER_VERSIONS_WAIT: case OR_CONN_STATE_OR_HANDSHAKING_V3: return connection_or_process_cells_from_inbuf(conn); default: @@ -708,7 +701,6 @@ connection_or_finished_flushing(or_connection_t *conn) } break; case OR_CONN_STATE_OPEN: - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: break; default: @@ -1690,35 +1682,6 @@ connection_tls_start_handshake,(or_connection_t *conn, int receiving)) return 0; } -/** Block all future attempts to renegotiate on 'conn' */ -void -connection_or_block_renegotiation(or_connection_t *conn) -{ - tor_tls_t *tls = conn->tls; - if (!tls) - return; - tor_tls_set_renegotiate_callback(tls, NULL, NULL); - tor_tls_block_renegotiation(tls); -} - -/** Invoked on the server side from inside tor_tls_read() when the server - * gets a successful TLS renegotiation from the client. */ -static void -connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn) -{ - or_connection_t *conn = _conn; - (void)tls; - - /* Don't invoke this again. */ - connection_or_block_renegotiation(conn); - - if (connection_tls_finish_handshake(conn) < 0) { - /* XXXX_TLS double-check that it's ok to do this from inside read. */ - /* XXXX_TLS double-check that this verifies certificates. */ - connection_or_close_for_error(conn, 0); - } -} - /** Move forward with the tls handshake. If it finishes, hand * <b>conn</b> to connection_tls_finish_handshake(). * @@ -1742,26 +1705,24 @@ connection_tls_continue_handshake(or_connection_t *conn) tor_tls_err_to_string(result)); return -1; case TOR_TLS_DONE: - if (! tor_tls_used_v1_handshake(conn->tls)) { + { if (!tor_tls_is_server(conn->tls)) { tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING); return connection_or_launch_v3_or_handshake(conn); } else { - /* v2/v3 handshake, but we are not a client. */ + /* v3+ handshake, but we are not a client. */ log_debug(LD_OR, "Done with initial SSL handshake (server-side). " - "Expecting renegotiation or VERSIONS cell"); - tor_tls_set_renegotiate_callback(conn->tls, - connection_or_tls_renegotiated_cb, - conn); + "Expecting VERSIONS cell"); + /* Note: We could instead just send a VERSIONS cell now, + * since the V2 handshake is no longer a thing. + * But that would require re-plumbing this state machine. */ connection_or_change_state(conn, - OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); + OR_CONN_STATE_SERVER_VERSIONS_WAIT); connection_stop_writing(TO_CONN(conn)); connection_start_reading(TO_CONN(conn)); return 0; } } - tor_assert(tor_tls_is_server(conn->tls)); - return connection_tls_finish_handshake(conn); case TOR_TLS_WANTWRITE: connection_start_writing(TO_CONN(conn)); log_debug(LD_OR,"wanted write"); @@ -1792,102 +1753,6 @@ connection_or_nonopen_was_started_here(or_connection_t *conn) return !tor_tls_is_server(conn->tls); } -/** <b>Conn</b> just completed its handshake. Return 0 if all is well, and - * return -1 if they are lying, broken, or otherwise something is wrong. - * - * If we initiated this connection (<b>started_here</b> is true), make sure - * the other side sent a correctly formed certificate. If I initiated the - * connection, make sure it's the right relay by checking the certificate. - * - * Otherwise (if we _didn't_ initiate this connection), it's okay for - * the certificate to be weird or absent. - * - * If we return 0, and the certificate is as expected, write a hash of the - * identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN - * space in it. - * If the certificate is invalid or missing on an incoming connection, - * we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes. - * (If we return -1, the contents of this buffer are undefined.) - * - * As side effects, - * 1) Set conn->circ_id_type according to tor-spec.txt. - * 2) If we're an authdirserver and we initiated the connection: drop all - * descriptors that claim to be on that IP/port but that aren't - * this relay; and note that this relay is reachable. - * 3) If this is a bridge and we didn't configure its identity - * fingerprint, remember the keyid we just learned. - */ -static int -connection_or_check_valid_tls_handshake(or_connection_t *conn, - int started_here, - char *digest_rcvd_out) -{ - crypto_pk_t *identity_rcvd=NULL; - const or_options_t *options = get_options(); - int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN; - const char *conn_type = started_here ? "outgoing" : "incoming"; - int has_cert = 0; - - check_no_tls_errors(); - has_cert = tor_tls_peer_has_cert(conn->tls); - if (started_here && !has_cert) { - log_info(LD_HANDSHAKE,"Tried connecting to router at %s, but it didn't " - "send a cert! Closing.", - connection_describe_peer(TO_CONN(conn))); - return -1; - } else if (!has_cert) { - log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. " - "That's ok."); - } - check_no_tls_errors(); - - if (has_cert) { - int v = tor_tls_verify(started_here?severity:LOG_INFO, - conn->tls, time(NULL), &identity_rcvd); - if (started_here && v<0) { - log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s: It" - " has a cert but it's invalid. Closing.", - connection_describe_peer(TO_CONN(conn))); - return -1; - } else if (v<0) { - log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert " - "chain; ignoring."); - } else { - log_debug(LD_HANDSHAKE, - "The certificate seems to be valid on %s connection " - "with %s", conn_type, - connection_describe_peer(TO_CONN(conn))); - } - check_no_tls_errors(); - } - - if (identity_rcvd) { - if (crypto_pk_get_digest(identity_rcvd, digest_rcvd_out) < 0) { - crypto_pk_free(identity_rcvd); - return -1; - } - } else { - memset(digest_rcvd_out, 0, DIGEST_LEN); - } - - tor_assert(conn->chan); - channel_set_circid_type(TLS_CHAN_TO_BASE(conn->chan), identity_rcvd, 1); - - crypto_pk_free(identity_rcvd); - - if (started_here) { - /* A TLS handshake can't teach us an Ed25519 ID, so we set it to NULL - * here. */ - log_debug(LD_HANDSHAKE, "Calling client_learned_peer_id from " - "check_valid_tls_handshake"); - return connection_or_client_learned_peer_id(conn, - (const uint8_t*)digest_rcvd_out, - NULL); - } - - return 0; -} - /** Called when we (as a connection initiator) have definitively, * authenticatedly, learned that ID of the Tor instance on the other * side of <b>conn</b> is <b>rsa_peer_id</b> and optionally <b>ed_peer_id</b>. @@ -2079,58 +1944,6 @@ connection_or_client_used(or_connection_t *conn) } else return 0; } -/** The v1/v2 TLS handshake is finished. - * - * Make sure we are happy with the peer we just handshaked with. - * - * If they initiated the connection, make sure they're not already connected, - * then initialize conn from the information in router. - * - * If all is successful, call circuit_n_conn_done() to handle events - * that have been pending on the <tls handshake completion. Also set the - * directory to be dirty (only matters if I'm an authdirserver). - * - * If this is a v2 TLS handshake, send a versions cell. - */ -static int -connection_tls_finish_handshake(or_connection_t *conn) -{ - char digest_rcvd[DIGEST_LEN]; - int started_here = connection_or_nonopen_was_started_here(conn); - - tor_assert(!started_here); - - log_debug(LD_HANDSHAKE,"%s tls handshake on %s done, using " - "ciphersuite %s. verifying.", - started_here?"outgoing":"incoming", - connection_describe_peer(TO_CONN(conn)), - tor_tls_get_ciphersuite_name(conn->tls)); - - if (connection_or_check_valid_tls_handshake(conn, started_here, - digest_rcvd) < 0) - return -1; - - circuit_build_times_network_is_live(get_circuit_build_times_mutable()); - - if (tor_tls_used_v1_handshake(conn->tls)) { - conn->link_proto = 1; - connection_or_init_conn_from_address(conn, &conn->base_.addr, - conn->base_.port, digest_rcvd, - NULL, 0); - tor_tls_block_renegotiation(conn->tls); - rep_hist_note_negotiated_link_proto(1, started_here); - return connection_or_set_state_open(conn); - } else { - connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V2); - if (connection_init_or_handshake_state(conn, started_here) < 0) - return -1; - connection_or_init_conn_from_address(conn, &conn->base_.addr, - conn->base_.port, digest_rcvd, - NULL, 0); - return connection_or_send_versions(conn, 0); - } -} - /** * Called as client when initial TLS handshake is done, and we notice * that we got a v3-handshake signalling certificate from the server. @@ -2427,8 +2240,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) } } -/** Array of recognized link protocol versions. */ -static const uint16_t or_protocol_versions[] = { 1, 2, 3, 4, 5 }; +/** Array of supported link protocol versions. */ +static const uint16_t or_protocol_versions[] = { 3, 4, 5 }; /** Number of versions in <b>or_protocol_versions</b>. */ static const int n_or_protocol_versions = (int)( sizeof(or_protocol_versions)/sizeof(uint16_t) ); diff --git a/src/core/or/connection_or.h b/src/core/or/connection_or.h @@ -24,7 +24,6 @@ void connection_or_clear_identity(or_connection_t *conn); void connection_or_clear_identity_map(void); void clear_broken_connection_map(int disable); -void connection_or_block_renegotiation(or_connection_t *conn); int connection_or_reached_eof(or_connection_t *conn); int connection_or_process_inbuf(or_connection_t *conn); ssize_t connection_or_num_cells_writeable(or_connection_t *conn); diff --git a/src/core/or/orconn_event.h b/src/core/or/orconn_event.h @@ -34,24 +34,16 @@ /** State for an OR connection client: SSL is handshaking, not done * yet. */ #define OR_CONN_STATE_TLS_HANDSHAKING 3 -/** State for a connection to an OR: We're doing a second SSL handshake for - * renegotiation purposes. (V2 handshake only.) */ -#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4 /** State for a connection at an OR: We're waiting for the client to - * renegotiate (to indicate a v2 handshake) or send a versions cell (to - * indicate a v3 handshake) */ -#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5 -/** State for an OR connection: We're done with our SSL handshake, we've done - * renegotiation, but we haven't yet negotiated link protocol versions and - * sent a netinfo cell. */ -#define OR_CONN_STATE_OR_HANDSHAKING_V2 6 + * send a versions cell (to indicate a v3+ handshake) */ +#define OR_CONN_STATE_SERVER_VERSIONS_WAIT 4 /** State for an OR connection: We're done with our SSL handshake, but we * haven't yet negotiated link protocol versions, done a V3 handshake, and * sent a netinfo cell. */ -#define OR_CONN_STATE_OR_HANDSHAKING_V3 7 +#define OR_CONN_STATE_OR_HANDSHAKING_V3 5 /** State for an OR connection: Ready to send/receive cells. */ -#define OR_CONN_STATE_OPEN 8 -#define OR_CONN_STATE_MAX_ 8 +#define OR_CONN_STATE_OPEN 6 +#define OR_CONN_STATE_MAX_ 6 /** @} */ /** Used to indicate the type of an OR connection event passed to the diff --git a/src/core/or/protover.c b/src/core/or/protover.c @@ -395,7 +395,7 @@ protocol_list_supports_protocol_or_later(const char *list, #define PR_HSDIR_V "2" #define PR_HSINTRO_V "4-5" #define PR_HSREND_V "1-2" -#define PR_LINK_V "1-5" +#define PR_LINK_V "3-5" #define PR_LINKAUTH_V "3" #define PR_MICRODESC_V "1-3" #define PR_PADDING_V "2" diff --git a/src/feature/control/btrack_orconn_cevent.c b/src/feature/control/btrack_orconn_cevent.c @@ -86,8 +86,6 @@ bto_cevent_anyconn(const bt_orconn_t *bto) case OR_CONN_STATE_TLS_HANDSHAKING: control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE, 0); break; - case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); break; @@ -140,8 +138,6 @@ bto_cevent_apconn(const bt_orconn_t *bto) case OR_CONN_STATE_TLS_HANDSHAKING: control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE, 0); break; - case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE, 0); break; diff --git a/src/lib/tls/tortls.c b/src/lib/tls/tortls.c @@ -393,48 +393,6 @@ tor_tls_free_(tor_tls_t *tls) tor_free(tls); } -/** 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, time_t now, - crypto_pk_t **identity) -{ - tor_x509_cert_impl_t *cert = NULL, *id_cert = NULL; - tor_x509_cert_t *peer_x509 = NULL, *id_x509 = NULL; - tor_assert(tls); - tor_assert(identity); - int rv = -1; - - 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; - } - peer_x509 = tor_x509_cert_new(cert); - id_x509 = tor_x509_cert_new(id_cert); - cert = id_cert = NULL; /* Prevent double-free */ - - if (! tor_tls_cert_is_valid(severity, peer_x509, id_x509, now, 0)) { - goto done; - } - - *identity = tor_tls_cert_get_key(id_x509); - rv = 0; - - done: - tor_x509_cert_impl_free(cert); - tor_x509_cert_impl_free(id_cert); - tor_x509_cert_free(peer_x509); - tor_x509_cert_free(id_x509); - - return rv; -} - static void subsys_tortls_shutdown(void) { diff --git a/src/lib/tls/tortls.h b/src/lib/tls/tortls.h @@ -89,9 +89,6 @@ void tor_tls_context_decref(tor_tls_context_t *ctx); tor_tls_context_t *tor_tls_context_get(int is_server); tor_tls_t *tor_tls_new(tor_socket_t 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_release_socket(tor_tls_t *tls); void tor_tls_free_(tor_tls_t *tls); @@ -99,14 +96,9 @@ void tor_tls_free_(tor_tls_t *tls); int tor_tls_peer_has_cert(tor_tls_t *tls); MOCK_DECL(struct tor_x509_cert_t *,tor_tls_get_peer_cert,(tor_tls_t *tls)); MOCK_DECL(struct tor_x509_cert_t *,tor_tls_get_own_cert,(tor_tls_t *tls)); -int tor_tls_verify(int severity, tor_tls_t *tls, time_t now, - crypto_pk_t **identity); 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); int tor_tls_get_pending_bytes(tor_tls_t *tls); size_t tor_tls_get_forced_write_size(tor_tls_t *tls); @@ -119,9 +111,7 @@ int tor_tls_get_buffer_sizes(tor_tls_t *tls, 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_cert_matches_key,(const tor_tls_t *tls, const struct tor_x509_cert_t *cert)); MOCK_DECL(int,tor_tls_export_key_material,( diff --git a/src/lib/tls/tortls_internal.h b/src/lib/tls/tortls_internal.h @@ -18,10 +18,6 @@ int tor_errno_to_tls_error(int e); int tor_tls_get_error(tor_tls_t *tls, int r, int extra, const char *doing, int severity, int domain); #endif -MOCK_DECL(void, try_to_extract_certs_from_tls, - (int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out)); tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, unsigned flags, int is_client); @@ -44,7 +40,6 @@ void tor_tls_context_impl_free_(tor_tls_context_impl_t *); #ifdef ENABLE_OPENSSL tor_tls_t *tor_tls_get_by_ssl(const struct ssl_st *ssl); -int tor_tls_client_is_using_v2_ciphers(const struct ssl_st *ssl); void tor_tls_debug_state_callback(const struct ssl_st *ssl, int type, int val); void tor_tls_server_info_callback(const struct ssl_st *ssl, @@ -53,15 +48,6 @@ void tor_tls_allocate_tor_tls_object_ex_data_index(void); #ifdef TORTLS_OPENSSL_PRIVATE int always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx); -int tor_tls_classify_client_ciphers(const struct ssl_st *ssl, - STACK_OF(SSL_CIPHER) *peer_ciphers); -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) */ #endif /* defined(ENABLE_OPENSSL) */ diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c @@ -46,34 +46,6 @@ ENABLE_GCC_WARNING("-Wstrict-prototypes") static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool); -MOCK_IMPL(void, -try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out)) -{ - tor_assert(tls); - tor_assert(cert_out); - tor_assert(id_cert_out); - (void) severity; - - *cert_out = *id_cert_out = NULL; - - CERTCertificate *peer = SSL_PeerCertificate(tls->ssl); - if (!peer) - return; - *cert_out = peer; /* Now owns pointer. */ - - CERTCertList *chain = SSL_PeerCertificateChain(tls->ssl); - CERTCertListNode *c = CERT_LIST_HEAD(chain); - for (; !CERT_LIST_END(c, chain); c = CERT_LIST_NEXT(c)) { - if (CERT_CompareCerts(c->cert, peer) == PR_FALSE) { - *id_cert_out = CERT_DupCertificate(c->cert); - break; - } - } - CERT_DestroyCertList(chain); -} - static bool we_like_ssl_cipher(SSLCipherAlgorithm ca) { @@ -464,18 +436,6 @@ tor_tls_new(tor_socket_t sock, int is_server) return tls; } -void -tor_tls_set_renegotiate_callback(tor_tls_t *tls, - void (*cb)(tor_tls_t *, void *arg), - void *arg) -{ - tor_assert(tls); - (void)cb; - (void)arg; - - /* We don't support renegotiation-based TLS with NSS. */ -} - /** * Tell the TLS library that the underlying socket for <b>tls</b> has been * closed, and the library should not attempt to free that socket itself. @@ -619,7 +579,7 @@ tor_tls_handshake(tor_tls_t *tls) if (s == SECSuccess) { tls->state = TOR_TLS_ST_OPEN; log_debug(LD_NET, "SSL handshake is supposedly complete."); - return tor_tls_finish_handshake(tls); + return TOR_TLS_DONE; } if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) return TOR_TLS_WANTREAD; /* XXXX What about wantwrite? */ @@ -628,29 +588,6 @@ tor_tls_handshake(tor_tls_t *tls) } int -tor_tls_finish_handshake(tor_tls_t *tls) -{ - tor_assert(tls); - // We don't need to do any of the weird handshake nonsense stuff on NSS, - // since we only support recent handshakes. - return TOR_TLS_DONE; -} - -void -tor_tls_unblock_renegotiation(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support renegotiation with NSS. */ -} - -void -tor_tls_block_renegotiation(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support renegotiation with NSS. */ -} - -int tor_tls_get_pending_bytes(tor_tls_t *tls) { tor_assert(tls); @@ -713,22 +650,6 @@ tls_get_write_overhead_ratio, (void)) return 0.95; } -int -tor_tls_used_v1_handshake(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support or allow the V1 handshake with NSS. - */ - return 0; -} - -int -tor_tls_server_got_renegotiate(tor_tls_t *tls) -{ - tor_assert(tls); - return 0; /* We don't support renegotiation with NSS */ -} - MOCK_IMPL(int, tor_tls_cert_matches_key,(const tor_tls_t *tls, const struct tor_x509_cert_t *cert)) diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c @@ -88,38 +88,9 @@ ENABLE_GCC_WARNING("-Wredundant-decls") #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 - /** Set to true iff openssl bug 7712 has been detected. */ static int openssl_bug_7712_is_present = 0; -/** 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; @@ -395,20 +366,6 @@ always_accept_verify_cb(int preverify_ok, return 1; } -/** 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 /* defined(TLS1_3_TXT_AES_128_GCM_SHA256) */ - 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[] = @@ -611,13 +568,12 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, 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); - } +#ifdef SSL_OP_NO_RENEGOTIATION + SSL_CTX_set_options(result->ctx, SSL_OP_NO_RENEGOTIATION); +#endif +#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION + SSL_CTX_set_options(result->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); +#endif /* 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 @@ -641,11 +597,10 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, result->my_link_cert->cert)) { goto error; } - if (result->my_id_cert) { - X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); - tor_assert(s); - X509_STORE_add_cert(s, result->my_id_cert->cert); - } + // Here we would once add my_id_cert too via X509_STORE_add_cert. + // + // We no longer do that, since we no longer send multiple certs; + // that was part of the obsolete v1 handshake. } SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); if (!is_client) { @@ -735,8 +690,14 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, EC_KEY_free(ec_key); } #endif /* defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SET1...) */ - SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, - always_accept_verify_cb); + + if (is_client) { + SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, + always_accept_verify_cb); + } else { + /* Don't send a certificate request at all if we're not a client. */ + SSL_CTX_set_verify(result->ctx, SSL_VERIFY_NONE, NULL); + } /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); @@ -773,329 +734,6 @@ 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. */ -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, tor_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, tor_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. - **/ -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 && peer_ciphers) - 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. */ -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> - */ -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; - } 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. - */ -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. */ @@ -1132,7 +770,8 @@ tor_tls_new(tor_socket_t sock, int isServer) #endif /* defined(SSL_CTRL_SET_MAX_PROTO_VERSION) */ if (!SSL_set_cipher_list(result->ssl, - isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) { + isServer ? UNRESTRICTED_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); @@ -1172,14 +811,8 @@ tor_tls_new(tor_socket_t sock, int isServer) 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); + SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); goto done; err: @@ -1190,51 +823,6 @@ tor_tls_new(tor_socket_t sock, int isServer) return result; } -/** 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 -} - /** * Tell the TLS library that the underlying socket for <b>tls</b> has been * closed, and the library should not attempt to free that socket itself. @@ -1284,13 +872,6 @@ tor_tls_read,(tor_tls_t *tls, char *cp, size_t len)) 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); @@ -1378,9 +959,7 @@ tor_tls_handshake(tor_tls_t *tls) 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, @@ -1389,52 +968,7 @@ tor_tls_handshake(tor_tls_t *tls) } 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; } @@ -1483,44 +1017,6 @@ tor_tls_get_own_cert,(tor_tls_t *tls)) return tor_x509_cert_new(duplicate); } -/** 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 both of the returned certificates. */ -MOCK_IMPL(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 ? X509_dup(id_cert) : NULL; -} - /** Return the number of bytes available for reading from <b>tls</b>. */ int @@ -1610,22 +1106,6 @@ check_no_tls_errors_(const char *fname, int 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 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; -} - /** 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 diff --git a/src/lib/tls/tortls_st.h b/src/lib/tls/tortls_st.h @@ -49,13 +49,6 @@ struct tor_tls_t { * 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; #ifdef ENABLE_OPENSSL /** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't * called that function yet. */ diff --git a/src/test/test_protover.c b/src/test/test_protover.c @@ -219,15 +219,15 @@ test_protover_all_supported(void *arg) tt_str_op(msg, OP_EQ, "Link=6-60"); tor_free(msg); tt_assert(! protover_all_supported("Link=1-3,50-63", &msg)); - tt_str_op(msg, OP_EQ, "Link=50-63"); + tt_str_op(msg, OP_EQ, "Link=1-2,50-63"); tor_free(msg); tt_assert(! protover_all_supported("Link=1-3,5-12", &msg)); - tt_str_op(msg, OP_EQ, "Link=6-12"); + tt_str_op(msg, OP_EQ, "Link=1-2,6-12"); tor_free(msg); /* Mix of protocols we do support and some we don't, where the protocols * we do support have some versions we don't support. */ - tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=40-41", &msg)); + tt_assert(! protover_all_supported("Link=3,5-12 Quokka=40-41", &msg)); tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=40-41"); tor_free(msg); diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c @@ -154,24 +154,6 @@ read_cert_from(const char *str) return res; } -static tor_x509_cert_impl_t * - fixed_try_to_extract_certs_from_tls_cert_out_result = NULL; -static tor_x509_cert_impl_t * - fixed_try_to_extract_certs_from_tls_id_cert_out_result = NULL; - -static void -fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out) -{ - (void) severity; - (void) tls; - *cert_out = tor_x509_cert_impl_dup_( - fixed_try_to_extract_certs_from_tls_cert_out_result); - *id_cert_out = tor_x509_cert_impl_dup_( - fixed_try_to_extract_certs_from_tls_id_cert_out_result); -} - static void test_tortls_errno_to_tls_error(void *data) { @@ -327,44 +309,6 @@ test_tortls_get_forced_write_size(void *ignored) done: tor_free(tls); } - -static void -test_tortls_used_v1_handshake(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - // These tests assume both V2 handshake server and client are enabled - tls->wasV2Handshake = 0; - ret = tor_tls_used_v1_handshake(tls); - tt_int_op(ret, OP_EQ, 1); - - tls->wasV2Handshake = 1; - ret = tor_tls_used_v1_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - - done: - tor_free(tls); -} - -static void -test_tortls_server_got_renegotiate(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tls->got_renegotiate = 1; - ret = tor_tls_server_got_renegotiate(tls); - tt_int_op(ret, OP_EQ, 1); - - done: - tor_free(tls); -} #endif /* defined(ENABLE_OPENSSL) */ static void @@ -492,58 +436,6 @@ test_tortls_is_server(void *arg) } static void -test_tortls_verify(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - crypto_pk_t *k = NULL; - tor_x509_cert_impl_t *cert1 = NULL, *cert2 = NULL, *invalidCert = NULL, - *validCert = NULL, *caCert = NULL; - time_t now = cert_strings_valid_at; - - validCert = read_cert_from(validCertString); - caCert = read_cert_from(caCertString); - invalidCert = read_cert_from(notCompletelyValidCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - MOCK(try_to_extract_certs_from_tls, fixed_try_to_extract_certs_from_tls); - - fixed_try_to_extract_certs_from_tls_cert_out_result = cert1; - ret = tor_tls_verify(LOG_WARN, tls, now, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_id_cert_out_result = cert2; - ret = tor_tls_verify(LOG_WARN, tls, now, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = invalidCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = invalidCert; - - ret = tor_tls_verify(LOG_WARN, tls, now, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = validCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = caCert; - - ret = tor_tls_verify(LOG_WARN, tls, now, &k); - tt_int_op(ret, OP_EQ, 0); - tt_assert(k); - - done: - UNMOCK(try_to_extract_certs_from_tls); - tor_x509_cert_impl_free(cert1); - tor_x509_cert_impl_free(cert2); - tor_x509_cert_impl_free(validCert); - tor_x509_cert_impl_free(invalidCert); - tor_x509_cert_impl_free(caCert); - - tor_free(tls); - crypto_pk_free(k); -} - -static void test_tortls_cert_matches_key(void *ignored) { (void)ignored; @@ -615,15 +507,12 @@ struct testcase_t tortls_tests[] = { #ifdef ENABLE_OPENSSL LOCAL_TEST_CASE(tor_tls_get_error, 0), LOCAL_TEST_CASE(get_forced_write_size, 0), - LOCAL_TEST_CASE(used_v1_handshake, TT_FORK), - LOCAL_TEST_CASE(server_got_renegotiate, 0), #endif /* defined(ENABLE_OPENSSL) */ LOCAL_TEST_CASE(evaluate_ecgroup_for_tls, 0), LOCAL_TEST_CASE(double_init, TT_FORK), LOCAL_TEST_CASE(address, TT_FORK), LOCAL_TEST_CASE(is_server, 0), LOCAL_TEST_CASE(bridge_init, TT_FORK), - LOCAL_TEST_CASE(verify, TT_FORK), LOCAL_TEST_CASE(cert_matches_key, 0), END_OF_TESTCASES }; diff --git a/src/test/test_tortls_openssl.c b/src/test/test_tortls_openssl.c @@ -662,49 +662,6 @@ test_tortls_classify_client_ciphers(void *ignored) } #endif /* !defined(OPENSSL_OPAQUE) */ -static void -test_tortls_client_is_using_v2_ciphers(void *ignored) -{ - (void)ignored; - -#ifdef HAVE_SSL_GET_CLIENT_CIPHERS - tt_skip(); - done: - (void)1; -#else - int ret; - SSL_CTX *ctx; - SSL *ssl; - SSL_SESSION *sess; - STACK_OF(SSL_CIPHER) *ciphers; - - library_init(); - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - sess = SSL_SESSION_new(); - - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, -1); - - ssl->session = sess; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 0); - - ciphers = sk_SSL_CIPHER_new_null(); - SSL_CIPHER *one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - tt_assert(one); - one->id = 0x00ff; - sk_SSL_CIPHER_push(ciphers, one); - sess->ciphers = ciphers; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 1); - done: - SSL_free(ssl); - SSL_CTX_free(ctx); -#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ -} - #ifndef OPENSSL_OPAQUE static int fixed_ssl_pending_result = 0; @@ -792,76 +749,6 @@ test_tortls_get_buffer_sizes(void *ignored) #endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE -typedef struct cert_pkey_st_local -{ - X509 *x509; - EVP_PKEY *privatekey; - const EVP_MD *digest; -} CERT_PKEY_local; - -typedef struct sess_cert_st_local -{ - STACK_OF(X509) *cert_chain; - int peer_cert_type; - CERT_PKEY_local *peer_key; - CERT_PKEY_local peer_pkeys[8]; - int references; -} SESS_CERT_local; - -static void -test_tortls_try_to_extract_certs_from_tls(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - X509 *cert = NULL, *id_cert = NULL, *c1 = NULL, *c2 = NULL; - SESS_CERT_local *sess = NULL; - - c1 = read_cert_from(validCertString); - c2 = read_cert_from(caCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - sess = tor_malloc_zero(sizeof(SESS_CERT_local)); - tls->ssl->session->sess_cert = (void *)sess; - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(!cert); - tt_assert(!id_cert); - - tls->ssl->session->peer = c1; - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sess->cert_chain = sk_X509_new_null(); - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sk_X509_push(sess->cert_chain, c1); - sk_X509_push(sess->cert_chain, c2); - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(id_cert); - X509_free(cert); /* decrease refcnt */ - X509_free(id_cert); /* decrease refcnt */ - - done: - sk_X509_free(sess->cert_chain); - tor_free(sess); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(c1); - X509_free(c2); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE static void test_tortls_get_peer_cert(void *ignored) { @@ -2105,10 +1992,8 @@ struct testcase_t tortls_openssl_tests[] = { INTRUSIVE_TEST_CASE(cert_get_key, 0), INTRUSIVE_TEST_CASE(get_ciphersuite_name, 0), INTRUSIVE_TEST_CASE(classify_client_ciphers, 0), - LOCAL_TEST_CASE(client_is_using_v2_ciphers, 0), INTRUSIVE_TEST_CASE(get_pending_bytes, 0), INTRUSIVE_TEST_CASE(get_buffer_sizes, 0), - INTRUSIVE_TEST_CASE(try_to_extract_certs_from_tls, 0), INTRUSIVE_TEST_CASE(get_peer_cert, 0), INTRUSIVE_TEST_CASE(peer_has_cert, 0), INTRUSIVE_TEST_CASE(finish_handshake, 0),