On Mon, Jan 31, 2011 at 09:50:06PM -0500, Nick Mathewson wrote:
1) We should make it easier to use self-signed certs, or maybe even existing HTTPS certificates, for the server side handshake, since most non-Tor SSL handshakes use either self-signed certificates or
or... CA-signed certificates?
2) We should make it harder to probe for a Tor server. Right now, you can just do a handshake with a server, renegotiate, then see if it gives you a VERSIONS cell. That's no good.
Does this proposal address this goal in any way? I don't see why it's on the list.
3) We should allow other changes in our use of TLS and in our certificates so as to resist fingerprinting based on how our certificates look.
Or this goal. Or do we simply mean here that proposal 176's results should not prevent results from other proposals like 179?
And the cell-based part of the V3 handshake, in summary, is:
C<->S: TLS handshake where S sends a "v3 certificate" In TLS: C->S: VERSIONS cell S->C: VERSIONS cell, CERT cell, AUTH_CHALLENGE cell, NETINFO cell C->S: Optionally: CERT cell, AUTHENTICATE cell
Would probably be clearer to append an explicit line here:
C->S: NETINFO cell
The v3 requirements are easy to meet: any certificate designed to resist fingerprinting will likely be self-signed, or if it's signed by a CA, then the issuer will surely have more DN fields set. Certificates that aren't trying to resist fingerprinting can trivially become v3 by using a CN that doesn't end with .net, or using a 1024-bit key.
I assume you mean "or using a key longer than 1024 bits."
If the client implements this proposal, however, and the server has shown it can understand the V3+ handshake protocol, the
This is the first point where you use "V3+" where you had otherwise used "V3". Should the + just be implicit, or do you mean to imply something different when you say V3+ vs V3? I don't see how we can predict that a given behavior could imply V4 without knowing what V4 will be.
An AUTH_CHALLENGE cell is a variable-length cell with the following fields: Challenge [32 octets]
On IRC you suggested that the AUTH_CHALLENGE cell might want to list the authtypes it knows how to parse. Thus if we bump the AuthType version, we may not need to bump the whole link version.
3.4. Authenticating via Tor cells: Client authentication
A client does not need to authenticate to the server. If it does not wish to, it responds to the server's valid CERT cell by sending NETINFO cell: once it has gotten a valid NETINFO cell back, the client should consider the connection open, and the server should consider the connection as opened by an unauthenticated client.
The word 'back' is misleading here, since it implies that the server waits to send its netinfo cell until it sees one from the client.
CID: A SHA256 hash of the client's RSA1024 identity key [32 octets] SID: A SHA256 hash of the server's RSA1024 identity key [32 octets] SLOG: A SHA256 hash of all bytes sent from the server to the client as part of the negotiation up to and including the AUTH_CHALLENGE cell; that is, the VERSIONS cell, the CERT cell, and the AUTH_CHALLENGE cell. [32 octets] CLOG: A SHA256 hash of all byte sent from the client to the server as part of the negotiation so far; that is, the VERSIONS cell and the CERT cell. [32 octets] SCERT: A SHA256 hash of the server's TLS link certificate. [32 octets] TLSSECRETS: Either 32 zero octets, or a SHA256 HMAC, using the TLS master secret as the secret key, of the following: - client_random, as sent in the TLS Client Hello - server_random, as sent in the TLS Server Hello - the NUL terminated ASCII string: "Tor V3 handshake TLS cross-certification" [32 octets] TIME: The time of day in seconds since the POSIX epoch. [8 octets] NONCE: A 16 byte value, randomly chosen by the client [16 octets]
In the server section you specify that the randomness needs to be strong. Does the omission of that specification for the client mean it doesn't need to be? :)
(I'd hate for somebody to misinterpret 'nonce' as 'value that was not previously used', and implement it as a counter, which would do perfectly fine for the protocol but also reveal how many authenticate cells we've sent since the last time you saw one.)
SIG: A signature of a SHA256 hash of all the previous fields using the client's "Authenticate" key as presented. (As always in Tor, we use OAEP-MGF1 padding; see tor-spec.txt section 0.3.) [variable length]
To check the AUTHENTICATE cell, a server checks that all fields containing a hash contain the correct value, then verifies the signature. The server MUST ignore any extra bytes after the SHA256 hash.
You mean extra bytes after the signature?
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, AUTH_CHALLENGE, and AUTHENTICATE. I suggest that in link protocol 3 and higher, we reserve a separate range of commands for variable-length cells.
Sounds good to me.
Security argument
These aren't crypto proofs, since I don't write those. They are meant be reasonably convincing.
They look plausible to me.
- Open questions:
- 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.
Would this be much of a win anyway? Seems like more code for not much of a win.
- With which TLS libraries is it feasible to yoink client_random, server_random, and the master secret? If the answer is "All free C TLS libraries", great. If the answer is "OpenSSL only", not so great.
Good question.
- Should we do anything to check the timestamp in the AUTHENTICATE cell?
Does having the timestamp give us anything that having the nonce doesn't already provide?
I pondered for a while that it might actually be bad to have the timestamp there, since its offset from 'real' time is a cookie that lets us track the user. But there are plenty of other ways that we can learn the client's time, like the NETINFO cell.
- 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.
Given that corporations like Bluecoat sell censorship devices that censor our V2 handshake -- and we've seen them deployed in Syria -- but we know of no places that censor our V1 handshake, it would not be crazy to declare that V3-supporting clients all prefer V1 to V2.
That said, bridges are a good example of a case where we don't know the server version, and also a prime use case here.
One hack would be to change Tor versions that don't support V3 (like 0.2.2.x) so they don't support V2.
*That* said, I think we shouldn't waste too much time on this topic. There aren't any Tors that can't renegotiate now (if we ignore Tor clients in Syria), so if we are forced to make some in the future before V3 is deployed, we could just make those Tors only support V1.
- What should servers that don't have TLS renegotiation do? For now, I think they should just stick with V1. Eventually we can deprecate the V2 handshake as we did with the V1 handshake. When that happens, servers can be V3-only.
Who are these servers you're thinking of?
--Roger
On Tue, Sep 20, 2011 at 2:13 PM, Roger Dingledine arma@mit.edu wrote:
Hi! I'm going to snip every point where I agree with you, and just patch the proposal accordingly.
On Mon, Jan 31, 2011 at 09:50:06PM -0500, Nick Mathewson wrote:
[...]
2) We should make it harder to probe for a Tor server. Right now, you can just do a handshake with a server, renegotiate, then see if it gives you a VERSIONS cell. That's no good.
Does this proposal address this goal in any way? I don't see why it's on the list.
Hm. I think we had hoped to solve that in an earlier version of the proposal, but decided that we probably couldn't do so in any really reasonable way. Adam Langley suggested that we could add a new 'be-a-tor' cell with a hash of the server's identity key that the client has to send after the TLS handshake but before any cells, but that would require that the client know the server's identity to connect to it, which would break some bridge users.
I'll take this goal out, since we don't have a solution. But should we try to get one? It seems like it will be really annoying to add later.
[...]
An AUTH_CHALLENGE cell is a variable-length cell with the following fields: Challenge [32 octets]
On IRC you suggested that the AUTH_CHALLENGE cell might want to list the authtypes it knows how to parse. Thus if we bump the AuthType version, we may not need to bump the whole link version.
Agreed; I'll add such a list.
[...]
TIME: The time of day in seconds since the POSIX epoch. [8 octets] NONCE: A 16 byte value, randomly chosen by the client [16 octets]
In the server section you specify that the randomness needs to be strong. Does the omission of that specification for the client mean it doesn't need to be? :)
Hah.
(I'd hate for somebody to misinterpret 'nonce' as 'value that was not previously used', and implement it as a counter, which would do perfectly fine for the protocol but also reveal how many authenticate cells we've sent since the last time you saw one.)
We already have a note in tor-spec.txt that tries to say that everything that we say is "random" has to really be random. I'm strengthening it to:
All "random" values MUST be generated with a cryptographically strong pseudorandom number generator seeded from a strong entropy source, unless otherwise noted.
Additionally, I'm renaming it the field to RAND.
SIG: A signature of a SHA256 hash of all the previous fields using the client's "Authenticate" key as presented. (As always in Tor, we use OAEP-MGF1 padding; see tor-spec.txt section 0.3.) [variable length]
To check the AUTHENTICATE cell, a server checks that all fields containing a hash contain the correct value, then verifies the signature. The server MUST ignore any extra bytes after the SHA256 hash.
You mean extra bytes after the signature?
No. I mean that if you check the signature and you do the signature check (RSA public-key decrypt, then check and remove padding), you get the thing that was signed. The thing that was signed must start with a SHA256 hash, but it is allowed to contain other stuff (so that we can, say, add a SHA3 hash seamlessly later on).
- Open questions:
- 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.
Would this be much of a win anyway? Seems like more code for not much of a win.
It saves a couple of public-key operations every time we do a connect. I think these will in practice be swamped by DH costs.
- With which TLS libraries is it feasible to yoink client_random, server_random, and the master secret? If the answer is "All free C TLS libraries", great. If the answer is "OpenSSL only", not so great.
Good question.
I continue to believe that the answer is "all free C TLS libraries, and Java libraries where you can hack them or ".
If RFC5705 is ever widely implemented, we can use that instead for TLS 1.2 and later, so we don't need to go mucking about in the crypto library's guts. I am currently not so happy about using the RFC5705 construction with TLS 1.1 and earlier, though, because of the wackypants SSL PRF. ("Split your key in two, and use one half of it to key a SHA1 PRF and the other half to key a MD5 PRF!")
I think on reflection that we should change the TLSSECRETS field from optional to required in all AUTHENTICATE cells. Only relays need to send it, after all.
- Should we do anything to check the timestamp in the AUTHENTICATE cell?
Does having the timestamp give us anything that having the nonce doesn't already provide?
I added it because Adam told me I should. I don't know for sure. Maybe it helps defend against bad nonces?
I pondered for a while that it might actually be bad to have the timestamp there, since its offset from 'real' time is a cookie that lets us track the user. But there are plenty of other ways that we can learn the client's time, like the NETINFO cell.
Right, also keep in mind that "client" here means "connection initiator." Regular clients shouldn't send AUTHENTICATE cells at all.
[...]
- What should servers that don't have TLS renegotiation do? For now, I think they should just stick with V1. Eventually we can deprecate the V2 handshake as we did with the V1 handshake. When that happens, servers can be V3-only.
Who are these servers you're thinking of?
AFAIK there are none. I have no idea what January-Nick was thinking.
On Wed, Sep 21, 2011 at 1:58 PM, Nick Mathewson nickm@alum.mit.edu wrote:
I'm thinking of a few more tweaks to this proposal, based on implementation.
Here's one:
I think on reflection that we should change the TLSSECRETS field from optional to required in all AUTHENTICATE cells. Only relays need to send it, after all.
Doing this makes us more secure, at the expense of making it a little harder for now to write a relay using an inflexible TLS library that you can't change.
Another change: Previously I had said that every server (including relays and bridges) should send an AUTH_CHALLENGE cell to say "I'd like authentication". In fact, that should only apply to relays: There is never a point in authenticating to a bridge, right? Similarly, bridges should only authenticate to their clients, not to the relays that they're extending to.
So here, I think, are the right behaviors for the possible interactions in the v3 protocol now: Client connects to bridge: C->B: VERSIONS B->C: VERSIONS, CERT, NETINFO C->B: NETINFO Client or bridge connects to relay: C->R: VERSIONS R->C: VERSIONS, CERT, AUTH_CHALLENGE, NETINFO C->R: NETINFO Relay connects to relay: R1->R2: VERSIONS R2->R1: VERSIONS, CERT, AUTH_CHALLENGE, NETINFO R1->R2: CERT, AUTHENTICATE, NETINFO
From a first look at 176 it looks good. Some comments and suggestions inline:
Terminological note: I use "client" below to mean the Tor instance (a client or a bridge or a relay) that initiates a TLS connection, and "server" to mean the Tor instance (a bridge or a relay) that accepts it.
There are still some initiator/responder below, which I've pointed out.
* Allow responder authentication or bidirectional authentication.
responder -> server
In other words, V2-supporting initiator behavior currently looks like this:
initiator -> client
And V2-supporting responder behavior now looks like this:
responder -> server
And the cell-based part of the V3 handshake, in summary, is:
C<->S: TLS handshake where S sends a "v3 certificate" In TLS: C->S: VERSIONS cell
I would be concerned that at some later point in the arms race, someone will block connections where the first application record doesn't look like a HTTP request. I'd therefore suggest that we permit variable length padding cells at all points, especially after the first VERSIONS cell. Then the client could pad out the first application record to a convincing length before flushing.
To check the AUTHENTICATE cell, a server checks that all fields containing a hash contain the correct value, then verifies the signature. The server MUST ignore any extra bytes in the signed data after the SHA256 hash.
I'd suggest expanding on what "correct value" means for each of the fields. Some might be obvious but others are not (e.g. TIME, which I see later on is not currently checked).
If we allow padding cells then I think we should probably include them in SLOG and CLOG.
[If we want to avoid the empty application record trick to fix the CBC vulnerability in TLS 1.0 then we could use padding cells with random data before every application record.]
A server SHOULD NOT send any sequence of cells when starting a v3 negotiation other than "VERSIONS, CERT, AUTH_CHALLENGE, NETINFO". A client SHOULD drop a CERT, AUTH_CHALLENGE, or NETINFO cell that appears at any other time or out of sequence.
A client should not begin a v3 negotiation with any sequence other than "VERSIONS, NETINFO" or "VERSIONS, CERT, AUTHENTICATE, NETINFO". A server SHOULD drop a CERT, AUTH_CHALLENGE, or NETINFO cell that appears at any other time or out of sequence.
Padding cells should be permitted.
If the client was not able to include a non-zero TLSSECRET component, or the server can't check it, the answer is a little trickier. The server knows that it is not getting a replayed AUTHENTICATE cell, since the cell authenticates (among other stuff) the server's AUTH_CHALLENGE cell, which it has never used before. The server knows that it is not getting a MITM'd AUTHENTICATE cell, since the cell includes a hash of the server's link certificate, which nobody else should have been able to use in a successful TLS negotiation.
Is a zero TLSSECRET permitted anymore?
A signature of the TLSSECRET element on its own should be sufficient to prevent the attacks we care about, but because we don't necessarily have access to the TLS master secret when using a non-C TLS library, we can't depend on it. I added it anyway so that, if there is some problem with the rest of the protocol, clients and servers that _are_ written in C (that is, the official Tor implementation) can still be secure.
Again, it looks like TLSSECRET is now mandatory.
Steven.
On Tue, Oct 4, 2011 at 1:05 PM, Steven Murdoch Steven.Murdoch@cl.cam.ac.uk wrote:
From a first look at 176 it looks good. Some comments and suggestions inline:
Thanks, Steven!
Terminological note: I use "client" below to mean the Tor instance (a client or a bridge or a relay) that initiates a TLS connection, and "server" to mean the Tor instance (a bridge or a relay) that accepts it.
There are still some initiator/responder below, which I've pointed out.
I've changed the above paragraph to make "client" and "initiator" are synonyms, as are "server" and "Responder".
On padding: agreed; I've added references to padding in the appropriate places, and referenced proposal 184.
To check the AUTHENTICATE cell, a server checks that all fields containing a hash contain the correct value, then verifies the signature. The server MUST ignore any extra bytes in the signed data after the SHA256 hash.
I'd suggest expanding on what "correct value" means for each of the fields. Some might be obvious but others are not (e.g. TIME, which I see later on is not currently checked).
I've changed that statement to say that all fields from TYPE through TLSSECRETS should be checked to make sure their "unique correct value as specified above."
If we allow padding cells then I think we should probably include them in SLOG and CLOG.
Agreed.
If the client was not able to include a non-zero TLSSECRET component, or the server can't check it, the answer is a little trickier. The server knows that it is not getting a replayed AUTHENTICATE cell, since the cell authenticates (among other stuff) the server's AUTH_CHALLENGE cell, which it has never used before. The server knows that it is not getting a MITM'd AUTHENTICATE cell, since the cell includes a hash of the server's link certificate, which nobody else should have been able to use in a successful TLS negotiation.
Is a zero TLSSECRET permitted anymore?
Nope; I've reworded this paragraph.
A signature of the TLSSECRET element on its own should be sufficient to prevent the attacks we care about, but because we don't necessarily have access to the TLS master secret when using a non-C TLS library, we can't depend on it. I added it anyway so that, if there is some problem with the rest of the protocol, clients and servers that _are_ written in C (that is, the official Tor implementation) can still be secure.
Again, it looks like TLSSECRET is now mandatory.
Also reworded this one.
Thanks,