Skip to content

Commit 81e5443

Browse files
committed
Expand OpenVPN data key usage
Signed-off-by: Arne Schwabe <[email protected]>
1 parent 07de450 commit 81e5443

File tree

1 file changed

+101
-36
lines changed

1 file changed

+101
-36
lines changed

openvpn-wire-protocol.xml

Lines changed: 101 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,15 +1187,27 @@ available) to drop revoked keys.)</li>
11871187
renegotiation can start using the CONTROL_V1 OPCODE.
11881188
</t>
11891189
<t>
1190-
When the ACK_V1 packet is being sent, the key_id field
1191-
MUST be incremented to ensure the connection can still
1192-
use the old keys for a shorter time until the transition
1193-
has completed. Any following packets need to use the new
1194-
key-id until the old key has been removed and the new
1195-
key-id replaces it completely. [FIXME/schwabe:THIS IS WRONG)
1190+
This session will be negotiated the same as the inital
1191+
session up to the point that the control channel is
1192+
establish. At this point the control channel of the new
1193+
session will replace the control channel of the old channel.
11961194
</t>
11971195
<t>
1198-
[FIXME: Elaborate more on how re-keying happens]
1196+
Unlike in the initial TLS session wih the key-id 0, the client
1197+
will not send PUSH_REQUEST messages to request server to query
1198+
its configuration but continue to use the configuration
1199+
negotiated in the initial TLS session.
1200+
</t>
1201+
<t>
1202+
Whenever a renegotiation happens, the new TLS session will use
1203+
the current key-id increased by one. When the renegotiation
1204+
succeeds, the key-id of the renegotion will also be used for all
1205+
data channel packets and further control channel packet that
1206+
belong/derive from this TLS session. If a renegotiation fails
1207+
and is reattempted, the key-id from the failed attempt will be
1208+
reused for a new renegotiation attempt.
1209+
Only the intial TLS session will use the key-id 0. If the key-id
1210+
reaches 7, the following key-id is 1 when increasing the key-id.
11991211
</t>
12001212
</section>
12011213

