Subject: Benjamin Kaduk's Discuss on draft-ietf-quic-transport-33: (with DISCUSS and COMMENT)

From: Benjamin Kaduk via Datatracker <[email-masked]>
Date: Wed, 06 Jan 2021 13:45:09 -0800

Benjamin Kaduk has entered the following ballot position for
draft-ietf-quic-transport-33: Discuss

When responding, please keep the subject line intact and reply to all
email addresses included in the To and CC lines. (Feel free to cut this
introductory paragraph, however.)

Please refer to https://www.ietf.org/iesg/statement/discuss-criteria.html
for more information about IESG DISCUSS and COMMENT positions.

The document, along with other ballot positions, can be found here:
https://datatracker.ietf.org/doc/draft-ietf-quic-transport/

----------------------------------------------------------------------
DISCUSS:
----------------------------------------------------------------------

This is very much a "discuss discuss", and I am not strongly convinced
that there is a problem here, but if there is a problem it is a fairly big
one.

This document defers creation of a downgrade protection mechanism for
version negotiation; after all, if there is only one version in
existence, there is nothing to negotiate.  However, an effective
downgrade protection mechanism requires support from all potentially
affected parties in order to be reliable, so some careful thought is in
order.  If we limit ourselves to a mindset where QUIC versions are
infrequent undertakings brought about by standards action (i.e., we
don't have to worry until a "v2" exists), then deferring seems to be
okay (but part of the Discuss is to confirm that my reasoning is valid).
The main goal of downgrade protection is to be able to distinguish a node
that only supports v1 (or in general, any single version, or set of
versions that only has one overlapping version with the peer) from one
that supports a different shared version but was tricked by an attacker
into using v1 when it otherwise would have used a different version.
I'll call that different version v2 for clarity.  However, if the peer
only supports v1, there's nothing to distinguish and nothing to
negotiate; it suffices to ensure that all nodes that are capable of v2
support the downgrade protection scheme.  That is, an attacker can only
change the negotiated protocol version (as opposed to just causing
connection failure, which can be done in many other ways) if there is
some shared version other than v1 that would have been negotiated in the
absence of the attacker.  So, if v2 is definitly going to be
defined+implemented before other versions, and all nodes that support v2
support downgrade protection, we are guaranteed that in any case where
two peers would negotiate v2 in the absence of an attack, both peers
support the downgrade protection mechanism and thus that mechanism will
be effective in the face of an attack.  Peers that don't support the
mechanism only do v1 and so there is no downgrade possible when they are
participating in the connection.  (We would, of course, still need to be
confident that we could define such a downgrade protection scheme in a
backwards-compatible manner, though this seems like a fairly low bar
given the extensibility provided by transport parameters and frame
types.)

However, it's not clear to me that this assumption holds that v2 is
going to be the next version and that every node that implements v1 and
some other version will definitely implement v2.  In particular, we
currently have a very open registration policy for new versions, and
there may be a desire to have some custom version of QUIC, perhaps that
only has a small difference from v1, and furthermore a desire to use
that custom version when available but be able to use v1 when not
available.  There might be multiple such new versions in development in
parallel, with no clear "first new version" tasked with the
responsibility to develop a downgrade protection mechanism for global
use.  The interaction between multiple competing downgrade-protection
mechanisms seems likely to become quite messy quite quickly, so I am
inclined to see "make each non-standards-track version specify their own
downgrade protection" as a non-starter.

I think that the lack of a secure downgrade protection mechanism is
fundamentally incompatible with an open procedure for creating new
versions while claiming that the protocol is a secure protocol.  While it
would not be a pleasant choice, I think we might be forced to require
standards action for new QUIC versions until we have a single global
downgrade protection mechanism defined.  Or perhaps I misunderstand the
ecosystem that we are trying to produce, or am making erroneous
assumptions.  I'd love to hear more about how the WG decided to proceed
with the current formulation, especially with regard to what
consideration was given to non-standards-track new versions.

The above notwithstanding, I support this protocol and I expect to
change my position to Yes once this point is resolved in some manner.

----------------------------------------------------------------------
COMMENT:
----------------------------------------------------------------------

This protocol is nicely done and the document well-written and
well-organized.  It's really exciting to see what we can do with a
nearly clear slate and the accumulated modern knowledge about protocol
design.  Congratulations and thanks to all who contributed!
Special thanks (in advance) to the chairs for helping translate my
comments into github issues.

I have some editorial suggestions that I put up at
https://github.com/quicwg/base-drafts/pull/4597 .

Abstract, Section 1

My understanding is that "exemplary" typically is used to refer to not
just any example of the topic in question, but to one that is the
pinnacle of achievement or the best of its kind.  Do we intend to make
such a claim about the congestion control algorithm in [QUIC-RECOVERY]?

Section 1.3

   x (E) ...:  Indicates that x is repeated zero or more times (and that
      each instance is length E)

Does "repeated zero or more times" mean that there is zero or more
instances in total, or one or more instances in total?  (I assume the
latter, and would suggest additional wording if the former is what was
intended.)  I am specifically curious about the application to the Ack
Range field of the ACK Frame, since it seems like early on in a
connection it is not always possible to construct a valid Gap field, but
will not duplicate the question there.

Section 2.4

   *  write data, understanding when stream flow control credit
      (Section 4.1) has successfully been reserved to send the written
      data;

(side note) I note that "flow control credit has been reserved" is
different than "has been ACKd by the peer".  I guess the expectation is
that if such information is needed, an application-layer ACK should be
used, since QUIC ACKs can be sent before the peer application has
consumed the received data?

Section 3.1

I'm not sure why "Peer Creates Bidirectional Stream" appears on two
transitions in the figure.  The prose suggests that the copy on the
Ready->Send transition is erroneous.

Section 4.1

   QUIC employs a limit-based flow-control scheme where a receiver
   advertises the limit of total bytes it is prepared to receive on a
   given stream or for the entire connection.  [...]

Should I be reading some distinction into "limit-based" (here) vs
"credit-based" (earlier) flow control?

Section 4.2

   When a sender receives credit after being blocked, it might be able
   to send a large amount of data in response, resulting in short-term
   congestion; see Section 6.9 in [QUIC-RECOVERY] for a discussion of
   how a sender can avoid this congestion.

No such section exists in the -33; perhaps §7.7 is intended?

Section 5.1.1

   An endpoint SHOULD ensure that its peer has a sufficient number of
   available and unused connection IDs.  Endpoints advertise the number
   of active connection IDs they are willing to maintain using the
   active_connection_id_limit transport parameter.  An endpoint MUST NOT
   provide more connection IDs than the peer's limit.  [...]

IIUC, the reason that a negotiated limit is needed here is not exactly
for the storage of the connection ID values themselves (though the
requirement to explicitly use RETIRE_CONNECTION_ID makes it not as
simple as it might be), but rather due to the requirement to recognize
the associated stateless reset tokens.  Is that correct?  If so, perhaps
it could be mentioned as a factor, here.

Section 5.2.2

                                   Servers SHOULD respond with a Version
   Negotiation packet, provided that the datagram is sufficiently long.

This SHOULD seems redundant with the first sentence of the section?

   Packets with a supported version, or no version field, are matched to
   a connection using the connection ID or - for packets with zero-
   length connection IDs - the local address and port.  These packets
   are processed using the selected connection; otherwise, the server
   continues below.

(side note) Packets with a short header do not indicate the connection
ID length (or version).  I think we admit the possibility that a server
could advertise a zero-length connection ID to some but not all clients;
does that imply that a lookup by address/port in the local connection
database would be needed to determine whether such a short-header packet
would have a zero-length connection ID or not?

Section 6.2

                                               A client MUST discard any
   Version Negotiation packet if it has received and successfully
   processed any other packet, including an earlier Version Negotiation
   packet.  [...]

It seems like this requirement might be too strict, in that it could
prevent otherwise successful communication when a limited on-path
attacker injects a Version Negotiation packet.

Section 7.2

   When an Initial packet is sent by a client that has not previously
   received an Initial or Retry packet from the server, the client
   populates the Destination Connection ID field with an unpredictable
   value.  This Destination Connection ID MUST be at least 8 bytes in
   length.  [...]

My usual policy on seeing a random nonce shorter than 128 bits is to ask
for explanation of why the shorter value is safe for the use it is being
put to.  (How bad would it be to bump this to 16?)

                                                           Once a client
   has received a valid Initial packet from the server, it MUST discard
   any subsequent packet it receives with a different Source Connection
   ID.

This seems over-zealous as written, since it would seem to prevent the
server from ever using a new Source Connection ID on that connection,
even in response to a client migration event.  Is it intended to be
scoped to just Initial (and Handshake?) packets as is done for the
server in the following paragraph?

Section 7.4

                   Application protocols can recommend values for
   transport parameters, such as the initial flow control limits.
   However, application protocols that set constraints on values for
   transport parameters could make it impossible for a client to offer
   multiple application protocols if these constraints conflict.

Should we go a step further and forbid application protocols from making
such requirements?

Section 7.5

   Once the handshake completes, if an endpoint is unable to buffer all
   data in a CRYPTO frame, it MAY discard that CRYPTO frame and all
   CRYPTO frames received in the future, or it MAY close the connection
   with a CRYPTO_BUFFER_EXCEEDED error code.  [...]

How future-proof is this?  NewSessionTicket is "safe" to discard in that
doing so has no negative consequences for the current connection (it may
indicate that previously received tickets have been invalidated, but
that is also fairly benign and can happen for other reasons), but in
general post-handshake CRYPTO frames are not constrained in what TLS
messages they can carry, including any TLS messages defined in the
future.  I am not sure that we can effectively require all future TLS
post-handshake messages to be safe to discard.

Section 8.1.3

   Clients that want to break continuity of identity with a server MAY
   discard tokens provided using the NEW_TOKEN frame.  [...]

This seems more like a SHOULD than a MAY, given the precondition.

                                                    A server SHOULD
   encode tokens provided with NEW_TOKEN frames and Retry packets
   differently, and validate the latter more strictly.  [...]

Didn't we already have a MUST-level requirement for being able to tell
them apart, in §8.1.1?

Section 8.1.4

   An address validation token MUST be difficult to guess.  Including a
   large enough random value in the token would be sufficient, but this
   depends on the server remembering the value it sends to clients.

(How large is "large enough?")

Section 8.2

   Path validation is used by both peers during connection migration
   (see Section 9) to verify reachability after a change of address.  In
   path validation, endpoints test reachability between a specific local
   address and a specific peer address, where an address is the two-
   tuple of IP address and port.

In light of the toplevel definition of "address" in this document, the
last clause seems unnecessary.

Section 9

   The design of QUIC relies on endpoints retaining a stable address for
   the duration of the handshake.  [...]

Why do we allow PATH_CHALLENGE (and the impossible PATH_RESPONSE) to be
sent in 0-RTT frames, then?  (This might dupe a comment later...)

Section 9.5

   Similarly, an endpoint MUST NOT reuse a connection ID when sending to
   more than one destination address.  Due to network changes outside
   the control of its peer, an endpoint might receive packets from a new
   source address with the same destination connection ID, in which case
   it MAY continue to use the current connection ID with the new remote
   address while still sending from the same local address.

The MAY seems like it may be in conflict with the MUST.

Section 10.2.1

   An endpoint's selected connection ID and the QUIC version are
   sufficient information to identify packets for a closing connection;
   the endpoint MAY discard all other connection state.  [...]

Are the packet protection keys for outgoing traffic (or the literal
CONNECTION_CLOSE packet contents) not considered part of "connection
state"?

Section 10.3

Just to check my understanding: it is "safe" for a server to decide that
it will never use stateless reset and send random values in the
stateless_reset_token fields that it immediately forgets?  (It would
then not be able to ever send stateless reset, of course, but AFAICT
that is the only consequence.  The client still has to track the
relevant state, and the server has to track
per-connection-ID-sequence-number state.)  I don't know if that's worth
mentioning, since the field is otherwise essentially mandatory when
server connection IDs are in use.

                                                                An
   endpoint that sends a stateless reset in response to a packet that is
   43 bytes or shorter SHOULD send a stateless reset that is one byte
   shorter than the packet it responds to.

(side note) We haven't gotten to the anti-looping stuff in §10.3.3 yet,
so the "one byte shorter" is a bit out of the blue until we get there.

Section 10.3.2

I'm not sure whether it should be here or earlier, but somewhere we
should motivate this construction as being something that can be
generated statelessly, e.g., by a server restarting after a crash, based
only on attributes (e.g., Connection ID) of a received packet from a
previous connection.  The value is computed in advance and given to the
peer so that the peer will know what to expect if the stateless reset
functionality needs to be used, and then generated at runtime by an
endpoint that has lost state.  The scheme described in the first
paragraph requires state, and thus is hard to justify describing as a
stateless reset...

   A single static key can be used across all connections to the same
   endpoint by generating the proof using a second iteration of a
   preimage-resistant function that takes a static key and the
   connection ID chosen by the endpoint (see Section 5.1) as input.  [...]

The phrase "second iteration" doesn't seem to be explained at all.

   This design relies on the peer always sending a connection ID in its
   packets so that the endpoint can use the connection ID from a packet
   to reset the connection.  An endpoint that uses this design MUST
   either use the same connection ID length for all connections or
   encode the length of the connection ID such that it can be recovered
   without state.  In addition, it cannot provide a zero-length
   connection ID.

(There is a corollary that the length of the connection ID has to be
enough so that multiple connection IDs can be issued to all potential
peers cumulatively over the lifetime of the static key, though perhaps
it's sufficiently obvious so as to go without saying.)

Section 12.4

A forward-reference to §19.21 for how extension frames can be used might
be useful.

Why are PATH_CHALLENGE/PATH_RESPONSE allowed in the 0-RTT packet number
space?  (Hmm, the prose and table may be inconsistent here, too.  I
touch some things in my PR but I think not all of them.)  The server
isn't allowed to send at that level, so it seems that even if a client
did sent PATH_CHALLENGE in 0-RTT, the PATH_RESPONSE would have to come
back in 1-RTT.  (And with no challenge to reply to, the client can't
very well send a PATH_RESPONSE in 0-RTT.)  Also, IIRC, we state
elsewhere that we require a stable path for the duration of the
handshake.  Even preferred-address probing can't occur until the client
has the server's transport parameters, which aren't usable until 1-RTT
keys are available (even if they may technically be available prior to
then).

Section 13.2.3

   ACK frames SHOULD always acknowledge the most recently received
   packets, and the more out-of-order the packets are, the more
   important it is to send an updated ACK frame quickly, [...]

Do we have a strict definition of "out of order" that we adhere to?  I
didn't see one in [QUIC-RECOVERY] on a quick search, but haven't read it
in depth yet.
(TCP RACK used roughly "X is out of order when X has lower sequence
number than Y and X is received after Y is received", which is what I'll
use as a mental model until I read otherwise.)

Section 13.2.5

   When the measured acknowledgement delay is larger than its
   max_ack_delay, an endpoint SHOULD report the measured delay.  This
   information is especially useful during the handshake when delays
   might be large; see Section 13.2.1.

I'm not sure I understand when this delay would not be reported even in
the absence of this guidance.  Is the idea that you should specifically
send an ACK with Largest Acknowledged corresponding to the highly
delayed packet, even if you could send an ACK with a larger Largest
Acknowledged (but lower delay)?

Section 17

(side note) I don't know that it would be of particular benefit to have
it explained in the document, but I do find myself curious why there is
a Fixed Bit.

Section 17.2.5

Should we give some guidance on the (minimum) length of the Retry Token
(possibly in a subsection)?  I am not sure that the "MUST be
non-zero-length" from §17.2.5.2 is the only guidance we want to give...

Section 17.2.5.1

   A server MAY send Retry packets in response to Initial and 0-RTT
   packets.  A server can either discard or buffer 0-RTT packets that it
   receives.  A server can send multiple Retry packets as it receives
   Initial or 0-RTT packets.  A server MUST NOT send more than one Retry
   packet in response to a single UDP datagram.

When the server sends multiple Retry packets in such a scenario, do the
Source Connection ID fields need to be different (or the same) across
all of them?  (Or does it not matter?)

Section 17.2.5.2

   Token field to the token provided in the Retry.  The client MUST NOT
   change the Source Connection ID because the server could include the
   connection ID as part of its token validation logic; see
   Section 8.1.4.

It looks like Section 8.1.4 doesn't actually talk specifically about
connection IDs being bound to the token, just "additional information
about clients".  Perhaps it should?

Section 19.16

   Retiring a connection ID invalidates the stateless reset token
   associated with that connection ID.

Is it the sending or the ACKing of the frame that effectuates the
invalidation?

Section 19.17

As above, please confirm that the 64-bit nonce is wide enough to support
the purpose for which it is being used.

Section 19.19

   Reason Phrase:  A human-readable explanation for why the connection
      was closed.  This can be zero length if the sender chooses not to
      give details beyond the Error Code.  This SHOULD be a UTF-8
      encoded string [RFC3629].

Does "human-readable" engage BCP 18 and the SHOULD-level requirement for
carrying information about language?

Section 20.1

   TRANSPORT_PARAMETER_ERROR (0x8):  An endpoint received transport
      parameters that were badly formatted, included an invalid value,
      was absent even though it is mandatory, was present though it is
      forbidden, or is otherwise in error.

(nit) maybe some singluar/plural mismatch here, though the RFC Editor
would probably have a better suggested fix than I could come up with.

Section 21

Should we reiterate somewhere that 1-RTT data sent by the server prior
to handshake completion is being sent to an unauthenticated client?

Section 21.1

As was noted by others, the terminology used for the taxonomy of
attackers is a bit unusual (i.e., divergent from [SEC-CONS]) and
surprising.  It does seem to be fairly clearly specified, though, so is
probably not worth trying to change at this point.

Section 21.1.1

[Just noting here for visibility that my editorial PR adds some text
here to emphasize that the peer authentication provided by the TLS
handshake is a vital property as well.  Clients that do not check TLS
server certificates against the identity of the endpoint they're
attempting to contact are not guaranteed secure operation.]

Section 21.1.3.1

   *  Split and merge datagrams along packet boundaries

Those packet boundaries are obfuscated by header protection, though,
right?

Section 21.1.3.3

   3.  A limited on-path attacker can cause an idle connection to be
       deemed lost if the server is the first to resume activity.

Pedantically, if the client resumes activity after the server does, but
within, say, 2*PTO, I don't think the connection would actually be lost.
But perhaps I am missing something.

Section 21.2

   The Source and Destination Connection ID fields are the primary means
   of protection against off-path attack during the handshake.  These

Presumably we should then give some guidance on how to generate the
Connection IDs so that they can fulfill this role effectively.  Though it
is likely to change significantly as a result of IETF Review,
draft-gont-numeric-ids-sec-considerations may have some useful advice
here.  In particular, it seems like they actually do need to be
unpredictable in order to fulfill this role, and very short Connection
IDs will not be very effective either.

Section 21.3

   Servers SHOULD provide mitigations for this attack by limiting the
   usage and lifetime of address validation tokens; see Section 8.1.3.

I recognize that it is probably an advanced implementation feature to do
so, but implementations can also mitigate by detecting elevated rates
across all connections or some identifiable cateogry of connections, of
sending responses to 0-RTT data that are declared lost, treating that as
indication of an ongoing attack, and racheting down the congestion
window it uses for such data for the duration of the attack.  This in
theory could improve the stability of the Internet as a whole, which
would be the motivation for mentioning it in this document as opposed to
leaving it at the discretion of implementors.

Section 21.5

   For example, cross-site request forgery [CSRF] exploits on the Web
   cause a client to issue requests that include authorization cookies
   [COOKIE], allowing one site access to information and actions that
   are intended to be restricted to a different site.

Server-side request forgery is also a powerful example of this type of
attack.  Though it's not really clear that we need more than one example
here, so "no change" is okay with me.

Section 21.5.2

   Clients however are not obligated to use the NEW_TOKEN frame.
   Request forgery attacks that rely on the Token field can be avoided
   if clients send an empty Token field when the server address has
   changed from when the NEW_TOKEN frame was received.

   Clients could avoid using NEW_TOKEN if the server address changes.
   However, not including a Token field could adversely affect
   performance.  Servers could rely on NEW_TOKEN to enable sending of
   data in excess of the three times limit on sending data; see
   Section 8.1.  In particular, this affects cases where clients use
   0-RTT to request data from servers.

This seems to be setting us up to specifically recommend trading away
security in favor of performance.  Is that the right tradeoff?
(Also, in the vein of my earlier comment, advanced implementation
strategies involving detecting the presence of an attack might provide
global benefit to the Internet, though the case is a bit weaker here
than it was in the other situation.)

Section 21.10

   An on-the-side attacker can duplicate and send packets with modified

This is the only instance of "on-the-side" (or "on the side") in the
document; I suggest rephrasing to conform to the prevailing terminology.

Section 21.11

This would be a good place (or §10.3) to discuss the procedures for
rotating the static key used by stateless reset, per BCP 107.

Section 21.13

                       Ideally, routing decisions are made independently
   of client-selected values; a Source Connection ID can be selected to
   route later packets to the same server.

Is the client's address considered to be "client-selected"?  It's not
clear to me that ignoring IP address locality and routing efficiency is
going to be the ideal behavior.

Section 22.1.1

Are there going to be PII concerns with requiring contact information in
the (public) registry?

Section 22.1.2

   Applications to register codepoints in QUIC registries MAY include a
   codepoint as part of the registration.  IANA MUST allocate the
   selected codepoint if the codepoint is unassigned and the
   requirements of the registration policy are met.

Is this intended to preclude the experts from requiring an allocation to
be made from a range with a different-length encoding?

Section 22.1.4

Should we require an expectation that the publicly available
specification is going to be stable and/or continue to be accessible, as
a condition of a permanent registration?

Section 23.1

I think RFC 4086 is typically listed only as an Informative reference.

It is amusing that IPv4 is a normative reference but IPv6 only
informative.  (Given how they are referenced, I don't fault this
categorization.)

Section 23.2

Should [QUIC-INVARIANTS] also be required reading?

---

From: Lucas Pardue <[email-masked]>
Date: Thu, 7 Jan 2021 02:28:15 +0000

Hi Ben,

Thanks for the review. I've captured your comments as issues on the QUIC WG
GItHub repository. Links to each are provided as in-line responses.

> https://datatracker.ietf.org/doc/draft-ietf-quic-transport/
https://github.com/quicwg/base-drafts/issues/4607

https://github.com/quicwg/base-drafts/issues/4608

> will not duplicate the question there.

https://github.com/quicwg/base-drafts/issues/4609

> consumed the received data?
https://github.com/quicwg/base-drafts/issues/4610

Section 3.1
> Ready->Send transition is erroneous.

https://github.com/quicwg/base-drafts/issues/4611

> "credit-based" (earlier) flow control?

https://github.com/quicwg/base-drafts/issues/4612

> No such section exists in the -33; perhaps §7.7 is intended?

https://github.com/quicwg/base-drafts/issues/4613

> it could be mentioned as a factor, here.

https://github.com/quicwg/base-drafts/issues/4614

> would have a zero-length connection ID or not?

https://github.com/quicwg/base-drafts/issues/4615

> attacker injects a Version Negotiation packet.

https://github.com/quicwg/base-drafts/issues/4616

> put to.  (How bad would it be to bump this to 16?)

https://github.com/quicwg/base-drafts/issues/4617

> server in the following paragraph?

https://github.com/quicwg/base-drafts/issues/4618

> Should we go a step further and forbid application protocols from making

https://github.com/quicwg/base-drafts/issues/4619

> post-handshake messages to be safe to discard.

https://github.com/quicwg/base-drafts/issues/4620

> This seems more like a SHOULD than a MAY, given the precondition.

https://github.com/quicwg/base-drafts/issues/4621

> Didn't we already have a MUST-level requirement for being able to tell

https://github.com/quicwg/base-drafts/issues/4622

> (How large is "large enough?")

https://github.com/quicwg/base-drafts/issues/4623

> last clause seems unnecessary.

https://github.com/quicwg/base-drafts/issues/4624

> sent in 0-RTT frames, then?  (This might dupe a comment later...)

https://github.com/quicwg/base-drafts/issues/4625

> The MAY seems like it may be in conflict with the MUST.

https://github.com/quicwg/base-drafts/issues/4630

> CONNECTION_CLOSE packet contents) not considered part of "connection

https://github.com/quicwg/base-drafts/issues/4631

> server connection IDs are in use.

https://github.com/quicwg/base-drafts/issues/4632

> so the "one byte shorter" is a bit out of the blue until we get there.

https://github.com/quicwg/base-drafts/issues/4633

> paragraph requires state, and thus is hard to justify describing as a

https://github.com/quicwg/base-drafts/issues/4635

> The phrase "second iteration" doesn't seem to be explained at all.

https://github.com/quicwg/base-drafts/issues/4636

> it's sufficiently obvious so as to go without saying.)

https://github.com/quicwg/base-drafts/issues/4637

> keys are available (even if they may technically be available prior to

https://github.com/quicwg/base-drafts/issues/4638

> use as a mental model until I read otherwise.)

https://github.com/quicwg/base-drafts/issues/4639

> Acknowledged (but lower delay)?

https://github.com/quicwg/base-drafts/issues/4640

> it explained in the document, but I do find myself curious why there is

https://github.com/quicwg/base-drafts/issues/4641

> non-zero-length" from §17.2.5.2 is the only guidance we want to give...

https://github.com/quicwg/base-drafts/issues/4642

> all of them?  (Or does it not matter?)

https://github.com/quicwg/base-drafts/issues/4643

> about clients".  Perhaps it should?

https://github.com/quicwg/base-drafts/issues/4644

> Is it the sending or the ACKing of the frame that effectuates the

https://github.com/quicwg/base-drafts/issues/4645

> the purpose for which it is being used.

https://github.com/quicwg/base-drafts/issues/4646

> carrying information about language?

https://github.com/quicwg/base-drafts/issues/4647

> would probably have a better suggested fix than I could come up with.

https://github.com/quicwg/base-drafts/issues/4648

> to handshake completion is being sent to an unauthenticated client?

https://github.com/quicwg/base-drafts/issues/4649

> probably not worth trying to change at this point.

https://github.com/quicwg/base-drafts/issues/4650

> attempting to contact are not guaranteed secure operation.]

