jiebi/CodeConvo huggingface dataset:
a third party will be able to extract your server mapping, but in practice it will be hard for an attacker to obtain this position on purpose. If this is the best outcome, we can stick with 2 config rotation bits. Option 2: Issue them different config rotation codepoints. So an observer can see the SNI and associate it with certain CR bits; if the client later migrates, it will still be able to associate that connection with that SNI. If this is better than Option 1, we should probably add a third config rotation bit. Other (minor) costs of having 3 config rotation bits: length self-encoding can only support 31 byte connection IDs, instead of 63 (obviously this is only relevant for hypothetical future versions of QUIC) each config can have its own set of server IDs. So there is considerably more config state at the LB. As SIDs can be up to 18B, it's 18B x (# of servers) x (# of config rotation codepoints). This memory footprint will roughly double by going from 3 to 7 codepoints. I've talked myself into Option 1 as being a mildly better situation, thus sticking with 2 CR bits.
Update: the ECHO design might allow the LB privileged access to the SNI, so it might be encrypted. However, an attacker could connect to the domains at that IP and obtain the config rotation bits. So option 2 actually circumvents ESNI entirely!
Closing -- I have received no pushback on doing nothing (leaving it at 2 bits), so I'm going to do nothing.
The draft doesn't address the impact of each method of connection ID generation on how servers can use stateless resets. Most of this is likely bound up in decisions stemming from . If you can guess a valid but unused connection ID, then you might be able to induce a stateless reset that could be used to kill an open connection. As the draft only includes methods that include an explicit server identifier, it is possible that as long as valid values cannot be guessed, the effect is minimal and each server instance can have its own configured stateless reset key (or a shared key from which a per-server key is derived using a KDF).
I don't understand the attack here. A given CID will deterministically map to a specific server instance.
So there is no way for another server to receive a packet with that CID and generate a stateless reset. What am I missing? There might be something here with the differing treatment of long-header vs. short-header packets, (and the option for servers to send resets on long headers), but I'll have to think about it more.
As to the last point, nope: even a long header with a DCID that conforms to the server's expectations (i.e. maps to a real server) will get delivered to that server, so I don't think that's an attack.
NAME Should we talk about this issue more, or are you satisfied enough that I can close it?
I don't see any mention of stateless reset in the draft at all. That's probably something worth addressing, even if it is to say what you have already.
The only language I can find in the document that prescribes serialization is in Section 1.2 (please point out if I missed anything): We intend this statement to be prescriptive, i.e., encoding/decoding of messages is as defined in RFC8446. Another valid interpretation might be "we define the fields of each message following the conventions of RFC8446, but leaving encoding/decoding unspecified". I think it would help to refine this statement a bit. WDYTA:
SGTM FWIW (this was our interpretation, and I think it makes sense to clarify)
Yeah, this seems like a fine clarification. I don't think it was under specified before, but more information for those unfamiliar with TLS-style encoding doesn't hurt.
to the extent I'm willing to do so.
Sec 4.1 and 4.1.2 do not explicitly define , , as stream errors. A.4.1 says that is a stream error. It would be nice if they are explicitly defined as stream errors in Sec 4.1 and 4.1.2. Also, it would be nice if each error code is categorized to either a connection error or a stream error in Table 4.
Commenting as an individual. The error code space is shared between connection and streams. The action associated with a stream error or connection error cause QUIC transport frames to be emitted, which can use a code. H3 inherits H2's design philosophy that endpoints can generate a connection error at will. So while there are specific cases that describe "treat X as stream error foo", endpoints are also allowed to "treat X as connection error foo". Constraining the error codes to different uses has a certain appeal. But then what do we say the the receiver of an error code of the wrong type should do? Generate its own error? I think this has come up a couple of times during H3 drafts but I'm satisfied that the flexibility we have today is about the best we can do.
I also think "stream error" and "abort a stream" are unique and consistent terms used through the document. But I'll let Mike spec to that point with his editor hat.
Even though categorization is not reasonable, Sec 4.1, for instance, should say like "the server SHOULD abort its response and treat as a stream error of type H3REQUESTINCOMPLETE".
"Abort" is a defined term in section 2.2. I personally don't see much clarity in the proposal, it threatens to add inconsistency to other places where streams are aborted due to application decisions rather than a protocol error.
My example proposal is to replace "the server SHOULD abort its response with the error code H3REQUESTINCOMPLETE" with "the server SHOULD abort its response and treat as a stream error of type H3REQUESTINCOMPLETE" in Sec 4.1. I don't understand why this would introduce inconsistency.
NAME For that particular instance, I think it is not unreasonable to change the text from "SHOULD abort its response with the error code ..." to "SHOULD abort its response stream with the error code ...", as the latter is the pattern that we use. Though I am not sure if such change is necessary; I tend to agree with NAME that the sentence is already clear; "abort" is a defined word and use of "response" implies a stream.
WRT inconsistency, the editor would need to sweep for all instances of abort and reason about whether they need additional text or not. And there's a risk that someone later on picks up on an inconsistency of usage because they didn't appreciate the nuance. Since adding more detail after an instance of seems duplicative, I would favour not adding any more.
I'm okay with NAME addition of "stream" since abort is defined as a stream operation. I don't think we need to separate out "abort" and "stream error" as separate statements, because abort already describes what needs to be done.
If I was worried too much, no change is necessary. One alternative approach is to add a sentence like "errors in this section are stream errors" in the beginning of Sec 4.
Simplify the TLS SNI challenge by removing the iterations concept, which I believe is not necessary in practice and complicates the protocol needlessly.
Implementing TLS SNI is currently really complicated, yes.
FYI, URL implements protocol according to the contents of this PR - i.e. without iterations.
(so does current Boulder)
I think this will be OK to land once lands. We should consider whether we want to bump the version number in the challenge. Principle would dictate that we should, since this breaks compatibility with what was published in -01. But since I'm not aware of any implementation of "tls-sni-01" as specified in -01 (vs. the off-spec implementation in boulder), I'm inclined to just leave it.
FWIW on the client side of things, xenolf/lego did not implement the iterations for the tls-sni-01 challenge.
URL implements iterations but takes the absence of an "n" parameter to be equivalent to an "n" parameter of 1, which is compatible.
Great, I'm taking this as sufficient evidence that a version bump is not needed :)
URL The example shows in flight 5 Certificate --------> ClientKeyExchange CertificateVerify [ChangeCipherSpec] Finished (cid=100) Does this imply that the flight 5 is send with cid = 100 or only the Finished? I would prefer to be able to send also the other handshake messages of the flight with a cid, that would make it harder to disturb handshakes by spoofed handshake messages.
In DTLS 1.2 only the Finished message is encrypted. In the current design we make use of the CIDs only once encryption is enabled. I should explain that only the Finished message contains a CID here.
See additional explanation in PR : URL
I would enjoy it, if the cid could be extended into the not encrypted handshake messages also. Is there any reason, not to do so? My consideration is to make the handshake "slightly more" protected against spoofing. The current protection in RFC6347 is limited to URL and URL . The first applies only to the CLIENTHELLO ("cookie" protection again spoofed CLIENTHELLOs). The second (MAC and Anti-Replay) is only usable after a successful handshake. If an attacker spoofs other handshake messages, the attacker may block a handshake from being successful (even if the time window for that is very small and so it would be a rather expensive attack). Using a CID would enable a implementation either to handshake even when addresses are changing during the handshake or to protect the handshake slightly more (not supporting address changes but) use the CID to validate the handshake message belonging to this handshake. I would leave the chosen strategy to the implementation, enabling implementations to flexible chose the strategy depending on the current handshake load (means: supporting address changes in handshakes as normal operation, but switch dynamically to the more protective one, if a certain relative number of handshake fails.) My current work in progress: URL contains already this feature as experimental extension. It's easy to be added to a cid implementation.
Section 4.1.2 describes an attack where an attacker injects traffic that cannot be correctly processed due to a MAC failure. The reason why MAC failures in DTLS do not lead to a connection termination (unlike in TLS) is that they are much easier to mount: an attacker only needs to know the source and destination IP and port.
Section 4.2.1 talks about the cookie exchange, which has been added to prevent amplification attacks against third parties. I would argue that these two attacks are very different from what you are trying to tackle. You would like to add resiliency against on-path (?) attacks sending spoofed handshake messages. I cannot see how the CID provides that extra protection. I understand the use case of address changes during the handshake. The question is whether this is actually something real. If the IP address & port changes during the handshake then this is indeed annoying but how often does this happen?
I mentioned 4.1.2 and 4.2.1 just to sum up the current protection mechanisms. The attack, I consider, is a off-path. e.g. using PSK, someone spoofs a CLIENTKEYEXCHANGE with the identity "ghost". Now it's hard for the server to differentiate the wrong from the right CLIENTKEYEXCHANGE with identity "me". With the CID in the handshake, spoofing into the handshake will be much harder. I don't assume, that such attacks will be easy or happen frequently. But assuming something as a "theft detection" for something valuable, it may be used to block the reporting message.
I don't understand why we'd need to enable CID during handshake, and in particular on Finished? Any sane handshake will complete well before any NAT rebinding has a chance to mess with the path (note that in-flight handshake messages refresh the port bindings...). What kind of use case would that address? Is it connection migrations while handshaking? I'm not sure the "increased robustness against spoofing" argument is a very strong one: the handshake is either robust as-is or we are in trouble :-) Also, would that imply reconsidering the security analysis of the handshake? My preference instead would be to send tls12cid records only after the handshake has completed successfully, i.e. on the first application_data.
FMPOV: protects in the long period before the handshake. With the cookie you could not only spoof CLIENTHELLOs an trigger heavy functions. protects in the long period after the handshake. With the MAC filter it's also not possible to spoof messages at that period (or even repeat them).
But in the short period (few seconds) of the handshake itself, I couldn't find a straight forward method, to distinguish between the right inner handshake messages and spoofed ones. Using the CID would offer a similar protection for those inner handshake messages as the cookie for the CLIENTHELLO. I don't assume, that such attack will happen too frequently. But I could assume, if someone has a high interest, such an attack may be used to "deny" a handshake of a certain peer for a certain time period, e.g. "theft detection" for one device may be blocked for a couple of minutes. Only because the CID would offer protection against this "for free", if used during the handshake, I started to try to introduce that.
Let me admit, that the attack in the inner handshake is not likely. Some implementations seems to use the 4.1.2 mechanism even in epoch 0, that may help, but introduces other risks (attack possibilities for the inner handshake). FMPOV, currently you would need too much implementation knowledge to execute such an attack. But, though in my opinion, using the CID within the handshake, offers a protection "for free", I think it's worth to be considered.
Sorry, I'm not sure I understand which kind of extra protection we'd get: when handshaking the CID is spoofable as much as the source address in the UDP packet.
Another argument for not changing the wire image of the record layer during the handshake phase is possible middleboxes interference.
The cookie of 4.2.1 is also spoofable, but for successful spoofing it must be the right cookie for that time period and address. The same applies for the CID. If combined with the address, then it protects, because a spoofer must know the CID. (And sure, it's visible and .. but the cookie is also visible. The point is also the time period, when this CID could be used for spoofing. And that's very short, comparable with the short valid time-period of the cookie.)
I'm still confused, could you characterise precisely your attacker in terms of its goal and position in the network? Thanks!
I don't want to change the wire image more, than this draft already does!
With outer type and inner types nothing additional to the already defined additions is introduces, except that it is used already within the handshake. If you want, I update my wip URL and document, how to use a CID in the handshake. Then you see in wireshark, how it works.
With outer type tls12cid(25) and inner types changecipher_spec(20), alert(21), handshake(22) nothing additional to the already defined additions is introduced Yep That's the trouble. Most "enterprise security" middleboxes want to be able to look into the handshake to determine whether a connection is ok according to their policies. After the handshake completes and the connection is considered alright, they just act as blind packet forwarders. To do the handshake inspection they depend on the established wire image of the TLS/DTLS protocol. If we introduce the ability to change the wire format during handshake (as opposed to the post-handshake phase only) we might end up impairing clients that sit behind those boxes.
Goal: Deny successful handshake of a selected peer. Position: off-path, but know the peer's address and the interesting time period. Something missing?
Smells for me, that a "list of typed cid" (see ) may be used, to enable a peer behind such a box to inform the other, not to use the CID during the handshake. types: "plain" - cid only after handshake "plain+" - cid also during handshake
Just for my personal interest: can you name a middlebox, which supports DTLS?
Sorry, now you triggered me: Why should those middleboxes forward my tlscid record, when my address has changed, but block my tlscid record, when it contains a handshake? If the middleboxes are unaware of this draft, but forward my tlscid record even with changed address, I would assume, they forward my tlscid record also with a inner handshake message.
Deny successful handshake of a selected peer. Position: off-path, but know the peer's address and the interesting time period. OK, thanks very much. Frankly, the combination of perfect timing as well as the randomization provided by the source port makes the attack window pretty narrow.
On the other hand, allocating state too early (i.e., allocating CIDs without strong commitment from client side) opens up an interesting amount of attack surface on server side.
This is a tricky question. Boxes like typically have scripting capabilities which give their admins lots of leeway. I do not build nor operate any of these so my direct experience is ~0, but speaking with the Symantec guys exactly about how to modify the DTLS wire image to signal the presence of CID in a middlebox-tolerant way, their feedback was "to be sure, just leave the handshake alone as much as possible"... I have no reason to doubt their assessment, also given the ways TLS 1.3 was hit in this same space.
Above I wrote nothing else. ??? what's that ??? Why should the use of cid in the inner handshake messages as well allocate anything additionally? The cid is provided in the CLIENTHELLO and/or SERVERHELLO, it's currently just not send in the inner handshake messages. But there is not more or less to allocate, if they are used with other handshake message or not.
I have also no reason to doubt them, but I'm very unsure, if an address change will then work at all with such boxes. I would really prefer to test such an address change. I couldn't find any hint, that that box supports DTLS at all.
So the critical issue seems: with TLS there are bad experience changing the records with DTLS this experience seems to be missing. Some expect them to be similar bad. I unfortunately suspect them to be either a real disaster (address change not working at all), or not that hard. Without boxes to test and/or people with DTLS-boxes experience, it will be hard to find a solution. So, try to use the mailing list to get more feedback?
Sorry, I fail to understand your argument. What to do with an unknown 5-tuple vs what to do with an unknown C-T in a context where you expect to understand the semantics of the flow seem orthogonal to me.
I don't really understand the above sentence so I know a reply is quite risky :-) Anyway, what I wanted to say is that if you want to use CID during handshake in any meaningful way, it means the party requiring it (e.g., server) needs to allocate state internally to be able to check it on receive.
If this allocation is triggered only by one (or two) CH(s), it's pretty easy to mount a "CID exhaustion" attack against the server. Requiring the client to complete the handshake before promoting a "2-tuple" connection into a "CID" connection makes the attack much more demanding and therefore a lot less likely.
(some overlap in the discussion :-) so a updated my comment with the question above.) Try to explain it: Which rules should a box apply to a tls_cid record? It's only valid after a successful handshake? But, how should such a record then be assigned to that successful handshake? Either by knowing the CID (which requires to be aware of this draft), or much weaker by the address, but then it will not work with address changes.
OK, so you don't allocate something on the server side for the CID in the CLIENTHELLO until the handshake is finished? Or you send a CID in the SERVERHELLO without allocating it before the handshake is finished? May be I'm too focused on my implementation, but without an other implementation, which shows what you wrote, it's also hard for me to understand your comments.
At least, I think you target the CID the server side is using. How is it ensured, that the CID in the SERVER_HELLO is unique at least for all established connections and all ongoing handshakes, which are not terminated at that time point?
In my message above s/CID exhaustion/resource exhaustion/ sorry... And yes, you can certainly separate the act of reserving the CID when you decide to send it in the CH from creating state associated with the CID-based session lookup paraphernalia. For example you could use a big enough CID space (say 8 bytes) and reserve your CIDs by means of a monotonically increasing function. And at a later time (my proposal is after the handshake is completed successfully) you grab the memory needed for the CID based session lookup stuff...
Another point is that we'd put more bytes on the wire, increasing the risk of message fragmentation with small MTUs in a situation, the handshake, where the timing of the messaging is such that NAT timeouts are very unlikely and therefore the 5-tuple based demuxing more than adequate.
I can't see a relation of "resource exhaustion" with the usage of the CID in the handshake.
That's right.
In my experience, "small MTUs" are rarely used. The highest risk is caused by a larger CLIENTHELLO, which then gets fragmented (see "resource exhaustion"). Though CID makes the CLIENTHELLO larger, it's more an argument, that CID may not be support on such path. FMPOV, a "optimal support" for peers with a very narrow link, should be moved into a other discussion.
The part with having the choice to either "protect the handshake" or "support address changes" should just leave it to the implementation, which strategy is chosen. I would go for a configurable solution, which enables a "dynamic protection", if too many handshakes are ongoing.
I had a chat with Achim and he agreed that we can leave the feature of using CIDs for handshake messages for DTLS 1.3. This will allow us to get this work done faster. DTLS 1.3 encrypts handshake messages earlier and hence already the handshake itself utilize CIDs.
NAME Thanks for your time!
Hi Hannes, Achim, Good, thanks both for taking the time to sort this out. I think it's a very reasonable choice to not introduce scope inflation at this (late) stage. One thing we still need to do though is tighten up a bit the language around when exactly the CID is put on the wire. Something like: "Once a non-empty CID is successfully negotiated, it MUST be sent on the XYZ message and on all subsequent records of the connection" would remove all the uncertainty I guess. I personally have an inclination for XYZ to be the first application data, mainly because I'd like to commit any resources only after I have full confirmation that the client is a good one. However, I don't care whatever choice we end up with, as long as it's written down precisely in 2119 language.
I'm not sure, what "commit" includes or means exactly. To verify the FINISH you will need the "keying material from the crypto context (derived from the specific mastersecret)". According URL a good estimation will be about 128 bytes. In your wording, you use them before you "commit" them? So adding a couple of bytes for CID to that storage, should not make a difference, or?