jiebi/CodeConvo huggingface dataset:
... as otherwise, code squatting again. See-Also: URL Thanks for the updates in the -26; they help a lot. I'm particularly happy to see the (default/example) "first-come-first-remembered" policy in § 7.5, which does a good job of documenting its properties (including potential deficiencies) and can be usable for many environments.  (I do have some suggestions for improvements to the specific wording in the section-by-section comments, but on the whole I like it.) It does lead in to a more general comment, though (which is not exactly new to the changes in the -26 though it is reflected in several of them): some aspects of the concept of "authorization" to appear in a directory, and the verification of authorization for the entire flow from client locating the RD server to final request at the discovered resource, are somewhat subtle.  (The new text discusses, e.g., "repeat the URI discovery step at the /.well-known/core resource of the indicated host to obtain the resource type information from an authorized source" and "a straightforward way to verify [discovered information] is to request it again from an authorized server, typically the one that hosts the target resource".)  The aspects I'm concerned about are not matters of a resource server being authorized to publish to a directory or a client deeming that a server is authorized to act as an RD (though both of those are also important), but seems to rather just be relating to the RD faithfully disseminating the information the RD retrieved from /.well-known/core discovery on the given server(s) (or otherwise learned via some other mechanism). In this sense the RD is just acting as a cache or efficiency aid, but the authoritative source of the information remains (in general) the server hosting the resource.  To be clear, I think the procedures that this document specifies are good and correct procedures for a client to perform, I'm just not sure whether "authorized" is the right term in these cases; "authoritative" might be more appropriate, in that the operation in question is to verify the information retrieved from the RD (which acts in some sense as an intermediary) at the more authoritative source.
(On a tangent from that note, it seems that there is not necessarily any indication to a client that a server claiming to provide a given resource (whether discovered via RD or /.well-known/core) is actually authorized to provide such a resource and be trusted by the client.  But that's not really a property of RD, and rather the underlying CoRE mechanism and any provisioned trust database, so my thoughts about it seem out of scope for this document.) (It's not entirely clear to me what the reader is expected to do with the information about the previous formulation.) (It seems that something also needs to cause the RD to check the authorization of lookup clients to receive the information in question, which might be worth reiterating in this section.) I'm pretty sure the intent here is that only the subject names that are certified by the recognized authority(ies) are stored, in which case I'd suggest to s/all those/all such/. (I can understand why the "store the whole list" logic is used, though there may be some subtleties about name constraints on the (X.509) CAs used, which is why we typically don't recomment treating the entire list of names in the certificate as validated from a single operation, instead preferring "is this certificate authenticated for this specific name?" when the specific target name is available.) Should we talk about whether the lifetime of registration entries is related to the various lifetimes of these credentials/identifiers?  DTLS without resumption is perhaps an interesting case, in that keeping the DTLS association "live" just to be able to update the registration information seems impractical, so perhaps some fixed cap would be applied on the lifetime in that case.  If resumption is used, the resumption information (ticket or session state) has some finite lifetime that could be used to bound the lifetime of the registration. IIRC an OSCORE security context can also have an expiration time; certificates and JWT/CWT have expiration time as well (though the procedures in the first bullet point would effectively allow a "renewal" operation), but the validity period (if any) of a raw public key would have to be provisioned along with that key (or just have RPK be handled akin to DTLS without resumption, I guess). (Similar to my earlier parenthetical comment, the requirement for exact match of all subject name information is unusual.
As concluded in Singapore.
When receiving a packet with an unexpected key phase, an implementation should compute the new keys: This creates a timing side-channel, since an attacker can modify the KEYPHASE bit, thereby making a peer compute the next key generation. The packet will be discarded, since the header is protected by the AEAD, but the fact that the key is computed on receipt of that packet is a side-channel that might be used to recover the header protection key. The way to avoid this side-channel is to pre-compute the N+1 key when rolling over keys from key phase N-1 to N. An implementation would then use the N+1 keys when receiving a packet with an unexpected KEYPHASE, in exactly the same way it would do decryption on a packet sent at key phase N. This however contradicts the text that claims that an implementation may choose to only keep two read keys at any given moment: Directly after a key update, an implementation would have to store (at least) 3 key generations: N-1 for a duration of 3 PTO, in order to be able to decrypt delayed / reordered packets, N, as well as the precomputed N+1 to avoid the timing side-channel described above. I don't think that storing 3 keys is a problem (I think NAME disagrees, I'll let him explain his reasoning himself), but the spec shouldn't pretend that it's possible to create an implementation that both isn't vulnerable to the timing side-channel and at the same time gracefully handles moderate amounts of reordering around a key update.
I think you are correct in pointing out that there is a timing side-channel, and that we need to fix the issue. OTOH, I disagree that requiring all endpoints to be capable of retaining 3 keys is not a good way of fixing the issue due to the following reasons. Firstly, I do not think we can justify why an endpoint needs to be capable of retaining that much keys, even though Key Update is expected to happen very rarely. The purpose of Key Update is to replace a key after extensive use, we would never be using a key that becomes weak just after couple of PTOs. Considering that, using 2 keys should be sufficient; 3 keys is likely a sign of a needlessly complex design.
Let's compare the proposal of the 3-key design with a 2-key design (that allows the receiver to delay the installation of the next key for 3 PTO after since Key Update, which is ). In the 3-key design, the next key is installed when a Key Update happens. The old key is disposed 3 PTO after a Key Update, and the slot becomes NULL. Note also that an endpoint needs to retain a mapping between packet number and key phase to determine whether an incoming packet is to be decrypted using the oldest key or the newest key (those two key share the same KEY_PHASE bit on the wire). In the 2-key design, installation of the next key and the disposal of the old key happens at the same moment (i.e. 3 PTO after a Key Update). An endpoint would always retain 2 keys once the handshake is confirmed. There is no need for retaining a mapping between packet numbers and key phases. The oddity of the key phase bit directly maps to the decryption key. To me it seems that the latter is simpler. As stated above, there is no need for doing Key Update every 3 PTO, and therefore, assuming that we need to make a change due to the attack vector, I think we should simply allow endpoints delay the installation of the next key rather than changing the increasing the minimum state that an endpoint needs to be capable of maintaining.
I agree, there's not really a need to do key updates that frequently. However, I like the fact that we're currently defining a clear rule: An endpoint is allowed to update to N+1 as soon as it has received an acknowledgement for a packet sent at key phase N. You should still keep track of the packet number at which the key update happened, in order to check that the peer is not reusing the old key to encrypt packets after it already switched to new keys. Strictly speaking, this is not required for a working implementation, but it's a really easy check to catch a misbehaving peer (or detect an active attack).
As I've mentioned in the discussion in , the reason I'm skeptical about delaying key updates by 3 PTO (and effectively dropping all packets with a higher key phase until this period is over) is that we're replacing a very clear definition by an approximate rule: the PTO is calculated locally, and depending on the network conditions, the two endpoints might have different opinions about the exact value of the PTO. An endpoint that wants to ensure that no packets are dropped due to the unavailability of keys would have no choice but to wait >> 3 PTO. While this should be well within the safety limits of the cipher suites we're using, not having a clear criterion seems to be a sign of suboptimal protocol design.
Perhaps we should state that an endpoint should precompute the key early but not update keys too frequently to prevent timing attacks and overhead. That is not necessarily a bad thing, but it is unfortunate that there is no clear definition. We could also say the idle timeout period. As long as we compute keys using SHA256 it might not be a concern, but computing keys too frequently could exhaust safety parameters on other potentially faster algorithms.
To clarify, the key phase bit is inside header protection, so the attacker in question is the peer?
NAME No, this is an on-path attack. Header protection is not authenticated, so an attacker can just flip bits in the header. Decrypting the packet will fail then, since the header is part of the authenticated data used in the AEAD. We have a timing side-channel as soon as we treat packets differently based on values in the unprotected header, before authenticating the packet. This is analogous to the .
Thanks for the extra explanation, I'm not sure that's a very good side-channel, but I agree it is one.
Does anyone have any ideas what kind of actual attack could take advantage of this? The attacker can only cause you to install your keys early once per key phase change. Assuming you hardly every change key phase, what then? I agree it's a way the unauthenticated attacker can change your state, but I don't think it's a big enough problem we need to worry about fixing.
That's a good question. I agree that this attack vector doesn't look very promising at first sight, but then again I'm always surprised what cryptanalysts can extract from a single bit. That depends.
If you create the new keys, try decrypt the packet, and then discard the keys (if decryption fails), the attacker has an unbounded number of tries. Obviously, this would also be a DoS vector, since computing new keys is more than order of magnitude more expensive than an AEAD operation (at least in my implementation). If you cache the new keys once they are computed, then the attacker indeed only has a single shot per key phase. However, then you might as precompute the new keys when installing the current key phase. The problem with that is that the spec currently suggests that you only ever need to keep state for 2 key generations at any given moment. This is incompatible with caching the keys for the next key phase, as I described above.
NAME But the current spec. also recommends to wait for 3 PTO before initiating the next Key Update. That would not change, and as we agree, nothing in practice requires us to do Key Updates every 3 PTO. I agree that an endpoint might still want to track the packet number at which key update happened. But even in such case, the simplicity of the 2-key design still exists, in sense that you'd only use it for detecting a suspicious peer. It's much straightforward and easier to test, because the rare case (of actually using 3 keys at the same time) never happens. To clarify, I am not saying that 3-key design is incorrect. My argument is that lack of clear signal is a non-issue (because there is no need to do a Key Update every 3 PTO or more frequently), and that therefore that argument cannot be used for prohibiting people to choose the 2-key design (which is simpler).
Isn't the middle ground here to pre-compute the N+1 key when the N-1 key is dropped, with the drop happening at the first of: 3xPTO after the N key was first successfully used First arrival of a packet which purports to be N+1 The attacker's ability at that point would be to cause any delayed N-1 packets to be dropped, but if we're presuming the ability to bit-flip, they can cause those packets to be invalid and dropped anyway.
NAME That certainly reduces the information being potentially exposed to the attacker to one bit per every key update.
But no less than that for example when an attacker injects two packets slightly more frequent than every 3 PTO, with the only difference between the two packets being the value of the KEY_PHASE bit. In such an attack scenario, the attacker can tell which of the two packets caused the calculation of the updated key for every key update. Admittedly, the leak is tiny; but I am not sure if it is tiny enough that we can ignore.
To recap my comments at the mic: it's not clear to me what the attacker is learning here. Can someone expand on this?
Discussed in Montreal: NAME to work with NAME and NAME to work out the details
I'd like to second NAME comment at the mic. I don’t think this is an issue for which we need text. Without loss of generality, let’s assume that in the worst case an attacker learns the entire unprotected header bytes for every packet. (That is, that header protection does nothing overwhelmingly helpful.) Revisiting the header protection algorithm, it basically works as follows: where H’ and H are the protected and unprotected header bytes, respectively, and sample is known to the adversary. If we assume mask is the output of a PRP, and therefore both IND-CPA secure and KPA secure, an adversary learns nothing from known plaintext and ciphertext pairs. (The typical game-based IND-CPA security definition says that an adversary with access to an oracle for encrypting any message Mi of its choice has negligible probability in selecting b, upon giving the challenger M0 and M1 and receiving an encryption of Mb. Recovering the header protection key would break this assumption, as it would let the adversary encrypt M0 and M1 -- without the oracle -- and trivially match against M_b.) All that said, I think adding text describing that endpoints should precompute keys is fine. After all, it'd be nice if header protection worked as intended.
NAME and NAME to resolve their issue before we'll take it forward
Discussed in Singapore; proposal is to change SHOULD to MAY regarding pregeneration of next phase of keys.
in what I believe is the simplest way possible -- point to 8164 and require that be successfully retrieved prior to sending any scheme other than .
It would be good if it could be clarified what will happen if someone needs/tries to send a HTTP request with an http:// uri over H3. I primarily see this to occur when you have a case where you have an HTTP proxy that receives an HTTP request and then have an HTTP/3 connection with the authorative server. If the expectation is that all requests are upgraded by the HTTP/3 sending side, then that needs to be made explicit.
I might propose this comes down to a discovery problem for the proxy. What method(s) do you envisage the proxy used to decide to make an HTTP/3 connection to the authorative server? This seems related to the discussion in HTTP WG - URL If Alt-Svc is being used, the flow might be that the proxy attempts to make a cleartext HTTP/1.1 connection to the authoritative server and does an upgrade, as described in RFC 7838, to HTTP/3. In which case I don't think any action is required. If the proxy wants to opportunistically upgrade via some happy eyeballs approach described on URL, we might want to provide guidance that either 1) it shouldn't be done for client requests with http:// or 2) that it should always be done.
This is another variant of -- HTTP/2 and HTTP/3 explicitly include the scheme and the authority with all requests, so the server knows what it's being asked for. The question is how the client decides that a QUIC endpoint is authoritative for this particular URL. RFC 7838 describes how an https://-schemed request might come to be sent to an HTTP/3 endpoint and the resolution of the issue was to ask the HTTP WG to define other ways. Adding RFC 8164 as well, an http://-schemed resource might also be requested over HTTP/3; it's up to the HTTPbis group whether they want to enable a direct upgrade there as well. I don't currently see any text required for this, but if you have suggestions, I'm happy to review or expand the discussion to the list.
I'd rather duplicate this to and rely on for this.
We were not very careful in that document to avoid mention of the specific HTTP version, but the technique is perfectly portable between versions. We only really intended to put HTTP/1.x off limits.
Perhaps "not very careful" was careful enough -- it says "such as HTTP/2," and mandates that the protocol needs a way to carry the scheme. HTTP/3 does, so we're covered. Do we think a reference to 8164 is warranted in the section about finding an HTTP/3 endpoint?
By "not very careful" I was mainly referring to the title :) As for the text, I don't know. It will depend on what else it says.
Discussed in London; reference 8164 and require the same check when sending a scheme other than "https."
addresses
"QUIC's linkability resistance ensures that a deliberate connection migration is accompanied by a change in the connection ID and necessitate that connection ID aware DDoS defense system must have the same information about connection IDs as the load balancer {{?I-D.ietf-quic-load-balancers}}. This may be complicated where mitigation and load balancing environments are logically separate." This is insufficient. Even the load balancer is only able to identify the end server, not the connection.
On a related note, the suggestion to use the "first 8 bytes" of a server's connection ID is somewhat strange. Why not observe the CIDL it's using in long headers, or just have common configuration?
How about if we just remove any wording about load balancers here? Like this maybe:
On the 8 bytes: I actually not sure where this comes from, however, I assume that the thinking was that using the first 8 bytes might be good enough to avoid collisions if you don't know the connection ID length. But I guess we can remove it or add some more explanation... any thoughts?
If you read the Retry Services section of QUIC-LB, you'll see that there is no dependence on the Connection ID encoding at all. It is a common format for Retry Tokens that allows servers to (at a minimum) extract the original CIDs necessary for verification. Certainly, no device should drop packets simply because the CID has changed, which is maybe what you're trying to say here? But I'm not sure that this is a DDoS thing.
The point is when a DDoS attack is on-going you want to make sure that on-going connections keep running while new connections are handled more carefully. So you have to be flow aware. However, maybe it's acceptable if connectivity breaks during a DDoS when the 5 tuple changes...? Otherwise you would need to be CID aware.
The VN section suggests that observers not use the version number to detect QUIC. Would it be futile to ask them to admit QUIC versions they don't recognize rather than drop them?
Probably.
Not sure. Depends on the function you implement. I guess there could be security functions that decide to only allow certain versions... not sure if that is justified but I don't think we can stop it.
Any further opinions here?
We can stop it with greasing, I guess.
IMO the draft should specify best practices that don't break extensibility and if people don't follow it it's on them. That's the approach I took in QUIC-LB.
The best practice is to not block any unknown traffic as blocking hinders evolution. However, I guess there might be security reasons why some will not do that. I guess allowing for certain versions of QUIC is better than blocking UDP entirely...?
+1... I don't think that putting text in this document saying "don't wholesale block versions of QUIC you don't understand" will actually change the behavior of the boxes that will ship this behavior, since drop-unknown is taken as a security best practice. But I still think it's worth putting that advice in the document nonetheless, if only to have "I told you so" in an RFC. (I do still tend to think that we'll see only two behaviors emerge in the wild: (1) permit anything with a QUIC wire image since there's not much to grab on to there (and rely on the LB implementation to eat DoS hiding behind that wire image) and (2) block anything that smells like QUIC (because it is easy to implement in the default case and it forces fallback to TCP, which already has lots of running security monitoring code).)
will work up a PR for us to discuss
In manageability: "Integrity Protection of the Wire Image {#wire-integrity} As soon as the cryptographic context is established, all information in the QUIC header, including information exposed in the packet header, is integrity protected. Further, information that was sent and exposed in handshake packets sent before the cryptographic context was established are validated later during the cryptographic handshake. Therefore, devices on path cannot alter any information or bits in QUIC packet headers, since alteration of header information will lead to a failed integrity check at the receiver, and can even lead to connection termination." This isn't precise. The Initial packet is not meaningfully integrity-protected, but the contents of the CRYPTO frame (and the connection IDs) are. An on-path attacker could, for instance, change the ClientHello's Packet Number to from '0' to '1' and then adjust the ACK frame from '1' to '0'. (Why would one do this?)
Is the ACK frame in the case not encrypted...?
The Initial is decryptable by anyone, and so could be rewritten.
Okay. What do we want to write here now?
how about "URL alter any information or bits in QUIC packet headers, since alteration..." changing to: "URL alter any information or bits in QUIC packet headers, except specific parts of Initial packets, since alteration..."
WFM. I can change that as soon as your PR landed (or you add it to your PR).
It seems blindingly obvious to me that an implementation would need to take care of this... and this note of caution seems quite appropriate (if unnecessary... but surely it doesn't hurt).
Dynamic framer add and passthrough (last two paragraphs of section 6.1) assume synchronous operation; what happens to bytes in the send/receive buffers when the framer stack changes? There either needs to be an explicit mutex here (allowing the framer/implementation to lock the buffers at the exact point the framer change happens, not allowing any bytes to be processed while the dynamic framer decision is made), or some way to annotate in a buffer the replay point after which a dynamic reframing is necessary. Are we going to leave this up to implementors to figure out, or should we point out that here be dragons?
We should clarify that these operations within the data path of the stack should be synchronized.