Subject: [quicwg/base-drafts] Make reset simpler and invisible (#574)

From: Martin Thomson <[email-masked]>
Date: Mon, 05 Jun 2017 06:09:48 -0700

More extensive rationale for this design will be provided at the interim.
You can view, comment on, or merge this pull request online at:

  https://github.com/quicwg/base-drafts/pull/574

-- Commit Summary --

  * Make reset simpler and invisible
  * Remove FIPS-180 from the references
  * Editorial tweaks
  * token, not secret, and be consistent

-- File Changes --

    M draft-ietf-quic-transport.md (195)

-- Patch Links --

https://github.com/quicwg/base-drafts/pull/574.patch
https://github.com/quicwg/base-drafts/pull/574.diff

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574

---

From: MikkelFJ <[email-masked]>
Date: Mon, 05 Jun 2017 06:28:37 -0700

The intial token sent in transport parameters - I presume the token is encrypted during setup - but an explanation would be good. Also, I presume the idea is for the server to store connection ID and token on persistent media.

It appears that peer-to-peer operation is not being considered. It would probably only be a minor rewording to allow a client to also reset with the same token.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306187259

---

From: Martin Thomson <[email-masked]>
Date: Mon, 05 Jun 2017 06:38:36 -0700

The server transport parameters are encrypted, the client parameters are not.  That makes this easy for the server, and much harder for the client.  If you are suggesting that the client can use the server-provided value, that wouldn't work.

I think that we need to discuss expectations about peer-to-peer operation at some point.  I see a lot of requests coming in that don't at all fit with my experience of how peer-to-peer works.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306189526

---

From: MikkelFJ <[email-masked]>
Date: Mon, 05 Jun 2017 06:56:23 -0700

> I think that we need to discuss expectations about peer-to-peer operation at some point. I see a lot of requests coming in that don't at all fit with my experience of how peer-to-peer works.

I suppose you consider peer-to-peer like Skype where the client traverses NAT to a cloud infrastructure out to another client.

Peer-to-peer can also mean server to server in a distributed system, at multiple levels: same data center, different data centers, different IP address ranges etc. but common for these are that it is random who initiates the connection and both might attempt to do so at the same time. Over time two entities may switch between being client and server.

Such a setup may also involve routing messages across multiple entities using algorithms such as Kademlia and Chord. This opens up some concerns regarding end-to-end flow control over a routed network while the link level connection would be QUIC. For example, streams might be forwarded using QUICs stream flow control mechanism, and some eggs might have to be broken to achieve the end result (i.e. not fully adhering to spec).

Another similar scenerio is mesh networks for sensor networks, but there are industry adhoc standards emerging for such networks I believe. Here some nodes may be promoted to being internal routing nodes and others edge nodes, though who gets chosen for what can be fairly arbitrary and changing over time.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306193652

---

From: MikkelFJ <[email-masked]>
Date: Tue, 06 Jun 2017 04:02:38 -0700

mikkelfj commented on this pull request.

> +In order to create a Stateless Reset Token, a server could randomly generate
+{{!RFC4086}} a secret for every connection that it creates.  However, this
+presents a coordination problem when there are multiple servers in a cluster or
+a storage problem for a server that might lose state.  Stateless reset
+specifically exists to handle the case where state is lost, so this approach is
+suboptimal.
+
+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 three inputs: the static key, a the connection ID for the connection
+(see {{connection-id}}), and an identifier for the server instance.  A server
+could use HMAC {{?RFC2104}} (for example, HMAC(static_key, server_id ||
+connection_id)) or HKDF {{?RFC5869}} (for example, using the static key as input
+keying material, with server and connection identifiers as salt).  The output of
+this function is truncated to 16 octets to produce the Stateless Reset Token
+for that connection.

A server could not use a connection id because the connection id might have changed, and even if didn't change, it might be available in a short header. It also would not be able to use IP and port tuple because it also might have changed.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-42276074

---

From: MikkelFJ <[email-masked]>
Date: Tue, 06 Jun 2017 04:11:25 -0700

> +the message to be identified as a stateless reset more easily using heuristics.
+
+A server copies the connection ID field from the packet that triggers the
+stateless reset.  A server omits the connection ID if explicitly configured to
+do so, or if the client packet did not include a connection ID.
+
+After the first short header octet and optional connection ID, the server
+includes the value of the Stateless Reset Token that it included in its
+transport parameters.
+
+After the Stateless Reset Token, the server pads the message with random
+octets.
+
+This design ensures that a stateless reset packet is - to the extent possible -
+indistinguishable from a regular packet.
+

Perhaps add that the token MUST appear cryptographically strong random to an observer.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-42277773

---

From: MikkelFJ <[email-masked]>
Date: Tue, 06 Jun 2017 04:42:12 -0700

If I understand the text correctly, and I am not sure that I do, I don't think this approach is workable due to path migration and Connection ID migration and due to the fact that connection ids are generally expected to be present in short headers, and due to the lack of symmetry. All issues mentioned in above comments.

The server essentially has no way to identify the original of the connection without requesting additional information.

A symmetric reset that allows both end points to reset the connection would require some sort of challenge where the server says - whoever this connection is from it makes no sense - please send credentials to allow me to terminate this connection. The same would be true for the client.

This can probably be based on x25519 public key exchange, but it requires some carefull consideration.

I think a simpler is to have the peer tear down the connection if the server does not reply to ping request where the ping is specified to require an immediate pong frame unless one has been sent recently. If the a peer receives garbage with a valid header it should consider issuing a ping request unless it has done so recently.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306461016

---

From: Mike Bishop <[email-masked]>
Date: Wed, 07 Jun 2017 07:11:34 -0700

MikeBishop commented on this pull request.

The connection ID change is a good point -- we would need a way to update the proof when getting a new connection ID.

If the incoming packet doesn't include Connection ID, you're basically stuck -- if you want the ability to reset, you'll need to request Connection ID.  The text talks about this two paragraphs later.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r120636047

---

From: Martin Thomson <[email-masked]>
Date: Wed, 07 Jun 2017 07:42:54 -0700

@martinthomson pushed 1 commit.

d659761  Add an updated token to NEW_CONNECTION_ID

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/fd30ace638a3e48a0f939a7d52be14b230f72269..d659761b78bc7b974ace1885bb70bb026f3854ed

---

From: Martin Thomson <[email-masked]>
Date: Wed, 07 Jun 2017 07:43:44 -0700

I've added a new token to NEW_CONNECTION_ID.  I still have an open action to make this symmetric.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306816916

---

From: MikkelFJ <[email-masked]>
Date: Wed, 07 Jun 2017 07:59:54 -0700

> I've added a new token to NEW_CONNECTION_ID. I still have an open action to make this symmetric.

Shouldn't it also be placed in initial handshake?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306822000

---

From: Martin Thomson <[email-masked]>
Date: Wed, 07 Jun 2017 08:15:00 -0700

> Shouldn't it also be placed in initial handshake?

There is a transport parameter for that.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-306826760

---

From: Martin Thomson <[email-masked]>
Date: Sat, 10 Jun 2017 10:11:32 -0700

@martinthomson pushed 2 commits.

aa475ca  Some minor editorial improvements
022c492  Difficult to guess is important enough to say explicitly.

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/057a738d40e6c94a48e998af892d09b356a2404e..022c492d1847b967032c678f9c12eff6142c56fb

---

From: Martin Thomson <[email-masked]>
Date: Sat, 10 Jun 2017 10:12:46 -0700

1c8751e  Improve grammar a little

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/022c492d1847b967032c678f9c12eff6142c56fb..1c8751e3aeffa6623436f4a27a321d6960e53fff

---

From: ekr <[email-masked]>
Date: Sat, 10 Jun 2017 10:24:45 -0700

ekr commented on this pull request.

> +|                                                               |
++                   Stateless Reset Token (128)                 +
+|                                                               |
++                                                               +
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                        Random Octets (*)                    ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~
+
+This packet uses the short header form with the shortest possible packet number
+encoding.  This minimizes the perceived gap between the last packet that the
+server sent and this packet.  The leading octet of the Stateless Reset Token
+will be interpreted as a packet number.  A server MAY use a different short
+header type, indicating a different packet number length, but this allows for
+the message to be identified as a stateless reset more easily using heuristics.

This seems confusing. Maybe you should instead of "uses" say SHOULD use

> @@ -1116,6 +1079,11 @@ idle_timeout (0x0003):
 : The idle timeout is a value in seconds that is encoded as an unsigned 16-bit
   integer.  The maximum value is 600 seconds (10 minutes).
 
+stateless_reset_token (0x0005):
+
+: The Stateless Reset Token is used in verifying a stateless reset, see
+  {{stateless-reset}}.  This parameter is a sequence of 16 octets.

The TLS term is "vector". I would supply the PDU for this.

I would say MUST be, because otherwise you are leaking

> @@ -2070,6 +2150,11 @@ Connection ID:
 
 : A 64-bit connection ID.
 
+Stateless Reset Token:
+
+: A 128-bit value that will be used to for a stateless reset when the associated
+  connection ID is used (see {{stateless-reset}}).

Ouch, it's ugly to have this delivered in two locations.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-43302050

---

From: MikkelFJ <[email-masked]>
Date: Sat, 10 Jun 2017 10:29:38 -0700

+After the Stateless Reset Token, the endpoint pads the message with an arbitrary
+number of packets containing random values.
+

packets?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-43302174

---

From: Martin Thomson <[email-masked]>
Date: Sat, 10 Jun 2017 10:34:54 -0700

martinthomson commented on this pull request.

Not sure that I follow the PDU comment.

Yep, not seeing an action here.  The token is attached to NEW_CONNECTION_ID and I explain that the technique here relies on having connection ID later in the text.

 
+Stateless Reset Token:
+

Yeah, open to suggestions for how this might be improved.  Nothing I tried seemed to work that well.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r121262137

---

From: Martin Thomson <[email-masked]>
Date: Sat, 10 Jun 2017 10:35:18 -0700

8222af2  stateless reset SHOULD use the short header

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/1c8751e3aeffa6623436f4a27a321d6960e53fff..8222af266c47e40a3bc7ea364cbef1b111d82fee

---

From: Martin Thomson <[email-masked]>
Date: Sat, 10 Jun 2017 10:36:22 -0700

ed1a6dc  octets, not packets

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/8222af266c47e40a3bc7ea364cbef1b111d82fee..ed1a6dc0de81d8ade512c4d51518af540ae4b8eb

---

From: MikkelFJ <[email-masked]>
Date: Sat, 10 Jun 2017 10:38:59 -0700

+Stateless Reset Token:
+

yes, it needs to be a new token otherwise it is not possible to hash 5-tuple based on an endpoint key and then multiple connections would have to share token.

Is there any text that says the token MUST be unique to the path with high probality.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r121262316

---

From: MikkelFJ <[email-masked]>
Date: Sat, 10 Jun 2017 11:16:21 -0700

I think I know how to avoid the reset token in new connection packet, but I am not sure it is simpler/better:

The endpoint generates an internal server key. With this key a connection/path specific reset key is created. This key is shared in transport parameters.

To send a reset: generate a random 64-bit nonce. Sign it with HMAC-SHA256(reset-key, nonce). Send the nonce and the reset key.

The reset key itself must depend on the path because the Connection ID is not always available. The 5-tuple is know to the sender, but not receiver because the receiver might have a different address than the sender observes. Therefore we cannot hash the 5-tuple directly. But the endpoint can derive the reset-key from its view of the 5-tuple and an internal static endpoint key. The transmitted nonce avoids the problem with the different 5-tuple view.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307581659

---

From: ekr <[email-masked]>
Date: Sun, 11 Jun 2017 00:14:15 -0700

+Stateless Reset Token:
+

My objection is just to having two messages, but as you say, I'm not sue how to deal with it

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r121273882

---

From: ekr <[email-masked]>
Date: Sun, 11 Jun 2017 00:14:48 -0700

I mean do:

opaque stateless_reset_token[16];

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r121273896

---

From: Martin Thomson <[email-masked]>
Date: Sun, 11 Jun 2017 01:13:36 -0700

2cad187  Merge branch 'master' into invisible_reset

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/574/files/ed1a6dc0de81d8ade512c4d51518af540ae4b8eb..2cad187993b2f6eec89057bd8bbff52b3d6b8170

---

From: Martin Thomson <[email-masked]>
Date: Sun, 11 Jun 2017 01:16:38 -0700

The connection ID *is* visible on packets.  @mikkelfj, you will have to be a LOT clearer about your concerns here.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307613782

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 03:15:43 -0700

> The connection ID is visible on packets.

The Connection ID is negotiable via transport parameters and may be absent.

> @mikkelfj, you will have to be a LOT clearer about your concerns here.

I'm sorry - I thought I had a good idea, but it was flawed. I will try explain my concerns in more details here - but I still think updating the token at NEW_CONNECTION_ID is better, unless there are race conditions.

In the following I sometimes refer to a server, where it might as well be a client, for the sake of simplicity.

Concern 0:
A reset must be identifiable as such from outside observers, with high probability - but why is this a concern? This concern is derived from the current design and needs an argument. If the token is padded with random data for this reason, the length should either be random, or have same length as other typical packets via padded encryption used to hide content length.

Concern 1:
A reset must work in either direction (symmetri) so both parties can terminate lost state.

Concern 2:
A reset token in one direction must be specific to a single connection with high probablity - otherwise other connections can learn the the token by connecting and forcing a reset, or by having observing powers on path.

Concern 3:
A reset token cannot rely on persistent state or pre-shared keys between two end-points. It could, but it would limit deployment scenarios.

Concern 4:
A reset token may not accidentally expose path migrations by sending the same token on different paths, even if that connection is about to end.

Concern 5:
Due to lack of state (concern 3), a reset token must be generated from a single semi-static server key and information observable from received packets and produce a connection (concern 2) and path specific (concern 4) .

Concern 6:
Because a static server keys may need to be updated, we potentially may have to send two resets, one for each static key during roll-over.

Concern 7:
A public reset should not result in a flood of resets, so an endpoint should limit the frequency of resets on a given path.

Concern 8:
An attacker could force many resets to attack a public reset keys integrity - e.g. AES-GCM breaks after so many iterations, but HMAC_SHA does not. Concern 7 reduces this ability of such attacks. 

Concern 9:
Only the endpoint sending a packet resulting in a reset being sent back must be able to accept the reset, with high propability, even if the token appears encrypted to outsiders, otherwise there is risk of resetting the wrong connection in a complex server environment, and there might be attack vectors on this as well.

Concern 10:
An endpoint cannot assume the observable state (OS) (concern 5) is known to the peer, in other words it cannot be assumed to be shared observable state (SOS). This affects how tokens can be generated. For example, the UDP IP address and port may be different from what the peer knows about itself. Also, the Connection ID is not guaranteed present in packets in the current QUIC draft. To work around this issue, a nonce can be generated and signed, and sent to the peer. This assumes the peers connection state is able to receive validate the signature, and that no other connection endpoints have this ability (concern 9). However, attempting to design a secure token hash algorithms that works under this assumption without violating other concerns is tricky.

End of concerns

This leads to some possible ways to generate resets:

1) A complete random is generated for each conection and path (aka each Connection ID). The token is updated during change of path. This ensures privacy, unique endpoint acceptance etc. This is the current proposal and fullfills all concerns, assuming the the token is created carefully. The current approach does not handle static server key update (roll-over), and does not discuss limiting flow rates, nor padded random length (concern 0), but it largely is compatible with the above concerns.

