-
Notifications
You must be signed in to change notification settings - Fork 205
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
Change Packet Number Gap to Packet Number Offset #1307
Conversation
|
||
Packets with with new connection IDs have special rules for encoding the packet | ||
number in the headers. They use an offset (see {{packet-number-offset}}) to | ||
transform the packet number via the following: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this only apply to new connection IDs? Wouldn't it be easier to apply this transformation to every packet number?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just following the existing model that gaps used. I don't have a strong opinion either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gap in the actual packet number was introduced at the point you sent the first packet with a new CID. This proposal is a transformation of the actual packet number for wire presentation, so it needs to occur every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's a clear mistake, the transformation should apply to all packet numbers on the network
I think that's a terrible idea. It perpetuates the fallacy that offsetting packet numbers provides privacy. We have established that it doesn't in an important case, when there is overlap between two connections. The matching pattern of holes and sequence number increment is more that sufficient to establish correlation in these cases. We would be much better off just getting rid of the gaps altogether. They force complex synchronization between sender and receiver, effectively the same management cost as managing encryption keys, but they do not provide nearly as much benefit as encryption. |
@huitema would adding the shuffle (or some other non-cryptographic greasing) alleviate your concerns here? Matching patterns between overlap would be more difficult then. As for this design being a complex synchronization between sender and receiver, I disagree with you. Each side needs only generate the offset once, per connection ID and just store that offset. When sending, it's just an additional add and modulo operation. The receiver just needs to do an add and subtraction operation. Obviously adding whatever greasing algorithm will add additional complexity, but the CPU cost per packet should still be quite low, and easily implemented in hardware. |
@nibanks this looks a bit like my segmented packet numbers proposal but not that this proposal has a fixed offset per connection ID and that a connection ID is replaced before that offset is exhausted. This avoids any linkage other than NAT rebinding. You can further mutilate the clean packet number sequence with a reversible permutation http://stackoverflow.com/a/12996028
And you can further encrypt that permutation using simple XOR magic - apparently IPSec style. |
Just using a random seed might be sufficient to deter the average middle box and with CID update there is no privacy leak. |
I suppose a more elaborate encryption would go like
Due to brute force the encryption is not strong, but combined with per path CID and update before 2^32 PN's it should be robust since the PN encryption is not privacy. To speed things up, one or two multiplication rounds can be taken out. See also |
The above cannot be used directly as IV because the permuation is no longer a 1 to 1 mapping but a key guided mapping, so the encrypted PN will not work as an IV. The same issue should not be the case with the initial seeded value. |
Given how frequently CID rotation might occur (path validation, quiescence, shifts in wind direction), I am dubious that it's wise to rotate 1-RTT keys every time a new CID is used, which I believe is what you're saying here. This also falls prey to the same problem as #1174 -- if you switched keys because you used a new CID to probe, what key do you use back on the original path while you wait for the probe to complete? Key rotation is supposed to be a ratchet forward, and you can't have two key rotations going on at once in the current design, so you also can't take the answer of doing a second rotation on the original path. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @marten-seemann is correct -- this solution only makes sense as a transform on every packet, not just as something to do on particular packets with a new CID. That's my key feedback on fixing the PR.
On the proposal itself, however, I share @huitema's concerns that correlation of gaps between flows is still possible. A future PR for a shuffle can make that harder for an observer, but only so much (observing over the shuffle window, you can perform the same analysis).
|
||
Packets with with new connection IDs have special rules for encoding the packet | ||
number in the headers. They use an offset (see {{packet-number-offset}}) to | ||
transform the packet number via the following: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gap in the actual packet number was introduced at the point you sent the first packet with a new CID. This proposal is a transformation of the actual packet number for wire presentation, so it needs to occur every time.
transform the packet number via the following: | ||
|
||
~~~ | ||
transformed_packet_number = (packet_number + offset) % 2^62 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might actually be okay, but the possibility that the transformed packet number might wrap around to zero before being truncated feels a little odd.
~~~ | ||
|
||
Once transformed, the normal rules of packet number encoding are followed, only | ||
encoding the least number of bits required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"only" and "the least" feels duplicative. Maybe just replace the part with the comma with a reference to the section where the truncation is defined?
Better yet, since this is effectively a transform on every packet number, put this in the section about truncation (it becomes a description of how the 64-bit number is encoded on the wire) and make this section purely about determining what the offset will be.
I forgot about my own proposal: No, rekeying is not needed for each new CID. The segmented packet number idea means that each CID is given an internal incremental high bit value. So the IV is the CID counter + the visible PN, permutated or not. Hence the AEAD can last much longer than CID's
However, for the sake of privacy, you need to do a a high bit increment for each CID, but that is also very cheap. |
This design falls in the category of "obfuscation", analyzed in https://github.com/quicwg/base-drafts/wiki/Summary-of-the-PN-encryption-issues-and-alternatives#alternative-pn-encryption. It does not provide privacy, and also does not protect against ossification. You would be better off leaving the PN in clear text. |
That was also my original intend, but it does offer privacy because it is unique per CID and there is no visible gap to be compared across CID's (modulo NAT rebinding). As to obfuscation, if seeded with an unguessable value, and filtered for the zero case, it would not be unbreakable, but neither would it be very trivial to make use of in a busy switch. So it comes down to how much you wan't to harden against ossification - if the answer is "very" then full PNE is the only way. |
@MikeBishop is right - the proposal only makes sense if it applies to all packets, so the text about this being only for new connection IDs must be removed |
No longer necessary as PNE was merged. |
This is a proposed solution to the privacy/linkability problem by slightly modifying the existing packet number gap solution to make it a per connection ID packet number offset. The offset is used to transform the wire encoding of the packet number, but the connection still uses the same monotonically increasing packet number space (no gaps).
This solution requires very little per packet CPU overhead, compared to PNE.
Unlike the PNE proposal (#1079), this doesn't fix the ossification/greasing problem as well. Instead, I'd like to treat that as a separate problem (and a separate PR) and attempt to solve that with a non-cryptographic solution (shuffle for instance).
Closes: