This is a preliminary description of tls-crypt-v2. It should give a good
impression about the reasoning and design behind tls-crypt-v2, but might
need some polishing and updating.
Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <1540208715-14044-1-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17788.html
Signed-off-by: David Sommerseth <davids@openvpn.net>
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,189 @@ |
0 |
+Client-specific tls-crypt keys (--tls-crypt-v2) |
|
1 |
+=============================================== |
|
2 |
+ |
|
3 |
+This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN |
|
4 |
+to use client-specific ``--tls-crypt`` keys. |
|
5 |
+ |
|
6 |
+Rationale |
|
7 |
+--------- |
|
8 |
+ |
|
9 |
+``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared |
|
10 |
+among all clients and servers in an OpenVPN deployment. If any client or |
|
11 |
+server is compromised, the attacker will have access to this shared key, and it |
|
12 |
+will no longer provide any security. To reduce the risk of losing pre-shared |
|
13 |
+keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique |
|
14 |
+tls-crypt key. This allows large organisations and VPN providers to profit |
|
15 |
+from the same DoS and TLS stack protection that small deployments can already |
|
16 |
+achieve using ``tls-auth`` or ``tls-crypt``. |
|
17 |
+ |
|
18 |
+Also, for ``tls-crypt``, even if all these peers succeed in keeping the key |
|
19 |
+secret, the key lifetime is limited to roughly 8000 years, divided by the |
|
20 |
+number of clients (see the ``--tls-crypt`` section of the man page). Using |
|
21 |
+client-specific keys, we lift this lifetime requirement to roughly 8000 years |
|
22 |
+for each client key (which "Should Be Enough For Everybody (tm)"). |
|
23 |
+ |
|
24 |
+ |
|
25 |
+Introduction |
|
26 |
+------------ |
|
27 |
+ |
|
28 |
+``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce |
|
29 |
+client-specific tls-crypt keys without introducing a lot of server-side state. |
|
30 |
+The client-specific key is encrypted using a server key. The server key is the |
|
31 |
+same for all servers in a group. When a client connects, it first sends the |
|
32 |
+encrypted key to the server, such that the server can decrypt the key and all |
|
33 |
+messages can thereafter be encrypted using the client-specific key. |
|
34 |
+ |
|
35 |
+A wrapped (encrypted and authenticated) client-specific key can also contain |
|
36 |
+metadata. The metadata is wrapped together with the key, and can be used to |
|
37 |
+allow servers to identify clients and/or key validity. This allows the server |
|
38 |
+to abort the connection immediately after receiving the first packet, rather |
|
39 |
+than performing an entire TLS handshake. Aborting the connection this early |
|
40 |
+greatly improves the DoS resilience and reduces attack surface against |
|
41 |
+malicious clients that have the ``tls-crypt`` or ``tls-auth`` key. This is |
|
42 |
+particularly relevant for large deployments (think lost key or disgruntled |
|
43 |
+employee) and VPN providers (clients are not trusted). |
|
44 |
+ |
|
45 |
+To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a |
|
46 |
+server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or |
|
47 |
+``tls-auth``. This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3 |
|
48 |
+opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the |
|
49 |
+current connection. |
|
50 |
+ |
|
51 |
+For an exact specification and more details, read the Implementation section. |
|
52 |
+ |
|
53 |
+ |
|
54 |
+Implementation |
|
55 |
+-------------- |
|
56 |
+ |
|
57 |
+When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or |
|
58 |
+tls-auth key previously): |
|
59 |
+ |
|
60 |
+1. Generate a tls-crypt-v2 server key using OpenVPN's ``--tls-crypt-v2-genkey server``. |
|
61 |
+ This key contains 2 512-bit keys, of which we use: |
|
62 |
+ |
|
63 |
+ * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke`` |
|
64 |
+ * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka`` |
|
65 |
+ |
|
66 |
+ This format is similar to the format for regular ``tls-crypt``/``tls-auth`` |
|
67 |
+ and data channel keys, which allows us to reuse code. |
|
68 |
+ |
|
69 |
+2. Add the tls-crypt-v2 server key to all server configs |
|
70 |
+ (``tls-crypt-v2 /path/to/server.key``) |
|
71 |
+ |
|
72 |
+ |
|
73 |
+When provisioning a client, create a client-specific tls-crypt key: |
|
74 |
+ |
|
75 |
+1. Generate 2048 bits client-specific key ``Kc`` using OpenVPN's ``--tls-crypt-v2-genkey client`` |
|
76 |
+ |
|
77 |
+2. Optionally generate metadata |
|
78 |
+ |
|
79 |
+ The first byte of the metadata determines the type. The initial |
|
80 |
+ implementation supports the following types: |
|
81 |
+ |
|
82 |
+ 0x00 (USER): User-defined free-form data. |
|
83 |
+ 0x01 (TIMESTAMP): 64-bit network order unix timestamp of key generation. |
|
84 |
+ |
|
85 |
+ The timestamp can be used to reject too-old tls-crypt-v2 client keys. |
|
86 |
+ |
|
87 |
+ User metadata could for example contain the users certificate serial, such |
|
88 |
+ that the incoming connection can be verified against a CRL. |
|
89 |
+ |
|
90 |
+ If no metadata is supplied during key generation, openvpn defaults to the |
|
91 |
+ TIMESTAMP metadata type. |
|
92 |
+ |
|
93 |
+3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant |
|
94 |
+ SIV construction we use for tls-crypt: |
|
95 |
+ |
|
96 |
+ ``len = len(WKc)`` (16 bit, network byte order) |
|
97 |
+ |
|
98 |
+ ``T = HMAC-SHA256(Ka, len || Kc || metadata)`` |
|
99 |
+ |
|
100 |
+ ``IV = 128 most significant bits of T`` |
|
101 |
+ |
|
102 |
+ ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len`` |
|
103 |
+ |
|
104 |
+ Note that the length of ``WKc`` can be computed before composing ``WKc``, |
|
105 |
+ because the length of each component is known (and AES-256-CTR does not add |
|
106 |
+ any padding). |
|
107 |
+ |
|
108 |
+4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a |
|
109 |
+ file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----`` |
|
110 |
+ and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``. (The PEM |
|
111 |
+ format is simple, and following PEM allows us to use the crypto lib function |
|
112 |
+ for en/decoding.) |
|
113 |
+ |
|
114 |
+5. Add the tls-crypt-v2 client key to the client config |
|
115 |
+ (``tls-crypt-v2 /path/to/client-specific.key``) |
|
116 |
+ |
|
117 |
+ |
|
118 |
+When setting up the openvpn connection: |
|
119 |
+ |
|
120 |
+1. The client reads the tls-crypt-v2 key from its config, and: |
|
121 |
+ |
|
122 |
+ 1. loads ``Kc`` as its tls-crypt key, |
|
123 |
+ 2. stores ``WKc`` in memory for sending to the server. |
|
124 |
+ |
|
125 |
+2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3 |
|
126 |
+ message, wraps it with tls-crypt using ``Kc`` as the key, and appends |
|
127 |
+ ``WKc``. (``WKc`` must not be encrypted, to prevent a chicken-and-egg |
|
128 |
+ problem.) |
|
129 |
+ |
|
130 |
+3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and |
|
131 |
+ |
|
132 |
+ 1. reads the WKc length field from the end of the message, and extracts WKc |
|
133 |
+ from the message |
|
134 |
+ 2. unwraps ``WKc`` |
|
135 |
+ 3. uses unwrapped ``Kc`` to verify the remaining |
|
136 |
+ P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication. |
|
137 |
+ |
|
138 |
+ The message is dropped and no error response is sent when either 3.1, 3.2 or |
|
139 |
+ 3.3 fails (DoS protection). |
|
140 |
+ |
|
141 |
+4. Server optionally checks metadata using a --tls-crypt-v2-verify script |
|
142 |
+ |
|
143 |
+ This allows early abort of connection, *before* we expose any of the |
|
144 |
+ notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the |
|
145 |
+ attack surface of the server. |
|
146 |
+ |
|
147 |
+ The metadata is checked *after* the OpenVPN three-way handshake has |
|
148 |
+ completed, to prevent DoS attacks. (That is, once the client has proved to |
|
149 |
+ the server that it possesses Kc, by authenticating a packet that contains the |
|
150 |
+ session ID picked by the server.) |
|
151 |
+ |
|
152 |
+ A server should not send back any error messages if metadata verification |
|
153 |
+ fails, to reduce attack surface and maximize DoS resilience. |
|
154 |
+ |
|
155 |
+6. Client and server use ``Kc`` for (un)wrapping any following control channel |
|
156 |
+ messages. |
|
157 |
+ |
|
158 |
+ |
|
159 |
+Considerations |
|
160 |
+-------------- |
|
161 |
+ |
|
162 |
+To allow for a smooth transition, the server implementation allows |
|
163 |
+``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``. |
|
164 |
+This specification does not allow simultaneously using ``tls-crypt-v2`` and |
|
165 |
+connections without any control channel wrapping, because that would break DoS |
|
166 |
+resilience. |
|
167 |
+ |
|
168 |
+WKc includes a length field, so we leave the option for future extension of the |
|
169 |
+P_CONTROL_HEAD_RESET_CLIENT_V3 message open. (E.g. add payload to the reset to |
|
170 |
+indicate low-level protocol features.) |
|
171 |
+ |
|
172 |
+``tls-crypt-v2`` uses fixed crypto algorithms, because: |
|
173 |
+ |
|
174 |
+ * The crypto is used before we can do any negotiation, so the algorithms have |
|
175 |
+ to be predefined. |
|
176 |
+ * The crypto primitives are chosen conservatively, making problems with these |
|
177 |
+ primitives unlikely. |
|
178 |
+ * Making anything configurable adds complexity, both in implementation and |
|
179 |
+ usage. We should not add any more complexity than is absolutely necessary. |
|
180 |
+ |
|
181 |
+Potential ``tls-crypt-v2`` risks: |
|
182 |
+ |
|
183 |
+ * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap) |
|
184 |
+ than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth). |
|
185 |
+ * Flexible metadata allow mistakes |
|
186 |
+ (So we should make it easy to do it right. Provide tooling to create client |
|
187 |
+ keys based on cert serial + CA fingerprint, provide script that uses CRL (if |
|
188 |
+ available) to drop revoked keys.) |