-
Notifications
You must be signed in to change notification settings - Fork 283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add quic-noise spec. #351
Add quic-noise spec. #351
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This document doesn’t specify how Noise would be used with QUIC. RFC 9000 defines a pretty tight coupling between TLS and QUIC, that defines how keys derived during the TLS handshake are used to encrypt (and header-protect) QUIC packets. Something along those lines would be needed if we wanted to use Noise with QUIC.
It is specified in the section handshake session. It explains how 0rtt, 1rtt and nextrtt keys are derived |
So the cipher is described here:
We can discuss the choice of cipher, and I can link to previous discussions on the topic. No header protection is used, header protection is considered controversial and it's utility questionable. (I can dig up a paper analyzing quic's security and making this claim). I guess I should mention that in the spec. Besides ossification is not something I'm concerned about for quic-noise. If anything my concern would be that it works at all. |
So regarding cipher choice:
EDIT: if chacha6 is broken in 10y we can still upgrade to chacha12 by incrementing the version. |
These are a few points off the top of my head (without even looking into the QUIC RFCs), that one would need to be address in a document that could rightfully claim to be a specification of Noise+QUIC. I'm sure that if I started re-reading the RFCs, I'd find a lot more problems. Basically, what one would have to do is produce a document along the lines of RFC 9001. Choise of IK handshakeAs you point out, it's required to know your peer's public key to use this handshake pattern. This might be fine, but I'd like to point out that in libp2p you don't always (though most of the time you do) know the peer's identity before connecting to its multiaddr. To my knowledge, rust-libp2p currently already implements this. Using IK means that it's not possible to use Noise+QUIC in that case. Mapping to packet typesQUIC defines a couple of different packet types: Initial, Retry, Handshake, 0-RTT and 1-RTT packets (and Version Negotiation). It's not clear how the IK handshake maps onto these packet types. For one, it seems like Retry won't be possible any more (I'm guessing, since there's nothing in the spec about it). Then it's not clear how / if one would still use Initial packets, or start the handshake using only Handshake packets. Choice of key derivationI have to admit, I'm not very familiar with how "normal" Noise derives its keys, but it seems like you're using a special key derivation here based on xoodyak. Not being a cryptographer, I have no idea if this makes sense or if it doesn't. Choice of cipher suite
This is a significant deviation from TLS 1.3, which uses chacha20poly1305. Why is that one good enough for TLS 1.3 and QUIC, but not good enough for Noise+QUIC? Anyway, switching to a different cipher suite would require a comprehensive security analysis, especially with regards to header protection (see separate section below) and key updates (see separate section below). Header protection
I would be strongly opposed to removing this feature from QUIC. Framing of handshake messagesI assume you intend to use CRYPTO frames, but the spec doesn’t say anything about this. Also, due to the different packet types, you effectively have 3 different CRYPTO byte streams, so it needs to be defined how they’re used and which message goes where. You’ll also need to take special care about the boundaries, as RFC 9000 does. Application Protocol NegotiationQUIC requires the use of ALPN to negotiate the application protocol and avoid protocol confusion attacks. It looks like this was removed entirely. This might be an acceptable choice for Noise+QUIC/libp2p variant, but probably not for a general purpose Noise+QUIC protocol. Transport ParametersQUIC uses TLS extensions to send the QUIC transport parameters. The Noise variant will need to send transport parameters some other way, but the spec doesn’t say anything about this either. Discarding of keys used during the handshakeWhen are keys used during the handshake discarded? I can't find anything about this topic in the spec. Is this completely analogous to how TLS does this? Note that this can have significant implication on loss recovery during the handshake, and that in QUIC we had to introduce a HANDSHAKE_DONE frame pretty late in the process just to prevent a deadlock associated with this. It would be crucial to translate what concepts like Handshake Confirmed means in the context of Noise+QUIC. Key UpdatesHow do key updates work? The spec also remains silent about this topic. 0-RTTPeers are required to remember certain transport parameters from the original connection. In TLS, a server can do so statelessly by encoding them into the session ticket. Losing that capability would severely limit a server’s ability to offer 0-RTT. Unfortunately, the spec doesn’t even mention 0-RTT, so I have no idea how this is intended to work. |
Now this became a lot longer than I initially planned. In fact, my list of things missing from the spec is now more than 3x longer than the spec itself. Given that, I don't think it makes sense to resolve these deficiencies using the GitHub PR review process, which is why I'm going to close this PR now. |
Well, I assume you're not really interested on a response to those points. But thank's for closing the PR so quickly, saves me wasting my time. While I disagree with you I honestly appreciate that very much. |
Yes that is correct. I'm aware of that and this choice was made to support 0-rtt. This was a requested feature here [0].
The retry mechanism is the same as for tls. I saw no need to modify it. In the handshake session the Initial, Handshake crypto frames are specified and how the keys for the packets are derived. There is nothing special about the 0-rtt and 1-rtt packets other than they're encrypted with the 0-rtt and 1-rtt keys.
There were a few issues in mapping noise directly to quic. One of them is that snow provides no api for adding associated data to a message which itself would not be that hard to add [1]. Another one is that a quic packet may have multiple frames. To let noise do it's thing you'd need to add the other frames as a payload to the (encrypted) crypto frame. Safely extracting keys from the noise state that could be used for packet protection is indeed something that would require some security analysis beyond what I can do. What I can do is pick something and use it how it was intended to be used. Since xoodyak is being used the way it was designed to I'm pretty confident that this is fine.
we can add more rounds if that makes people more comfortable. I'm not really loosing any sleep because of it. We can also make the number of rounds to be configurable.
also not loosing much sleep over this one. but we could easily reuse the tls mechanism and specify a key in the spec.
not entirely sure what you mean here, but I'm sure it can be clarified. I sometimes implement specs I don't usually write any.
good point. yes some alpn mechanism could/should be added. opened an issue for this [3]
yes, the transport parameters are added to the crypto frame and || means concatenation. also needs to be clarified.
Also nothing special was done here. There was one issue with the state machine not working due to assumptions about tls. [2]
you can continue squeezing keys from the handshake state. quinn takes care of this, would need to look into the exact conditions when this gets called, but the code is the same as for tls.
quinn somehow takes care of this. I'd have to investigate it more closely. I think having conservative defaults should work. |
What makes you assume this? |
This didn't sound like, I think there is room for improvement, let's try to make it better. The first comment was hard to guess at what the problem was. The second one was more constructive, so I could actually understand the issues. Then the follow up was let's close it because it is unsalvageable which gave me the impression that there was more interest in finding reasons to close it than finding ways to improve it. |
The way I read it was, “GitHub issues aren’t a good place for this kind of discussion; let’s discuss this elsewhere.” |
I guess if you squint your eyes you could arrive at that conclusion, and I'm not uninclined to believe it. However to be able to interpret it the way, a show of good will would have been to suggest an alternative place to discuss it. |
However constructive criticism is only constructive if it is intended that way. So at least allowing for a rebuttal before closing the PR shows that you are actually interested in discussing those points. |
For the record, I have to say that I also find the dismissal rude and condescending. |
A dismissal would be closing it without considering the contents of the PR, marten left very detailed consideration of the contents of the PR, then requested that we not use a pull request to have this discussion. Closing the PR immediately does track as a sensical next course of action, though I would have personally waited for @dvc94ch to close it himself (@marten-seemann, feedback for the future).
This is another bad-faith argument, marten commented in your other issue thread ten minutes later, providing a clear place to continue the conversation. |
On second reading your interpretation of events does seem plausible |
It was not clear to me how to respond to those points. If you get a list of "deficiencies" and then move the conversation somewhere else, that doesn't make it easy to address those points or request for clarification. Also there is the concept of home advantage when engaging in a debate or in sports. So pointing out deficiencies and then moving the discussion to a different avenue is similar to the home team deciding to play the second half time in a different court. We can argue to what degree the other team was notified of this change in avenue, it wasn't obvious to me that he expected me to reply in the issue. |
Closes #315
Related-to libp2p/rust-libp2p#2144