Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mask packet numbers with a per-connection-ID key #1043

Closed
wants to merge 5 commits into from
Closed

Conversation

martinthomson
Copy link
Member

@martinthomson martinthomson commented Jan 9, 2018

This changes the key schedule so that connection ID is part of the key
derivation. Secrets are generally unchanged, except that the handshake secret
is now fixed (we integrate the connection ID via key derivation).

Packet numbers now start from zero, with an additive masking value that is
derived in the same way that packet protection keys are. Also, the type.

Closes #1048, #1034, #850, #990, #311.

This changes the key schedule so that connection ID is part of the key
derivation.  Secrets are generally unchanged, except that the handshake secret
is now fixed (we integrate the connection ID via key derivation).

Packet numbers now start from zero, with an additive masking value that is
derived in the same way that packet protection keys are.

Closes #1034, #850.
connection ID provided by the server. Using a new connection ID will produce a
new packet protection key and IV. New values for obscuring header fields (see
{{header-obscuring}}) ensure that packet numbers can't be used to link activity
on paths that use different connection IDs.

Copy link
Contributor

@mikkelfj mikkelfj Jan 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this optional? @ianswett suggested elsewhere that a packet might be dropped if it receives a packet with a tuple that does not match the connection ID. If so, a new connection ID must be used when transmitting on a new path. OTOH, but I am not sure about the implications with NAT rebinding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be optional if it is to be interoperable.

I'm not sure which point Ian was making. If you lose connection ID and the address tuple changes, you are lost, but either of those can be enough to recover. The address tuple is only sufficient if the server isn't routing based on connection ID though, and we expect that to be quite common.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was in relation to two separate connections during handshake in long form, so it might not actually apply here.

Negotiation packets don't contain a packet number and Retry packets include the
packet number from the Initial packet it responds to. Rather than relying on
ACK frames, these packets are implicitly acknowledged by the next Initial packet
sent by the client.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exclusive to this, but is there text to discuss DoS and amplification attacks related to triggering multiple VN and retry packets? One could imagine slowly triggering a lot of retry packets that are never responded to and though the server backs off, it might effectively send a flood to one target.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've discussed this previously. Retry and Version Negotiation are necessarily smaller than the Initial packet that triggers them. It would therefore be more efficient for the attacker to send its packets directly toward the victim.

for sending MUST increase by at least one after sending any packet, unless
otherwise specified (see {{initial-packet-number}}).
for sending starts at zero for the first packet set and MUST increase by one
after sending a packet.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in #1030, random packet number gaps still need to be permitted to defend against the optimistic ACK attack.
If we want to change the defense against this attack, I'd prefer to discuss this in a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an error. I wish that we had a better defense against optimistic ACK attacks though.

Copy link
Contributor

@MikeBishop MikeBishop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable; minor nits.

struct {
uint16 length = Length;
opaque label<6..255> = "QUIC " + Label;
uint8 connectionId<0>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this included just to emphasize that it's zero-length, or does it actually include a byte representing the zero-length array?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I meant to check up on this, and now that I have, I don't actually know how <0> would be encoded.

been sent, 0-RTT keys can be generated and installed for writing, if 0-RTT is
available. Finally, the TLS state machine reports completion of the handshake,
the 1-RTT keys can be generated and installed for writing. Additionally, new
keys are installed each time that the connection ID changes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to mention TLS key updates?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key updates in TLS are mentioned elsewhere, I think. We don't need to use them.

The packet number and connection ID fields echo the corresponding fields from
the triggering client packet. This allows a client to verify that the server
received its packet.
The connection ID field echoes the corresponding fields from the triggering
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One field

received its packet.
The connection ID field echoes the corresponding fields from the triggering
client packet. This allows a client to correlate a Retry with the Initial
packet that it sends that the server received its packet.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence doesn't parse.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also wrong :/

value is increased for each subsequent packet sent by the server as described in
{{packet-numbers}}. The client increments the packet number from its previous
packet by one for each packet that it sends (which might be an
Initial, 0-RTT Protected, or Handshake packet).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this isn't new text, but this statement about the client is redundant -- the client's behavior is already described at line 586. (In fact, it might be worth consolidating them and simply describing that the first packet sent by each party has a packet number of zero and is incremented with each packet.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed down.

numbers still increase monotonically as long as the connection ID remains
constant. However, these values are different for client and server, and they
change when a connection ID changes, together ensuring that flows with different
connection IDs are not linkable based on the value of these fields.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong statement; maybe we stick to making it more difficult to link?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that this is true as qualified. Based on the values of these fields alone there isn't linkability: they are effectively random. There are ways to mess this up (and multipath will definitely risk doing that).

@ianswett
Copy link
Contributor

ianswett commented Jan 9, 2018

I need some more time to think about this, but is there a discussion which led to this solution I missed?

Also, this PR is large. Is it possible to make it more focused?

@britram britram mentioned this pull request Jan 10, 2018
martinthomson added a commit that referenced this pull request Jan 29, 2018
This is an almost purely editorial change.  It consolidates the description of
QHKDF-Expand and corrects a bunch of minor things related to key derivation and
expansion.  This is the parts of #1043 that I wanted to keep.

The only non-editorial change is a change to the handshake salt used to derive
handshake keys.  That should keep the fresh.

Closes #1043.
martinthomson added a commit that referenced this pull request Jan 29, 2018
This is an almost purely editorial change.  It consolidates the description of
QHKDF-Expand and corrects a bunch of minor things related to key derivation and
expansion.  This is the parts of #1043 that I wanted to keep.

The only non-editorial change is a change to the handshake salt used to derive
handshake keys.  That should keep the fresh.

Closes #1043.
This was referenced Jan 29, 2018
Lekensteyn added a commit to Lekensteyn/base-drafts that referenced this pull request Mar 18, 2018
QHKDF-Update was specific to PR quicwg#1043 (not merged) and included the
Connection ID in the info structure, but the actual merged PR (quicwg#1077)
does not use this, nor does it define QHKDF-Update.
@martinthomson martinthomson deleted the pnadd branch May 29, 2018 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Packet number rework
5 participants