https://github.com/quicwg/base-drafts/issues/4651

> Those packet boundaries are obfuscated by header protection, though,

https://github.com/quicwg/base-drafts/issues/4652

> But perhaps I am missing something.

https://github.com/quicwg/base-drafts/issues/4653

> IDs will not be very effective either.

https://github.com/quicwg/base-drafts/issues/4654

> leaving it at the discretion of implementors.

https://github.com/quicwg/base-drafts/issues/4655

> here, so "no change" is okay with me.

https://github.com/quicwg/base-drafts/issues/4656

> than it was in the other situation.)

https://github.com/quicwg/base-drafts/issues/4657

> document; I suggest rephrasing to conform to the prevailing terminology.

https://github.com/quicwg/base-drafts/issues/4658

> rotating the static key used by stateless reset, per BCP 107.

https://github.com/quicwg/base-drafts/issues/4659

> going to be the ideal behavior.

https://github.com/quicwg/base-drafts/issues/4660

> Are there going to be PII concerns with requiring contact information in

https://github.com/quicwg/base-drafts/issues/4661

> be made from a range with a different-length encoding?

https://github.com/quicwg/base-drafts/issues/4662

> a condition of a permanent registration?

https://github.com/quicwg/base-drafts/issues/4663

> informative.  (Given how they are referenced, I don't fault this

https://github.com/quicwg/base-drafts/issues/4664

> Should [QUIC-INVARIANTS] also be required reading?

https://github.com/quicwg/base-drafts/issues/4665

Cheers,
Lucas
On behalf of QUIC WG Chairs

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 07 Jan 2021 15:52:00 +1100

Responding to the DISCUSS point only:

On Thu, Jan 7, 2021, at 08:45, Benjamin Kaduk via Datatracker wrote:
> [... many words on version negotiation removed...]
>
> I'd love to hear more about how the WG decided to proceed

I think that this is the key ask here.  I don't think that this is an appropriate use of DISCUSS, I believe that the working group consensus is clear and clearly documented, but I'll attempt to answer faithfully nonetheless.

The working group came to the conclusion around half way though the design process that we did not have a firm understanding of what it meant to authenticate the choice of QUIC version.  We had mechanisms proposed, but we found either operational issues or ways to circumvent the protections in those proposals.  Given those discoveries, we made a decision to defer protections for version negotiation until after version 1 was deployed.

This comes with risks, though I don't think that uncoordinated development of mechanisms is the primary one.  The primary risk is that we never publish a workable design.  It is a hard problem, after all.

Other relevant points made in that discussion:

* You don't need to rely on version negotiation to deploy a new version, in the extreme case where we fail to secure it.  We have Alt-Svc, for instance, which is secure enough for HTTP (though I will concede that SVCB isn't good enough).  Indeed, we want to avoid the performance hit of version negotiation for those applications anyway, so we're unlikely to be affected.

* The problem only exists if you have both clients and servers willing to support two different versions and the least preferred (or worst) doesn't provide any downgrade protection.  Non-standards track versions that have no intent of coexisting with version 1 are therefore not a downgrade risk.

* Addressing version downgrade in QUIC doesn't address the problem of downgrade from QUIC to TCP (or vice versa if you prefer the other order).  That said, we probably have to tolerate that sort of downgrade, at least for the moment.

Ultimately, the working group is committed to solving the problem.  There is adopted draft on defining a form of version negotiation.  I've also recently updated draft-thomson-tls-snip which attempts to solve the problem more generally, including addressing the question of TCP/QUIC downgrade, which nothing this working group does will ever address.  Not a lot of engagement on that, but I think what it reveals - in addition to this being HARD - is how the problem is not necessarily limited to QUIC.

There has been a lot more discussion on this point than the above, and I have likely missed other key points, but I hope that this will suffice and we can get back to the YES position promptly.

> change my position to Yes once this point is resolved in some manner.

Cheers,
Martin

---

From: Benjamin Kaduk <[email-masked]>
Date: Wed, 6 Jan 2021 22:54:04 -0800

> I think that this is the key ask here.  I don't think that this is an appropriate use of DISCUSS, I believe that the working group consensus is clear and clearly documented, but I'll attempt to ans…

