diff options
Diffstat (limited to 'doc/spec')
-rw-r--r-- | doc/spec/proposals/000-index.txt | 6 | ||||
-rw-r--r-- | doc/spec/proposals/169-eliminating-renegotiation.txt | 401 |
2 files changed, 405 insertions, 2 deletions
diff --git a/doc/spec/proposals/000-index.txt b/doc/spec/proposals/000-index.txt index 93dc0299dc..aa554d6a54 100644 --- a/doc/spec/proposals/000-index.txt +++ b/doc/spec/proposals/000-index.txt @@ -71,7 +71,7 @@ Proposals by number: 148 Stream end reasons from the client side should be uniform [CLOSED] 149 Using data from NETINFO cells [OPEN] 150 Exclude Exit Nodes from a circuit [CLOSED] -151 Improving Tor Path Selection [DRAFT] +151 Improving Tor Path Selection [FINISHED] 152 Optionally allow exit from single-hop circuits [CLOSED] 153 Automatic software update protocol [SUPERSEDED] 154 Automatic Software Update Protocol [SUPERSEDED] @@ -89,6 +89,7 @@ Proposals by number: 166 Including Network Statistics in Extra-Info Documents [ACCEPTED] 167 Vote on network parameters in consensus [CLOSED] 168 Reduce default circuit window [OPEN] +169 Eliminate TLS renegotiation for the Tor connection handshake [DRAFT] Proposals by status: @@ -99,7 +100,7 @@ Proposals by status: 133 Incorporate Unreachable ORs into the Tor Network 141 Download server descriptors on demand 144 Increase the diversity of circuits by detecting nodes belonging the same provider - 151 Improving Tor Path Selection + 169 Eliminate TLS renegotiation for the Tor connection handshake [for 0.2.2] NEEDS-REVISION: 131 Help users to verify they are using Tor OPEN: @@ -132,6 +133,7 @@ Proposals by status: 099 Miscellaneous proposals FINISHED: 121 Hidden Service Authentication [in 0.2.1.x] + 151 Improving Tor Path Selection 155 Four Improvements of Hidden Service Performance [in 0.2.1.x] CLOSED: 101 Voting on the Tor Directory System [in 0.2.0.x] diff --git a/doc/spec/proposals/169-eliminating-renegotiation.txt b/doc/spec/proposals/169-eliminating-renegotiation.txt new file mode 100644 index 0000000000..f07ca1e963 --- /dev/null +++ b/doc/spec/proposals/169-eliminating-renegotiation.txt @@ -0,0 +1,401 @@ +Filename: 169-eliminating-renegotiation.txt +Title: Eliminate TLS renegotiation for the Tor connection handshake +Author: Nick Mathewson +Created: 27-Jan-2010 +Status: Draft +Target: 0.2.2 + +1. Overview + + I propose a backward-compatible change to the Tor connection + establishment protocol to avoid the use of TLS renegotiation. + + Rather than doing a TLS renegotiation to exchange certificates + and authenticate the original handshake, this proposal takes an + approach similar to Steven Murdoch's proposal 124, and uses Tor + cells to finish authenticating the parties' identities once the + initial TLS handshake is finished. + + Terminological note: I use "client" below to mean the Tor + instance (a client or a relay) that initiates a TLS connection, + and "server" to mean the Tor instance (a relay) that accepts it. + +2. Motivation and history + + In the original Tor TLS connection handshake protocol ("V1", or + "two-cert"), parties that wanted to authenticate provided a + two-cert chain of X.509 certificates during the handshake setup + phase. Every party that wanted to authenticate sent these + certificates. + + In the current Tor TLS connection handshake protocol ("V2", or + "renegotiating"), the parties begin with a single certificate + sent from the server (responder) to the client (initiator), and + then renegotiated to a two-certs-from-each-authenticating party. + We made this change to make Tor's handshake look like a browser + speaking SSL to a webserver. (See proposal 130, and + tor-spec.txt.) To tell whether to use the V1 or V2 handshake, + servers look at the list of ciphers sent by the client. (This is + ugly, but there's not much else in the ClientHello that they can + look at.) If the list contains any cipher not used by the V1 + protocol, the server sends back a single cert and expects a + renegotiation. If the client gets back a single cert, then it + withholds its own certificates until the TLS renegotiation phase. + + In other words, initiator behavior now looks like this: + + - Begin TLS negotiation with V2 cipher list; wait for + certificate(s). + - If we get a certificate chain: + - Then we are using the V1 handshake. Send our own + certificate chain as part of this initial TLS handshake + if we want to authenticate; otherwise, send no + certificates. When the handshake completes, check + certificates. We are now mutually authenticated. + + Otherwise, if we get just a single certificate: + - Then we are using the V2 handshake. Do not send any + certificates during this handshake. + - When the handshake is done, immediately start a TLS + renegotiation. During the renegotiation, expect + a certificate chain from the server; send a certificate + chain of our own if we want to authenticate ourselves. + - After the renegotiation, check the certificates. Then + send (and expect) a VERSIONS cell from the other side to + establish the link protocol version. + + And V2 responder behavior now looks like this: + + - When we get a TLS ClientHello request, look at the cipher + list. + - If the cipher list contains only the V1 ciphersuites: + - Then we're doing a V1 handshake. Send a certificate + chain. Expect a possible client certificate chain in + response. + Otherwise, if we get other ciphersuites: + - We're using the V2 handshake. Send back a single + certificate and let the handshake complete. + - Do not accept any data until the client has renegotiated. + - When the client is renegotiating, send a certificate + chain, and expect (possibly multiple certificates in + reply). + - Check the certificates when the renegotiation is done. + Then exchange VERSIONS cells. + + Late in 2009, researchers found a flaw in most application's use + of TLS renegotiation: Although TLS renegotiation does not + reauthenticate any information exchanged before the renegotiation + takes place, many applications were treating it as though it did, + and assuming that data sent _before_ the renegotiation was + authenticated with the credentials negotiated _during_ the + renegotiation. This problem was exacerbated by the fact that + most TLS libraries don't actually give you an obvious good way to + tell where the renegotiation occurred relative to the datastream. + Tor wasn't directly affected by this vulnerability, but its + aftermath hurts us in a few ways: + + 1) OpenSSL has disabled renegotiation by default, and created + a "yes we know what we're doing" option we need to set to + turn it back on. (Two options, actually: one for openssl + 0.9.8l and one for 0.9.8m and later.) + + 2) Some vendors have removed all renegotiation support from + their versions of OpenSSL entirely, forcing us to tell + users to either replace their versions of OpenSSL or to + link Tor against a hand-built one. + + 3) Because of 1 and 2, I'd expect TLS renegotiation to become + rarer and rarer in the wild, making our own use stand out + more. + +3. Design + +3.1. The view in the large + + Taking a cue from Steven Murdoch's proposal 124, I propose that + we move the work currently done by the TLS renegotiation step + (that is, authenticating the parties to one another) and do it + with Tor cells instead of with TLS. + + Using _yet another_ variant response from the responder (server), + we allow the client to learn that doesn't need to rehandshake, + and it can use a cell-based authentication system. Once the + TLS handshake is done, the client and server exchange VERSIONS + cells to determine what link protocol version (including + handshake version). If they're using the handshake version + specified here, the client and server arrive at link protocol + version 3 (or higher), and use cells to exchange further + authentication information. + +3.2. New TLS handshake variant + + We already used the list of ciphers from the clienthello to + indicate whether the client can speak the V2 ("renegotiating") + handshake or later, so we can't encode more information there. + + We can, however, change the DN in the certificate passed by the + server to back the client. Currently, all V2 certificates are + generated with CN values ending with ".net". I propose that we + have the ".net" commonName ending reserved to indicate the V2 + protocol, and use commonName values ending with ".com" to + indicate the V3 ("minimal") handshake described herein. + + Now, once the initial TLS handshake is done, the client can look + at the server's certificate(s). If there is a certificate chain, + the handshake is V1. If there is a single certificate whose + subject commonName ends in ".net", the handshake is V2 and the + client should try to renegotiate as it would currently. + Otherwise, the client should assume that the handshake is V3+. + [Servers should _only_ send ".com" addesses, to allow room for + more signaling in the future.] + +3.3. Authenticating inside Tor + + Once the TLS handshake is finished, if the client renegotiates, + then the server should go on as it does currently. + + If the client implements this proposal, however, and the server + has shown it can understand the V3+ handshake protocol, the + client immediately sends a VERSIONS cell to the server + and waits to receive a VERSIONS cell in return. We negotiate + the Tor link protocol version _before_ we proceed with the + negotiation, in case we need to change the authentication + protocol in the future. + + Once either party has seen the VERSIONS cell from the other, it + knows which version they will pick (that is, the highest version + shared by both parties' VERSIONS cells). All Tor instances using + the handshake protocol described in 3.2 MUST support at least + link protocol version 3 as described here. + + On learning the link protocol, the server then sends the client a + CERT cell and a NETINFO cell. If the client wants to + authenticate to the server, it sends a CERT cell, an AUTHENTICATE + cell, and a NETINFO cell, or it may simply send a NETINFO cell if + it does not want to authenticate. + + The CERT cell describes the keys that a Tor instance is claiming + to have. It is a variable-length cell. Its payload format is: + + N: Number of certs in cell [1 octet] + N times: + CLEN [2 octets] + Certificate [CLEN octets] + + Any extra octets at the end of a CERT cell MUST be ignored. + + Each certificate has the form: + + CertType [1 octet] + CertPurpose [1 octet] + PublicKeyLen [2 octets] + PublicKey [PublicKeyLen octets] + NotBefore [4 octets] + NotAfter [4 octets] + SignerID [HASH256_LEN octets] + SignatureLen [2 octets] + Signature [SignatureLen octets] + + where CertType is 1 (meaning "RSA/SHA256") + CertPurpose is 1 (meaning "link certificate") + PublicKey is the DER encoding of the ASN.1 representation + of the RSA key of the subject of this certificate, + NotBefore is a time in HOURS since January 1, 1970, 00:00 + UTC before which this certificate should not be + considered valid. + NotAfter is a time in HOURS since January 1, 1970, 00:00 + UTC after which this certificate should not be + considered valid. + SignerID is the SHA-256 digest of the public key signing + this certificate + and Signature is the signature of the all other fields in + this certificate, using SHA256 as described in proposal + 158. + + While authenticating, a server need send only a self-signed + certificate for its identity key. (Its TLS certificate already + contains its link key signed by its identity key.) A client that + wants to authenticate MUST send two certificates: one containing + a public link key signed by its identity key, and one self-signed + cert for its identity. + + Tor instances MUST ignore any certificate with an unrecognized + CertType or CertPurpose. + + The AUTHENTICATE cell proves to the server that the client with + whom it completed the initial TLS handshake is the one possessing + the link public key in its certificate. It is a variable-length + cell. Its contents are: + + SignatureType [2 octets] + SignatureLen [2 octets] + Signature [SignatureLen octets] + + where SignatureType is 1 (meaning "RSA-SHA256") and Signature is + an RSA-SHA256 signature of the HMAC-SHA256, using the TLS master + secret key as its key, of the following elements: + + - The SignatureType field (0x00 0x01) + - The NUL terminated ASCII string: "Tor certificate verification" + - client_random, as sent in the Client Hello + - server_random, as sent in the Server Hello + + Once the above handshake is complete, the client knows (from the + initial TLS handshake) that it has a secure connection to an + entity that controls a given link public key, and knows (from the + CERT cell) that the link public key is a valid public key for a + given Tor identity. + + If the client authenticates, the server learns from the CERT cell + that a given Tor identity has a given current public link key. + From the AUTHENTICATE cell, it knows that an entity with that + link key knows the master secret for the TLS connection, and + hence must be the party with whom it's talking, if TLS works. + +3.4. Security checks + + If the TLS handshake indicates a V2 or V3+ connection, the server + MUST reject any connection from the client that does not begin + with either a renegotiation attempt or a VERSIONS cell containing + at least link protocol version "3". If the TLS handshake + indicates a V3+ connection, the client MUST reject any connection + where the server sends anything before the client has sent a + VERSIONS cell, and any connection where the VERSIONS cell does + not contain at least link protocol version "3". + + If link protocol version 3 is chosen: + + Clients and servers MUST check that all digests and signatures + on the certificates in CERT cells they are given are as + described above. + + After the VERSIONS cell, clients and servers MUST close the + connection if anything besides a CERT or AUTH cell is sent + before the + + CERT or AUTHENTICATE cells anywhere after the first NETINFO + cell must be rejected. + + ... [write more here. What else?] ... + +3.5. Summary + + We now revisit the protocol outlines from section 2 to incorporate + our changes. New or modified steps are marked with a *. + + The new initiator behavior now looks like this: + + - Begin TLS negotiation with V2 cipher list; wait for + certificate(s). + - If we get a certificate chain: + - Then we are using the V1 handshake. Send our own + certificate chain as part of this initial TLS handshake + if we want to authenticate; otherwise, send no + certificates. When the handshake completes, check + certificates. We are now mutually authenticated. + Otherwise, if we get just a single certificate: + - Then we are using the V2 or the V3+ handshake. Do not + send any certificates during this handshake. + * When the handshake is done, look at the server's + certificate's subject commonName. + * If it ends with ".net", we're doing a V2 handshake: + - Immediately start a TLS renegotiation. During the + renegotiation, expect a certificate chain from the + server; send a certificate chain of our own if we + want to authenticate ourselves. + - After the renegotiation, check the certificates. Then + send (and expect) a VERSIONS cell from the other side + to establish the link protocol version. + * If it ends with anything else, assume a V3 or later + handshake: + * Send a VERSIONS cell, and wait for a VERSIONS cell + from the server. + * If we are authenticating, send CERT and AUTHENTICATE + cells. + * Send a NETINFO cell. Wait for a CERT and a NETINFO + cell from the server. + * If the CERT cell is a good cert signing the public + key in the x.509 certificate we got during the TLS + handshake, we connected to the server with that + identity key. Otherwise close the connection. + * Once the NETINFO cell arrives, continue as before. + + And V3+ responder behavior now looks like this: + + - When we get a TLS ClientHello request, look at the cipher + list. + + - If the cipher list contains only the V1 ciphersuites: + - Then we're doing a V1 handshake. Send a certificate + chain. Expect a possible client certificate chain in + response. + Otherwise, if we get other ciphersuites: + - We're using the V2 handshake. Send back a single + certificate whose subject commonName ends with ".com", + and let the handshake complete. + * If the client does anything besides renegotiate or send a + VERSIONS cell, drop the connection. + - If the client renegotiates immediately, it's a V2 + connection: + - When the client is renegotiating, send a certificate + chain, and expect (possibly multiple certificates in + reply). + - Check the certificates when the renegotiation is done. + Then exchange VERSIONS cells. + * Otherwise we got a VERSIONS cell and it's a V3 handshake. + * Send a VERSIONS cell, a CERT cell, an AUTHENTICATE + cell, and a NETINFO cell. + * Wait for the client to send cells in reply. If the + client sends a CERT and an AUTHENTICATE and a NETINFO, + use them to authenticate the client. If the client + sends a NETINFO, it is unauthenticated. If it sends + anything else before its NETINFO, it's rejected. + +4. Numbers to assign + + We need a version number for this link protocol. I've been + calling it "3". + + We need to reserve command numbers for CERT and AUTH cells. I + suggest that in link protocol 3 and higher, we reserve command + numbers 128..240 for variable-length cells. (241-256 we can hold + for future extensions. + +5. Efficiency + + This protocol add a round-trip step when the client sends a + VERSIONS cell to the server, and waits for the {VERSIONS, CERT, + NETINFO} response in turn. (The server then waits for the + client's {NETINFO} or {CERT, AUTHENTICATE, NETINFO} reply, + but it would have already been waiting for the client's NETINFO, + so that's not an additional wait.) + + This is actually fewer round-trip steps than required before for + TLS renegotiation, so that's a win. + +6. Open questions: + + - Should we use X.509 certificates instead of the certificate-ish + things we describe here? They are more standard, but more ugly. + + - May we cache which certificates we've already verified? It + might leak in timing whether we've connected with a given server + before, and how recently. + + - Is there a better secret than the master secret to use in the + AUTHENTICATE cell? Say, a portable one? Can we get at it for + other libraries besides OpenSSL? + + - Does using the client_random and server_random data in the + AUTHENTICATE message actually help us? How hard is it to pull + them out of the OpenSSL data structure? + + - Can we give some way for clients to signal "I want to use the + V3 protocol if possible, but I can't renegotiate, so don't give + me the V2"? Clients currently have a fair idea of server + versions, so they could potentially do the V3+ handshake with + servers that support it, and fall back to V1 otherwise. + + - What should servers that don't have TLS renegotiation do? For + now, I think they should just get it. Eventually we can + deprecate the V2 handshake as we did with the V1 handshake. |