2) the reset is only advisory and not particularly unique - receving a reset results in verifying the connection is live via a PING that requieres an immediate PONG (acks are too slow). This needs to be rate limited. The reset need not be very secret but should avoid outsiders from easily genering a lot of valid resets.

3) IFF we assume the observable state OS is also shareable (SOS), i.e. the Connection ID is alway visible, we cannot assume SOS does not change on path migration. In fact, if it was, it would by definition violate privacy of path migration. Now lets see how we can generate the token with SOS available (this is not necessarily different from current proposal):

The Static Server Key (SSK) and SOS is used to generate a connection specific reset token signing key (RTSK) which is exhanged during handshake. RTSK = HMAC_SHA256(SSK, SOS). When a reset is sent, a reset nonce RN is generated for each new reset. The reset token (RT) is computed as RT = HMAC-SHA256(RTSK, RN | RT). A random padding sequence (RPS) is also generated unless the RN is large enough to fill that role. The reset header is RH and not detailed here. The reset message is sent as <RH, RN, RT, RPS>. The receiver detects RH and integrity failure and proceeds by retrieving the stored RTSK and computes RTcheck = HMAC-SHA256(RTSK, RN | RT). if RTcheck == RT then the reset is accepted.

Following a crash, a retrieves SSK and computes RTSK = HMAC_SHA256(SSK, SOS) for each path and sends rate limited resets.

If SOS is not not SOS, but only OS (observable state), then the reset can proceed because the peer has stored the RTSK. Therefore, it is not necessary to require that SOS is not OS. However this did not solve the problem of path migration. We saw that we could not have OS or SOS being unchanged after migration for privacy reasons, so path migration MUST issue a new RTSK.

IFF we have migration invariant shared observable state (MISOS) we did not have to exchange information at path migration because RTSK = HMAC_SHA256(SSK, MISOS). When the server crashes it recomputes RTSK and sends the reset. Again, we see that the state need not be shared, so MIOS would also work. But it violates privacy.

We can now define OS to be sufficient to generate tokens. We could define it to be the peers 3-tuple depending on network layer with UDP being default. But it would not solve the issue of having to migrate RTSK during path migration. If we could rely on Connection ID being visible, we could use it as OS, be we cannot (as I understand it).

Therefore, it appears that the might as well send an explicit reset token instead of RTSK over the wire, while keeping the RTSK server side. (Where client has a similar setup the other direction). However, this will violate keeping the reset token unique per reset, but it will still be unique per path. If a reset is only sent once per path, this may be acceptable, otherwise the RTSK needs to be shared instead, per path.

Solution 2) is also an option.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307618844

---

From: ekr <[email-masked]>
Date: Sun, 11 Jun 2017 03:36:08 -0700