By way of clarification, allow me to phrase a related (if not identical)
concern in a way that closely adheres to the RFC 2026 requirements for a
Proposed Standard specification:

1) is this an unresolved design choice?
2) did the WG resolve a design choice by concluding that it is safe to defer
   creation of a version downgrade protection mechanism?
3) if yes, what assumptions were used to make that choice?
4) are those assumptions valid?

Most of the discourse in my ballot position involved inferences and
assumptions as to the answers to (2) and (3), leaving uncertainty about
(4).

Thank you for continuing on an attempting to answer; I would prefer if we
do not spend too much energy on the "appropriate use of DISCUSS" topic and
attempt to conclude the technical discussion quickly instead.

> * The problem only exists if you have both clients and servers willing to support two different versions and the least preferred (or worst) doesn't provide any downgrade protection.  Non-standards…

Yes.  Do we have any reason to believe that non-standards-track versions
will or will not intend to coexist with v1?  I, at least, do not have any
data on that question either way.  I think this relates to my (3) above --
are we assuming that the problem of downgrade protection only becomes
relevant when there is specifically an IETF v2?

> Ultimately, the working group is committed to solving the problem.  There is adopted draft on defining a form of version negotiation.  I've also recently updated draft-thomson-tls-snip which attemp…

I agree that it's not necessarily limited to QUIC, though even having
something that only works within the QUIC ecosystem would be better than
nothing.  It would be surprising to define a protocol with verisons and a
Version Negotiation packet but end up with technical flaws that prevent
that packet from working properly, though.

> There has been a lot more discussion on this point than the above, and I have likely missed other key points, but I hope that this will suffice and we can get back to the YES position promptly.

This helps some, and I'm happy to hear that the WG is committed to solving the
problem.  I think it would be fruitful to try to drill a little more into
what assumptions we are making when we say (okay, I'm synthesizing a bit,
but I believe this is the sentiment) that "it is safe to defer availability
of this mechanism until a future version of the protocol exists".

This might touch on things like:

- is the only "future version" we care about IETF v2?
- what role will non-standards-track versions play in the global ecosystem?
- what does "safe" mean in that statement?
- what properties are needed for a version downgrade mechanism to be called
  "secure"?

(I recognize that answering that last one may end up being nearly as hard to
answer as actually solving the problem.)

My main goal here is to have some reasonable level of confidence that we
are not putting ourselves in a position that will be hard or impossible to
get out of in the future.  Depending on what assumptions we are making, it
may be very easy or somewhat less easy to achieve such confidence, but
deferring entirely to future versions of the protocol without information
on how or when such version(s) will appear leaves me without much
confidence on that front.

Thanks,

Ben

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 07 Jan 2021 18:20:33 +1100

Excision performed in the service of brevity.
> relevant when there is specifically an IETF v2?

We have no information, but that indicates more that we have time to work on a solution.

> that packet from working properly, though.

I am confident that we have enough of an escape valve that we will be able to define new versions securely.  As is the working group (who I am certain will speak up if they disagree).

> I think it would be fruitful to try to drill a little more into

If only we hadn't already discussed this at length.

> answer as actually solving the problem.)

I think that we know the answer in the general sense, just not in the specific sense of being able to define the bits and manage operational concerns and other protocol design constraints.

> confidence on that front.

The working group reached that confidence.  I don't know how much effort I'm able to devote now to helping you reach that state.  Perhaps other participants would like to offer their help now.

---

From: Jana Iyengar <[email-masked]>
Date: Wed, 6 Jan 2021 23:39:08 -0800

Ben,

The working group chose actively to make this decision. We had a broken
version negotiation in the spec, and after several long discussions, we
decided to remove the VN process out of the v1.

As it stands, in the worst case, if we find that we cannot do a safe
version negotiation within QUIC, we are stuck with a wasted version field
and a VN packet in the protocol. We can still build and deploy future
versions of QUIC, we just won't be able to negotiate their use within QUIC.

Given that we have a draft in progress, I don't believe that we'll end up
in that state, but even if we do, it's not an unsafe state. The working
group has consensus to move with v1 being incomplete in this regard,
because it's not unsafe.

To be clear, we aren't deferring safety of QUIC v1 (this document and this
protocol) to a future mechanism. We're deferring safety of the version
negotiation mechanism (which we don't have) to when we actually build that
mechanism. If we don't succeed, all we lose are the wasted bits in v1 and
we won't be able to negotiate a different version within QUIC.

If anyone else deploys a vN, the only way we are providing to use it is
through Alt-Svc. That is how major HTTP/3 deployments deploy multiple QUIC
versions today. That allows us to deploy multiple QUIC versions without
needing VN.

Am I helping, or is there a different point that I'm missing?

- jana

On Wed, Jan 6, 2021 at 11:21 PM Martin Thomson <[email-masked]> wrote:

> I am confident that we have enough of an escape valve that we will be able
> to define new versions securely.  As is the working group (who I am certain
> will speak up if they disagree).
>
> I think that we know the answer in the general sense, just not in the
> specific sense of being able to define the bits and manage operational
> concerns and other protocol design constraints.
>
> The working group reached that confidence.  I don't know how much effort
> I'm able to devote now to helping you reach that state.  Perhaps other
> participants would like to offer their help now.
>

---

From: Mikkel Fahnøe Jørgensen <[email-masked]>
Date: Thu, 7 Jan 2021 15:34:53 +0100

> On 7 Jan 2021, at 07.54, Benjamin Kaduk <[email-masked]> wrote:
> 
>  Do we have any reason to believe that non-standards-track versions

There are probably no information available at this point, but given how easy it is to deploy a new QUIC version, it is likely that several non-standard versions will emerge. Some variability can happen within v1 using extension frames but for example crypto will require a new version.

TLS 1.3 is not suitable for very resource constrained devices so it is likely that optimized protocols will emerge either as a standard or out of necessity. Another example could be space communication with network characteristics beyond what is practical in v1, and this isn’t that far out given that a mobile network has already been contracted for a moon base.

Even so, the overreaching concern was that producing a broken version negotiation protocol would be far worse than not providing one as long as there is only one version. This would also allow for practical experiments - keeping in mind that at the time, various prototype implementations were rather rudimentary. There were other more pressing concerns such as connection migration that had to be done right in v1. Getting everything right would risk never getting anything done.

So ideally version negotiation should be ready for v1 but realistically, it is not critical facility as long as there is only one version. Thus, anyone releasing other versions while there is no standardized negotiation protocol would necessarily not be able to safely interoperate with other versions in general, but they would be able to detect multiple client versions and decide to accept or reject a connection.

We have also historically seen downgrade attacks in critical infrastructure such as TLS, so version negotiation should not be taken lightly. Again, no negotiation is better than bad negotiation.

Mikkel

---

From: Mike Bishop <[email-masked]>
Date: Thu, 7 Jan 2021 15:16:21 +0000

To expand on the Alt-Svc case slightly; we removed the “version hint” ALPN extension from HTTP/3, but later made a decision that an ALPN token can imply a QUIC version, so offering a set of ALPNs implies the set of supported QUIC versions.

From: QUIC <[email-masked]> On Behalf Of Jana Iyengar
Sent: Thursday, January 7, 2021 2:39 AM
To: Martin Thomson <[email-masked]>
Cc: WG Chairs <[email-masked]>; [email-masked]; The IESG <[email-masked]>; Lars Eggert <[email-masked]>; QUIC WG <[email-masked]>; Benjamin Kaduk <[email-masked]>
Subject: Re: Benjamin Kaduk's Discuss on draft-ietf-quic-transport-33: (with DISCUSS and COMMENT)

Ben,

The working group chose actively to make this decision. We had a broken version negotiation in the spec, and after several long discussions, we decided to remove the VN process out of the v1.

As it stands, in the worst case, if we find that we cannot do a safe version negotiation within QUIC, we are stuck with a wasted version field and a VN packet in the protocol. We can still build and deploy future versions of QUIC, we just won't be able to negotiate their use within QUIC.

Given that we have a draft in progress, I don't believe that we'll end up in that state, but even if we do, it's not an unsafe state. The working group has consensus to move with v1 being incomplete in this regard, because it's not unsafe.

To be clear, we aren't deferring safety of QUIC v1 (this document and this protocol) to a future mechanism. We're deferring safety of the version negotiation mechanism (which we don't have) to when we actually build that mechanism. If we don't succeed, all we lose are the wasted bits in v1 and we won't be able to negotiate a different version within QUIC.

If anyone else deploys a vN, the only way we are providing to use it is through Alt-Svc. That is how major HTTP/3 deployments deploy multiple QUIC versions today. That allows us to deploy multiple QUIC versions without needing VN.

- jana

On Wed, Jan 6, 2021 at 11:21 PM Martin Thomson <[email-masked] <mailto:[email-masked]> > wrote:

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 7 Jan 2021 08:56:34 -0800

I mostly agree with what others have said here.

For the record, my view was that the WG should define what
draft-ietf-quic-version-negotiation calls "compatible" version negotiation
(i.e., where the Initial was valid for both version N and N+1) but not
"incompatible" negotiation. However, the WG consensus was to negotiate
neither. I believe it is possible to add version negotiation safely to QUIC
after v1 is published, as evidenced by the fact that a design for this
already exists in draft-ietf-quic-version-negotiation. ISTM that this falls
into the category of "informed WG decisions".

To clarify one point, Jana writes:
"If anyone else deploys a vN, the only way we are providing to use it is
through Alt-Svc." This is true, but as noted above, the mechanism defined
in the current draft the WG is working on would allow a version N+1/version
N client to safely offer version N+1 to servers even without an alt-svc
hint, which I believe is the right VN target (this is what, for instance,
TLS allows).

-Ekr

On Thu, Jan 7, 2021 at 7:16 AM Mike Bishop <[email-masked]> wrote:

> To expand on the Alt-Svc case slightly; we removed the “version hint” ALPN
> extension from HTTP/3, but later made a decision that an ALPN token can
> imply a QUIC version, so offering a set of ALPNs implies the set of
> supported QUIC versions.
>
>
>
> *From:* QUIC <[email-masked]> *On Behalf Of *Jana Iyengar
> *Sent:* Thursday, January 7, 2021 2:39 AM
> *To:* Martin Thomson <[email-masked]>
> *Cc:* WG Chairs <[email-masked]>; [email-masked];
> The IESG <[email-masked]>; Lars Eggert <[email-masked]>; QUIC WG <
> [email-masked]>; Benjamin Kaduk <[email-masked]>
> *Subject:* Re: Benjamin Kaduk's Discuss on draft-ietf-quic-transport-33:
> (with DISCUSS and COMMENT)
>
>
>
> Ben,
>
>
>

---

From: Benjamin Kaduk <[email-masked]>
Date: Thu, 7 Jan 2021 15:18:19 -0800

Thanks everyone for the productive discussion.  It's clear that there's
a lot of background available to those who participated in the previous
WG discussions but (understandably!) did not make it into the document
itself, and I appreciate the effort that was put in to help share that with
me.

Just to state it clearly, at no point has my position been that QUIC v1
needs to be delayed until a complete version negotiation story exists.
As this was a "discuss discuss", my goal was to obtain more information
about the actual situation in order to confirm that there are no
significant issues, since my interpretation of the text in the document
itself left that possibility open.

Attempting to summarize salient points:

- the IETF is only currently defining bindings for HTTP over QUIC,
  though other entities are free to define their own protocol over QUIC
  at any time.
- the only way currently defined to discover a QUIC endpoint to use as
  server for a given HTTP service is the Alt-Svc header field, which
  uses an ALPN value to indicate the protocol to use; it is perhaps not
  fully nailed down that the ALPN value will be specific to a particular
  version of QUIC but the ALPN vlaue probably will be specific to a
  particular version of QUIC.
- (SVCB is in the works, too, but may not be able to meet all the needs
  for this purpose.)
- Anyone doing non-HTTP or non-Alt-Svc is presumed to be configuring it
  out of band and thus can provision the QUIC version to use along with
  other provisioned information; in-band version negotiation is not
  needed in that case.  If needed (e.g., we cannot build a secure
  downgrade protection mechanism), this or similar techniques could be
  used generically.
- A downgrade protection mechanism solely in-band at the QUIC layer will
  not be a complete solution for existing protocols that may also fall
  back to a TCP binding (or new protocols that need to traverse networks
  like the Internet that don't reliably pass UDP in the ways QUIC
  needs).  New protocols over QUIC that are berift of such legacy would
  have a complete solution, though.
- There seems to be a desire to have only zero or one functional downgrade
  prortection/version negotiation mechanism, globally.
- (There is a corresponding desire to have zero non-functional downgrade
  protection/version negotiation mechanisms.)
- In accordance with the previous two points, it's expected that a
  downgrade protection/version negotiation scheme, when specified, will
  be in an IETF standards-track protocol specification.  (This document
  does not necessarily have to be a new QUIC version, as I understand it,
  though is not a blocking dependency until there is such a new version.)
- In particular, we do *not* expect non-IETF QUIC versions to define
  their own downgrade protection scheme.  They are expected to either
  pick up the IETF one (when it exists) or just only use a single
  version at a time, possibly with out of band configuration.

I've attempted to update the text in the document to reflect my
understanding of the current WG expectations (as summarized above), in a
PR at https://github.com/quicwg/base-drafts/pull/4697 .
Obviously, if my summary above is incorrect, that PR is not expected to
be useful.

In particular, since we do *not* expect or want non-IETF QUIC versions
to be attempting to specify a downgrade protection scheme, the scope of
the problem space seems sufficiently restricted that we have ample time
to come up with something good and not find ourselves reacting to events
out of our control.  The phrasing in the -33 suggests, at least to me,
that *any* future version of QUIC, including one developed outside the
IETF, might update version negotiation handling, which is where my
perception of risk arose.

I've tried to refrain from expounding on topics that are not actually
relevant, but since I'm prone to doing so I may have let some sneak in
anyway...

Thanks again,

Ben

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 7 Jan 2021 15:36:21 -0800

>   particular version of QUIC.

I don't believe this is correct. You can simply try to connect with QUICv1.

>   have a complete solution, though.

Hmm.... Well, it obviously can't be at the QUIC layer, because you won't be
using QUIC at all, but it can be at the TLS layer.

>   version at a time, possibly with out of band configuration.

Maybe? I'm not sure there is a consensus one way or the other on this.

-Ekr

---

From: Spencer Dawkins at IETF <[email-masked]>
Date: Fri, 8 Jan 2021 13:14:46 -0600

Hi, Ben,

Top-posting here - I think one other point that is worth remembering, is
that the QUIC working group also has
https://datatracker.ietf.org/doc/draft-ietf-quic-manageability/, which
seems like a fine place for recommendations about deployment of specific
versions and withdrawal of other versions.

In my mind, there are two cases. Either

   - QUICv1 is "secure enough", so using it is OK even if QUICv2 would be
   better, or
   - QUIVv1 is not "secure enough", so downgrading will be a problem.

People can deploy QUIC using a variety of implementation strategies, but
given that the QUIC implementation is likely at least a library, and may be
a library bound to a specific application, it would be reasonable to say
"QUICv1 is not secure enough, so stop using QUICv1 as soon as possible",
and let implementers and deployers put out versions of applications that
aren't bound to QUICv1 at all.

(This discussion is slightly weird to me, because the last time I asked
about "QUICv2", the answer I got was that we're more likely to run for some
time with QUIv1 + extensions, but even then, my intention when QUIC was
chartered, was that deploying new versions should be orders of magnitude
than the universal deployment of a new version of TCP, for instance, and
withdrawing QUICv1 should be a lot easier than withdrawing TCPv4).

I'm sure everyone will Do The Right Thing, of course.

Best,

Spencer

---

From: Martin Duke <[email-masked]>
Date: Fri, 8 Jan 2021 11:18:27 -0800

Downgrade is a problem even if v2 offers no security improvements. For
instance, a middlebox might want to inspect v1 Initials and force
downgrades, which would prevent deployment of new versions.