-
Notifications
You must be signed in to change notification settings - Fork 3
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
Add specification for epoch data keys #5
base: master
Are you sure you want to change the base?
Conversation
560eebb
to
198c1b9
Compare
198c1b9
to
3643c9a
Compare
openvpn-wire-protocol.xml
Outdated
|
||
</references> | ||
<references title='Informative References'> | ||
<reference anchor="AEAD-LIMITS" target="http://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf"> |
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 get a 404 at this link.
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 new link works!
openvpn-wire-protocol.xml
Outdated
The epoch key generation is inspired by the TLS key generation and | ||
<xref target="RFC5869">HMAC-based Key Derivation Function (HKDF)</xref> | ||
and the definition of HDKF-Expand-Label in TLS 1.3. |
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.
Might as well reference RFC 8446 here too.
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.
Has been added!
openvpn-wire-protocol.xml
Outdated
For OpenVPN the epoch 0 key E0 is the OpenVPN key, for any further key, the key derivation is | ||
<artwork> E_N+1 = HKDF-Expand-Label(E_N, "OpenVPN data key update", "", 256)</artwork> | ||
|
||
|
||
The per epoch data channel key is derived via | ||
<artwork> K_i = HKDF-Expand-Label(E_i, "OpenVPN epoch key", "", 256) </artwork> |
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'm pretty sure we don't want 256-byte keys, this should be 32 for a 256-bit key.
(We're both having trouble with bits and bytes lately it seems)
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.
Actually this time, the 256 is intended as it is the size of the OpenVPN key block. I will add some more text to describe why these are so big.
6cfb3e4
to
49d7cb2
Compare
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.
Some language review
openvpn-wire-protocol.xml
Outdated
<ttcol>packet size</ttcol> | ||
<ttcol>Maximum number of packets</ttcol> | ||
<c> 64 </c> | ||
<c> 29.4 </c> |
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.
Missing 2^
?
openvpn-wire-protocol.xml
Outdated
The receiver should count the number of packets that have been received but failed verification. | ||
The number of packets that fail verification and we can tolerate is again specified differently | ||
for DTLS 1.3 and the data usage limit document. For OpenVPN we set the number to 2^36 for all | ||
ciphers, the same DTLS 1.3. An implementation may choose a lower 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.
"same as DTLS 1.3"
openvpn-wire-protocol.xml
Outdated
<xref target="RFC5869">HMAC-based Key Derivation Function (HKDF)</xref> | ||
and the definition of HKDF-Expand-Label in TLS 1.3. | ||
|
||
For OpenVPN the epoch 0 key E0 are the first 32 the OpenVPN key, for any further key, the key derivation is |
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.
"are the first 32 bytes of the OpenVPN key. For any"?
openvpn-wire-protocol.xml
Outdated
} OvpnLabel; | ||
</artwork> | ||
|
||
Keep in mind that the " characters, like in TLS 1.3 are part of the label prefix. |
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.
"characters are part of the label prefix, like in TLS 1.3."
openvpn-wire-protocol.xml
Outdated
</section> | ||
<section title="Epoch key usage"> | ||
<t> | ||
When sending packets, a peer will encrypt packet until the limit for the epoch K_i is reach. At this point, |
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.
"reached"
openvpn-wire-protocol.xml
Outdated
packets is lost, the implementation will still be able to authenticate the packets. | ||
</t> | ||
<t> | ||
Allowing multiple epochs keys, requires the receiving side to keep multiple keys to able to decrypt and |
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.
superfluous comma
openvpn-wire-protocol.xml
Outdated
verify packets with different epochs. An attacker can send a packet with a epoch that is a lot higher than | ||
the current epoch. In order to avoid needing to the generate/keep arbitrary epoch decryption keys, the window | ||
of future decryption keys that is acceptable should be limited. At the same time, the window needs to be large | ||
enough that a long packet loss that causes all packet to be dropped (e.g. a topology change) does not |
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.
"all packets"
openvpn-wire-protocol.xml
Outdated
<t> | ||
The packet id is split into 16 bit bits of epoch and 48bit of counter for | ||
that epoch. Each epoch uses a different a encryption/decryption key and a | ||
different implicit_iv. The epoch select the key to use for decryption. |
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.
"selects"
openvpn-wire-protocol.xml
Outdated
<t> | ||
The epoch_counter of the packet_id together with the implicit IV for the epoch | ||
forms the IV for decryption. The epoch_counter is also used for the replay | ||
protection. Implementation are encouraged to a have a per epoch replay protection. |
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.
"Implementations"
openvpn-wire-protocol.xml
Outdated
forms the IV for decryption. The epoch_counter is also used for the replay | ||
protection. Implementation are encouraged to a have a per epoch replay protection. | ||
Using the whole packet_id as a flat 64bit counter for replay protection will work as | ||
well but will reject reordered packets from the older epoch when a (valid) packet if |
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.
broken sentence
9ada2e3
to
24e0ebe
Compare
openvpn-wire-protocol.xml
Outdated
For details about this opcode see sections about <xref target="dataaead">AEAD</xref> | ||
and <xref target="datacbc">CBC/OFB/CTR</xref> packet format. | ||
For details about this opcode see the sections <xref target="dataaead">AEAD</xref>, | ||
<xref target="data_epoch">AEAD</xref>, and <xref target="datacbc">CBC/OFB/CTR</xref> |
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.
Reference ref text pasto
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.
Some comments from a quick scan, no full review (yet).
openvpn-wire-protocol.xml
Outdated
@@ -1462,7 +1463,8 @@ struct key_exchange { | |||
<li>bit 7: The client is capable of sending exit notification via control channel using <xref target="exitcc">EXIT</xref> message. The client is accpting the protocol-flags pushed option for the EKM capability</li> | |||
<li>bit 8: The client is capable of accepting <xref target="authfailed">AUTH_FAILED,TEMP</xref> messages.</li> | |||
<li>bit 9: The client is capable of dynamic tls-crypt</li> | |||
<li>bit 10: The client is capable of AEAD tag at the end of a data channel packet and capable of using 64bit packet counters for AEAD ciphers.</li> | |||
<li>bit 10: The client is capable of using the epoch data format that uses AEAD tag at the end | |||
has a 64bit packet counters to allow for epoch ciphers.</li> |
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.
Sentence does not compile. Remnant of old text?
openvpn-wire-protocol.xml
Outdated
existing term key-id and since <xref target="RFC9147">DTLS 1.3</xref> uses the same terminology. | ||
</t> | ||
<t> | ||
A sender should calculate a safe amount of packets to send/number of encryption that can be done. |
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.
s/encryption/encryptions/
openvpn-wire-protocol.xml
Outdated
</texttable> | ||
<t> | ||
Instead of (implicitly) only tracking only the number of packets, an implementation can also instead | ||
track the number of plain text blocks s and the number of packets q: |
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.
Good point. It might actually make even more sense to present this first, and make the hard requirement for implementations to not exceed the limits you present here. The above section could then serve as an example of a possible implementation.
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.
Yes, I will do that. My current implementation actually tracks the plaintext blocks and number of packets as that is easier to track then do the whole figuring out the maximum size we are willing to encrypt thing.
openvpn-wire-protocol.xml
Outdated
<artwork>q ≤ (p^(1/2) * 2^(129/2) - 1) / (L + 1)></artwork> | ||
|
||
gives us basically the same limit that TLS imposes: | ||
<artwork> q ≤ 24^(24.9999) </artwork> |
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.
2^24.9999 ?
openvpn-wire-protocol.xml
Outdated
necessary. | ||
</t> | ||
<t> | ||
Implementations have to ensure to calculate the limit with the actual maximum size that they are |
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.
Might need some clarification that this is only relevant for implementations that do not track the actual amount of plain text blocks encrypted.
openvpn-wire-protocol.xml
Outdated
and the definition of HKDF-Expand-Label in TLS 1.3. | ||
|
||
For OpenVPN the epoch 1 key E_1 are the first 32 the OpenVPN data key. Note that unlike when | ||
when using the OpenVPN key directly for encrypting/decryption, E_1 is the same for both direction |
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 need some extra wording to make it immediately clear that this does not mean we use the same key for both directions. Something like "E_1 is used for key expansion only and therefore the same [..]" perhaps?
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.
Yeah. During the implementation I changed this to actually use different epoch keys for both direction as that was better suited and I wanted to eliminate that strange "generate a 256 byte blob and slice into key/iv" stuff as that is "fine" for internally in OpenVPN itself but I don't want that to bleed into DCO implmentations. They should rather do something saner.
openvpn-wire-protocol.xml
Outdated
</t> | ||
<t> | ||
Each peer is expected to hold the current epoch key K_i, the previous K_i-1 and a number of | ||
future keys K_i+1, K_i+2,....,K_i+j. The number of future key j depends on the expected possible |
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.
future keyS
Each peer is expected to hold the current epoch key K_i, the previous K_i-1 and a number of | ||
future keys K_i+1, K_i+2,....,K_i+j. The number of future key j depends on the expected possible | ||
data rate of the implementation and needs to be large enough that even when a reasonable amount of | ||
packets is lost, the implementation will still be able to authenticate the packets. |
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 seems to be an implementation consideration for implementations that are not able to derive future keys on demand from the data channel code (like DCO?). Consider being explicit about that.
And, doesn't the same hold for old keys? If you expect to roll over often, and want to be able to gracefully accept out-of-order packets, you might want to keep more old keys. Or is that not a valid use case?
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.
Yeah, this is a tradeoff that I will explicility mention here. Not being able to decrypt an old keys only results a packet loss. Not being able to decrypt a future key results in complete loss of the connection.
3471fa0
to
fa0e65e
Compare
fa0e65e
to
a0b85e3
Compare
As addition a peer cannot regard apparent overuse of a send key by other the other peer as error as the | ||
limit can change if new information is available but the peer MAY move to a higher sending key epoch of its | ||
own to try to trigger the same on the peer as outlined in the previous paragraph. |
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'm not sure I understand this. In the future, there might be better bounds for GCM mode and we update our RFC to reflect them, and old implementations need to handle that situation?
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.
Yes, basically the recommendation of the limits RFC is the same. If you see a peer using more packets than we currently consider safe, you have two options
- error out and kill connection/drop packets
- ignore that the peer sent too many packets and continue decrypting the packets.
We choose option 2 here, so that if it turns out that the limits were too pessimistic, we can use better limits in the future and don't have to fall back to the lowest limits that we ever put into a client/server.
a0b85e3
to
34fa086
Compare
Signed-off-by: Arne Schwabe <[email protected]>
34fa086
to
b29639f
Compare
No description provided.