@@ -1533,15 +1545,95 @@ struct datakeys {
15331545
key_c2s and auth_c2s are used to encrypt/authenticate data from client to server
15341546
and key_s2c and auth_s2c are used to encrypt/authenticate from server to client.
15351547
</t>
1548+
<section title="Data channel key generation">
1549+
<t>
1550+
Every time a OpenVPN control channel session is succesfully established, a data channel key in the above format is
1551+
generated and assigned to the key-id of the control channel.
1552+
</t>
15361553
<t>
15371554
This key structure is normally generated by using <xref target="RFC5705">RFC 5705 key material exporter</xref>
15381555
from the Control Channel session with the label <tt>EXPORTER-OpenVPN-datakeys</tt>
15391556
and using the 256 bytes length of the structure.
1557+
</t>
1558+
<t>
1559+
When a client or server lack the support for generating data channel keys using TLS Key material
1560+
export and do not annoounce the support in IV_CIPHER, the server may reject a client. At the same
1561+
time a client that does not get signalled by the server by `key-derivation tls-ekm` or
1562+
`protocol-flags tls-ekm` to use TLS Key material can abort the connection.
1563+
</t>
1564+
<t>
1565+
If support for older server or clients is desired that do not support TLS EKM, client and
1566+
server can fall back to the old mechanism of using the
1567+
<xref target="openvpnprf"> OpenVPN data channel PRF</xref>.
1568+
</t>
1569+
</section>
1570+
<section anchor="openvpnprf" title="OpenVPN data channel PRF">
1571+
<t>
1572+
This is a deprecated way of deriving the data channel keys. It should be only implemented if
1573+
compatibility with older OpenVPN versions is required that do not support key derivation via
1574+
the RFC5705 key material exporter. It also requires the MD5 algorithm which often
1575+
modern crypto libraries do not readily support anymore.</t>
1576+
1577+
<t>This uses the <tt>key_random</tt>, <tt>random1</tt>, and <tt>random2</tt> from the key
1578+
exchange messages. These will be prefixed with client and server here to indicate from which
1579+
packet these field are coming. Also the session id of the control channel will be used here</t>
1580+
1581+
<t>
1582+
Here TLS_PRF(seed, secret) is the TLS PRF function according to RFC 2246 with
1583+
MD5 and SHA1 as used in TLS 1.0/1.1.
1584+
1585+
<figure>
1586+
<sourcecode>
1587+
seed = "OpenVPN master secret" | client.random1 | server.random1
1588+
secret = client.key_random
1589+
master_secret - TLS_PRF(seed, secret)
15401590

1541-
Older clients use the mechanism described in the section OpenVPN data channel
1542-
PRF.
1591+
key_seed = "OpenVPN key expansion " | client.random2 | server.random2
1592+
datakeys = TLS_PRF(key_seed, key_seed)
1593+
</sourcecode>
1594+
</figure>
15431595
</t>
1596+
</section>
15441597
</section>
1598+
<section title="Data channel key rotation">
1599+
<t>
1600+
Whenever a reneogiation of a key has finshed, a new data channel key is generated.
1601+
This new key will consider the pending key. A pending key is considered valid for
1602+
decryption of packets with that key-id but will not be used for encryption yet.
1603+
</t>
1604+
<t>
1605+
After a set time period the pending key is promoted to being the active key and
1606+
the active key is set to be the retired key (sometimes also referred to as lame
1607+
duck key). The retired key will be used only for decryption but no longer for
1608+
encryption.
1609+
</t>
1610+
<t>
1611+
In the default configuration of OpenVPN, the time period of promoting a key from
1612+
pending to active is calucated as
1613+
<artwork>
1614+
min(handshake_window, renegotiation_time/2)
1615+
</artwork>
1616+
set by the --hand-window and --reneg-sec options, which default to 60 and 3600
1617+
respectively. So the default time to promote a key from pending to active is 60s.
1618+
</t>
1619+
<t>
1620+
This approach to defer using the key with a timeout is done to avoid key
1621+
desynchronisation. It allows installing the new keys with enough lead time
1622+
that at the point that any side switches from pending to active key, the
1623+
other side will have the key already installed as pending key and is able
1624+
to decrypt the packets. Likewise, keeping the old key as retired key for
1625+
some time after the pending key is switched to active ensures that the
1626+
if the peer takes longer to switch the pending key to active key, the
1627+
receiver will still be able to decrypt the packets using the retiring key.
1628+
</t>
1629+
<t>
1630+
Should a renegotiation complete before a pending key is promoted to an active
1631+
key, the pending key will replace the active key and the new pending key will
1632+
be the pending key. Note that that implementations are allowed to
1633+
limit themselves just two key slots with either active/pending or active/retired
1634+
and in this scenario will drop active key without moving it to retired state first.
1635+
</t>
1636+
</section>
15451637
<section title="Peer-ID">
15461638
<t>
15471639
The purpose of this feature is to allow a client to float between various client
@@ -1755,33 +1847,6 @@ struct data_packet_xfb {
17551847
<t>For unencrypted data packets the same format as CBC without IV is used.</t>
17561848
</t>
17571849
</section>
1758-
<section title="OpenVPN data channel PRF">
1759-
<t>
1760-
This is a deprecated way of deriving the data channel keys. It should be only implemented if
1761-
compatibility with older OpenVPN versions is required that do not support key derivation via
1762-
the RFC5705 key material exporter. It also requires the MD5 algorithm which often
1763-
modern crypto libraries do not readily support anymore.</t>
1764-
1765-
<t>This uses the <tt>key_random</tt>, <tt>random1</tt>, and <tt>random2</tt> from the key
1766-
exchange messages. These will be prefixed with client and server here to indicate from which
1767-
packet these field are coming. Also the session id of the control channel will be used here</t>
1768-
1769-
<t>
1770-
Here TLS_PRF(seed, secret) is the TLS PRF function according to RFC 2246 with
1771-
MD5 and SHA1 as used in TLS 1.0/1.1.
1772-
1773-
<figure>
1774-
<sourcecode>
1775-
seed = "OpenVPN master secret" | client.random1 | server.random1
1776-
secret = client.key_random
1777-
master_secret - TLS_PRF(seed, secret)
1778-
1779-
key_seed = "OpenVPN key expansion " | client.random2 | server.random2
1780-
datakeys = TLS_PRF(key_seed, key_seed)
1781-
</sourcecode>
1782-
</figure>
1783-
</t>
1784-
</section>
17851850
</section>
17861851
<section title="Control channel messages">
17871852
<section title="Message format">

0 commit comments

Comments
 (0)