> Concern 0: A reset must be identifiable as such from outside
> observers, with high probability - but why is this a concern? This
> concern is derived from the current design and needs an argument. If
> the token is padded with random data for this reason, the length
> should either be random, or have same length as other typical packets
> via padded encryption used to hide content length.

I'm not following this. The point of the current design is to make
it *indistinguishable* to outside observers. And the text does say
you should pad with a random amount of random data.

> Concern 1: A reset must work in either direction (symmetri) so both
> parties can terminate lost state.

Well, more precisely, it should be possible to reset in either
direction. It need not be the same token.

> Concern 2: A reset token in one direction must be specific to a single
> connection with high probablity - otherwise other connections can
> learn the the token by connecting and forcing a reset, or by having
> observing powers on path.

Yes.

> Concern 3: A reset token cannot rely on persistent state or pre-shared
> keys between two end-points. It could, but it would limit deployment
> scenarios.

Perhaps you mean "per-connection" state?

> Concern 6: Because a static server keys may need to be updated, we
> potentially may have to send two resets, one for each static key
> during roll-over.

I'm not sure that this is a real issue. If you re-generate your
server key every 6 months or so and you can't generate stateless
resets for a while, I'm not sure I care. Remember that this is just
a fallback mechanism that is intended to be better than ignoring
the packets.

> Concern 7: A public reset should not result in a flood of resets, so
> an endpoint should limit the frequency of resets on a given path.

I'm not following what this concern is. I agree that sending a
stateless reset shouldn't generate a pile of responses. Do you
mean something else?

> Concern 8: An attacker could force many resets to attack a public
> reset keys integrity - e.g. AES-GCM breaks after so many iterations,
> but HMAC_SHA does not. Concern 7 reduces this ability of such attacks.

I'm not following this either. This mechanism should be designed so
that it is cryptographically safe.

> Concern 10: An endpoint cannot assume the observable state (OS)
> (concern 5) is known to the peer, in other words it cannot be assumed
> to be shared observable state (SOS). This affects how tokens can be
> generated. For example, the UDP IP address and port may be different
> from what the peer knows about itself. Also, the Connection ID is not
> guaranteed present in packets in the current QUIC draft. To work
> around this issue, a nonce can be generated and signed, and sent to
> the peer. This assumes the peers connection state is able to receive
> validate the signature, and that no other connection endpoints have
> this ability (concern 9). However, attempting to design a secure token
> hash algorithms that works under this assumption without violating
> other concerns is tricky.

What we had discussed in the WG was just requiring conn_id if you
wanted stateless reset to work. With that said, assuming that the
path is invariant, you could also establish the shared key as
SK = PRF(K_static, <5-tuple>) (note that the peer need not know its
own address) and have the reset be HMAC(SK, Packet). That avoids
attacks where an attacker uses the server as an oracle to generate
the reset (I think)

> the reset is only advisory and not particularly unique - receving a
> reset results in verifying the connection is live via a PING that
> requieres an immediate PONG (acks are too slow). This needs to be rate
> limited. The reset need not be very secret but should avoid outsiders
> from easily genering a lot of valid resets.

Is this intended as an alternative design? I'm not understanding
why it's attractive, given that the entire point is you want
the other side to go away.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307620235

---

From: Martin Thomson <[email-masked]>
Date: Sun, 11 Jun 2017 03:39:39 -0700

@mikkelfj, I'm afraid that you will need to be much clearer and concise.  Please describe one scenario where this fails.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307620956

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 04:06:16 -0700

> @mikkelfj, I'm afraid that you will need to be much clearer and concise. Please describe one scenario where this fails.

The server cannot store per connection state. So it must derive from the packet it sees. It must combine a static key with that information. So simplified token = hmac(server-key, connection-id). However, if the Connection ID is not present in the packet because it was negotiated away, it will not work because the server create valid token post crash. However, token = hmac(server-key, <UDP, peer-ip, peer-port>) could work.

The concerns could perhaps better be restated as requirements and facts to help guide an analysis. Which I needed because there things stopped working for various reasons and it would be good to have a basis to argue around.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307622357

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 04:30:21 -0700

Perhaps concern is the wrong word - it started that way, but became more like facts and and requirements that can be used to analyse if a solution fullfills these, and if not, what trade-offs are being made.

Also, the concerns are not a critique against the current solution, but it can be used to see where it matches and where it does not - this is what I tried to summarize at the end.

> observers,...
> > it indistinguishable to outside observers. And the text does say

This was added because any solution must fullfill this. But to me it is not clear why we require this. It is not mean to say there is a current problem. But if we don't need this, it would open the design space. I do like to keep it appear random, but that is not an argument.

> direction. It need not be the same token.

I was careful to say reset, not reset token - but I struggled a bit with this.
Yes, sometimes it can be same token both ways, sometimes it cannot - depending on the underlying design and potential exposure to related packet analysis.

>> Perhaps you mean "per-connection" state?

Yes, I thought about clarifying this - the static server key mentioned later is clearly persistent.

>> a fallback mechanism that is intended to be better than ignoring
 
I agree, I just wanted to make the concern visible. But I am happy to accept ignore the issue.

>> stateless reset shouldn't generate a pile of responses. Do you

That is largely it - but this boils down to how a server identifies a unique connection - there may be a flood of meaningless packets from 100K+ connections, so rate limiting here makes little sense, but per end point there can also be many packets, and here only one should be sent within a given time interval. This is non-trivial to implement - you need a large reset state table just for booting a server. You may choose to ignore this concern knowingly as long as you don't open to certain attacks that comprise other servers that share the same key on still valid connections.

> that it is cryptographically safe.

Exactly. It is only a concern if not done so. The concern is there to make sure this is upheld.
 
>> ...

> attacks where an attacker uses the server as an oracle to generate

This is also largely what I suggest at then end of my text. Except a 5-tuple would not work if shared state is required so I used a 3-tuple. But I convinced myself the peer need not observe the same 5-tuple, so this would be ok - when I started I assumed it was necessary for peer to observe same state for key computations, but that turned out to not be correct.

Stating that reset should only work when Connection ID is present is a fair design decision. I may have missed this requirement, but it changes nothing in the list of concerns. It is a willingness to do a trade-off.

> the other side to go away.

It is not necessarily more attractive - and it is intended as alternative design with different tradeoffs. For example it could enable you to have a public reset without a Connection Id if the other design breaks down for some reason, now, or when other changes are made in the protocol.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307623435

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 04:40:27 -0700

BTW:

> you could also establish the shared key as SK = PRF(K_static, <5-tuple>) 

If you do this, you should add a reset nonce RN

SK = PRF(K_static, <5-tuple> | RN) 

Otherwise it could be replayed for new connections. With Connection ID this would not be possible.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307623881

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 04:53:26 -0700

observers,...

> you should pad with a random amount of random data.

That was a complete typo I didn't see even when re-reading the text. Yes, it must NOT be identifiable as such. The rest remains valid - why do we require this, even if it does sound like a good idea?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307624419

---

From: Martin Thomson <[email-masked]>
Date: Sun, 11 Jun 2017 05:38:12 -0700

@mikkelfj,

> The server cannot store per connection state. So it must derive from the packet it sees. It must combine a static key with that information. So simplified token = hmac(server-key, connection-id). However, if the Connection ID is not present in the packet because it was negotiated away, it will not work because the server cannot create a valid token post crash.

The construction of the token is a suggestion.  Note also that the suggestion says this:

> This design relies on the client always sending a connection ID in its packets
so that the server can use the connection ID from a packet to reset the
connection.

I don't know how to make this clearer.  I would accept a pull request that improved the text, certainly.

> However, token = hmac(server-key, <UDP, peer-ip, peer-port>) could work.

It's possible that the remote IP and port are sufficient, especially in the absence of connection ID.  However, these are lower in entropy and not controlled by the server.  If the values collide, which is possible, then the token will be reused, once the reset is used, later connections that collide will be vulnerable to the exact type of denial of service attack that this design is intended to protect against.  I think that connection ID is the best recommendation.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307626605

---

From: MikkelFJ <[email-masked]>
Date: Sun, 11 Jun 2017 05:56:49 -0700

> I don't know how to make this clearer. I would accept a pull request that improved the text, certainly.

I guess I was just not willing to accept that the Connection ID is required for the reset to work - meaning reset does not always work. It is a trade-off.

> It's possible that the remote IP and port are sufficient, especially in the absence of connection ID. However, these are lower in entropy and not controlled by the server. If the values collide, wh…

I touched upon this in other comments. It is possible to avoid repeating the token with just a 3-tuple or 5-tuple if you send a connection/path specific shared key PRF(static-key, connection-id), and sign a nonce and send it to peer. But if you are careful not to send the same token more than once you can avoid this - this requires server state after crash. So I think overall I would prefer sharing a key over a direct token - but there is not a deep difference - since token or key must be replaced at path migration.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307627510

---

From: MikkelFJ <[email-masked]>
Date: Mon, 12 Jun 2017 05:21:01 -0700

Concern 11: A Public Reset MUST not be a source of amplicifcation attacks.

It is not entirely clear what the criteria is for sending Public Reset vs. dropping random garbage. An adverserial packet with random data except first byte and spoofed source address could trigger an implification attack if the triggering packet is smaller than the reset response. Only sending reset upon reboot would be one option.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-307773248

---

From: janaiyengar <[email-masked]>
Date: Tue, 13 Jun 2017 05:38:34 -0700

Can we please move this conversation to the list or to an issue? I hate having to go through commits to figure out what text folks are talking about (there are 11 commits here). This is a significant enough change that I'd like to have this be attached to an issue where the idea is summarized and discussed before we get to the PR.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-308102342

---

From: Martin Thomson <[email-masked]>
Date: Tue, 20 Jun 2017 19:57:37 -0700

@janaiyengar, the commits are all editorial.  The commit is, as far as I can see, ready for review.  I think that we can all apologize for the distracting comments, feel free to ignore those.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#issuecomment-309948926

---

From: MikkelFJ <[email-masked]>
Date: Wed, 21 Jun 2017 07:05:40 -0700

> +continue the connection.  A server that wishes to communicate a fatal connection
+error MUST use a CONNECTION_CLOSE frame if it has sufficient state to do so.
+
+To support this process, the server sends a stateless_reset_token value during
+the handshake in the transport parameters.  This value is protected by
+encryption, so only client and server know this value.
+
+A server that receives packets that it cannot process sends a packet in the
+following layout:
+
+~~~
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+
+|0|C|K|  00001  |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Should CK be required to be 10 here? Keyphase makes little sense, and Connection ID is required.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-45442982

---

From: MikkelFJ <[email-masked]>
Date: Wed, 21 Jun 2017 07:13:09 -0700

+This packet SHOULD use the short header form with the shortest possible packet
+number encoding.  This minimizes the perceived gap between the last packet that
+the server sent and this packet.  The leading octet of the Stateless Reset Token
+will be interpreted as a packet number.  A server MAY use a different short
+header type, indicating a different packet number length, but this allows for
+the message to be identified as a stateless reset more easily using heuristics.
+
+A server copies the connection ID field from the packet that triggers the
+stateless reset.  A server omits the connection ID if explicitly configured to
+do so, or if the client packet did not include a connection ID.
+
+After the first short header octet and optional connection ID, the server
+includes the value of the Stateless Reset Token that it included in its
+transport parameters.
+

Is the Connection ID optional here?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#pullrequestreview-45445365

---

From: MikkelFJ <[email-masked]>
Date: Wed, 21 Jun 2017 07:20:57 -0700

I guess it is - it is only the suggested reset token design that requires the connection ID. But if the reset is from a client that reboots and sends a reset, it cannot reproduce a unique 5-tuple, and so it requires that the connection can be identified by the reset token, unless the connection ID is available.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/574#discussion_r123262254