[Openvpn-devel,02/10] tls-crypt-v2: add specification to doc/

Message ID 1512734870-17133-3-git-send-email-steffan.karger@fox-it.com
State Superseded
Headers show
Series Client-specific tls-crypt keys (--tls-crypt-v2) | expand

Commit Message

Steffan Karger Dec. 8, 2017, 1:07 a.m. UTC
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>
---
 doc/tls-crypt-v2.txt | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)
 create mode 100644 doc/tls-crypt-v2.txt

Comments

Antonio Quartulli March 7, 2018, 8:34 p.m. UTC | #1
Hi,

On 08/12/17 20:07, Steffan Karger wrote:
> 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>
> ---
>  doc/tls-crypt-v2.txt | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 164 insertions(+)
>  create mode 100644 doc/tls-crypt-v2.txt
> 
> diff --git a/doc/tls-crypt-v2.txt b/doc/tls-crypt-v2.txt
> new file mode 100644
> index 0000000..578b2f9
> --- /dev/null
> +++ b/doc/tls-crypt-v2.txt
> @@ -0,0 +1,164 @@
> +Client-specific tls-crypt keys (--tls-crypt-v2)
> +===============================================
> +
> +This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN
> +to use client-specific ``--tls-crypt`` keys.
> +
> +Rationale
> +---------
> +
> +``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared
> +among all clients and servers in an OpenVPN deployment.  If any client or
> +server is compromised, the attacker will have access to this shared key, and it
> +will no longer provide any security.  To reduce the risk of loosing pre-shared

did you really mean "loosing"? or is it a misspelled "losing"?

> +keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique
> +tls-crypt key.  This allows large organisations and VPN providers to profit
> +from the same DoS and TLS stack protection that small deployments can already
> +achieve using ``tls-auth`` or ``tls-crypt``.
> +
> +Also, for ``tls-crypt``, even if all these peers succeed in keeping the key
> +secret, the key lifetime is limited to roughly 8000 years, divided by the
> +number of clients (see the ``--tls-crypt`` section of the man page).  Using
> +client-specific keys, we lift this lifetime requirement to roughly 8000 years
> +for each client key (which "Should Be Enough For Everybody (tm)").
> +
> +
> +Introduction
> +------------
> +
> +``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce
> +client-specific tls-crypt keys without introducing a lot of server-side state.
> +The client-specific key is encrypted using a server key.  The server key is the
> +same for all servers in a group.  When a client connects, it first sends the
> +encrypted key to the server, such that the server can decrypt the key and all
> +messages can thereafter be encrypted using the client-specific key.
> +
> +A wrapped (encrypted and authenticated) client-specific key can also contain
> +metadata.  The metadata is wrapped together with the key, and can be used to
> +allow servers to identify clients and/or key validity.  This allows the server
> +to abort the connection immediately after receiving the first packet, rather
> +than performing an entire TLS handshake.  Aborting the connection this early
> +greatly improves the DoS resilience and reduces attack service against
> +malicious clients that have the ``tls-crypt`` or ``tls-auth`` key.  This is
> +particularly relevant for large deployments (think lost key or disgruntled
> +employee) and VPN providers (clients are not trusted).
> +
> +To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a
> +server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or
> +``tls-auth``.  This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3
> +opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the
> +current connection.
> +
> +For an exact specification and more details, read the Implementation section.
> +
> +
> +Implementation
> +--------------
> +
> +When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or
> +tls-auth key previously):
> +
> +1. Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey``.  This key
> +   contains 4 512-bit keys, of which we use:
> +
> +   * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke``
> +   * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka``
> +
> +2. Add the tls-crypt-v2 server key to all server configs
> +   (``tls-crypt-v2 /path/to/server.key``)
> +
> +
> +When provisioning a client, create a client-specific tls-crypt key:
> +
> +1. Generate 2048 bits client-specific key ``Kc``
> +2. Optionally generate metadata
> +3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant
> +   SIV conruction we use for tls-crypt:
> +
> +   ``T = HMAC-SHA256(Ka, Kc || metadata)``
> +
> +   ``IV = 128 most significant bits of T``
> +
> +   ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata)``
> +
> +4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a
> +   file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----``
> +   and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``.  (The PEM
> +   format is simple, and following PEM allows us to use the crypto lib function
> +   for en/decoding.)
> +5. Add the tls-crypt-v2 client key to the client config
> +   (``tls-crypt-v2 /path/to/client-specific.key``)

For the server key you've said "using OpenVPN's ``--genkey``", while for
the client key you haven't mentioned the ``--tls-crypt-v2-genkey``
introduced in patch 3/10. Any reason for that?

> +
> +
> +When setting up the openvpn connection:
> +
> +1. The client reads the tls-crypt-v2 key from its config, and:
> +
> +   1. loads ``Kc`` as its tls-crypt key,
> +   2. stores ``WKc`` in memory for sending to the server.
> +
> +2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3
> +   message without payload, wraps it with tls-crypt using ``Kc`` as the key,
> +   and appends ``WKc``.  (``WKc`` must not be encrypted, to prevent a
> +   chicken-and-egg problem.)
> +
> +3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and
> +
> +   a. unwraps ``WKc`` and strips ``WKc`` from the message.
> +   b. uses unwrapped ``Kc`` to verify the remaining
> +      P_CONTROL_HARD_RESET_CLIENT_V3 message's authentication.
> +
> +   The message is dropped and no error response is sent when either a or b
> +   fails (DoS protection).
> +
> +4. Server optionally checks metadata using a --tls-crypt-v2-verify script
> +
> +   Metadata could for example contain the users certificate serial, such that
> +   the incoming connection can be verified against a CRL, or a notAfter
> +   timestamp that limits the key's validity period.
> +
> +   This allows early abort of connection, *before* we expose any of the
> +   notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the
> +   attack surface of the server.
> +
> +   The metadata is checked *after* the OpenVPN three-way handshake has
> +   completed, to prevent DoS attacks.  (That is, once the client has proved to
> +   the server that it possesses Kc, by authenticating a packet that contains the
> +   session ID picked by the server.)

just a thought here: the metadata is actually created by the
server/provider and it is authenticated/encrypted with the server key.

Isn't this enough to ensure that its content is not malicious and thus
allow the server to parse it right after having received the
HARD_RESET_V3 (instead of performing a "three-way handshake" first)?

> +
> +   RFC: should the server send a 'key rejected' message if the key is e.g.
> +   revoked or expired?  That allows for better client-side error reporting, but
> +   also reduces the DoS resilience.
> +
> +6. Client and server use ``Kc`` for (un)wrapping any following control channel
> +   messages.
> +
> +
> +Considerations
> +--------------
> +
> +To allow for a smooth transition, the server implementation allows
> +``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``.
> +This specification does not allow simultaneously using ``tls-crypt-v2`` and
> +connections without any control channel wrapping, because that would break DoS
> +resilience.  RFC: should we add an option along the lines of
> +--tls-crypt-v2-allow-insecure-fallback to allow admins to enable this anyway?
> +It might help with transitioning.

good question, but I think people are already fighting with this now
while transitioning to tls-crypt, thus I would vote for not introducing
more code complexity.

> +
> +``tls-crypt-v2`` uses fixed crypto algorithms, because:
> +
> + * The crypto is used before we can do any negotiation, so the algorithms have
> +   to be predefined.
> + * The crypto primitives are chosen conservatively, making problems with these
> +   primitives unlikely.
> + * Making anything configurable adds complexity, both in implementation and
> +   usage.  We should not add anymore complexity than is absolutely necessary.
> +
> +Potential ``tls-crypt-v2`` risks:
> +
> + * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap)
> +   than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth).
> + * Flexible metadata allow mistakes
> +   (So we should make it easy to do it right.  Provide tooling to create client
> +   keys based on cert serial + CA fingerprint, provide script that uses CRL (if
> +   available) to drop revoked keys.)
> 


The rest looks good! Thanks for this exhaustive description!

Cheers,

Patch

diff --git a/doc/tls-crypt-v2.txt b/doc/tls-crypt-v2.txt
new file mode 100644
index 0000000..578b2f9
--- /dev/null
+++ b/doc/tls-crypt-v2.txt
@@ -0,0 +1,164 @@ 
+Client-specific tls-crypt keys (--tls-crypt-v2)
+===============================================
+
+This document describes the ``--tls-crypt-v2`` option, which enables OpenVPN
+to use client-specific ``--tls-crypt`` keys.
+
+Rationale
+---------
+
+``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, which is shared
+among all clients and servers in an OpenVPN deployment.  If any client or
+server is compromised, the attacker will have access to this shared key, and it
+will no longer provide any security.  To reduce the risk of loosing pre-shared
+keys, ``tls-crypt-v2`` adds the ability to supply each client with a unique
+tls-crypt key.  This allows large organisations and VPN providers to profit
+from the same DoS and TLS stack protection that small deployments can already
+achieve using ``tls-auth`` or ``tls-crypt``.
+
+Also, for ``tls-crypt``, even if all these peers succeed in keeping the key
+secret, the key lifetime is limited to roughly 8000 years, divided by the
+number of clients (see the ``--tls-crypt`` section of the man page).  Using
+client-specific keys, we lift this lifetime requirement to roughly 8000 years
+for each client key (which "Should Be Enough For Everybody (tm)").
+
+
+Introduction
+------------
+
+``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce
+client-specific tls-crypt keys without introducing a lot of server-side state.
+The client-specific key is encrypted using a server key.  The server key is the
+same for all servers in a group.  When a client connects, it first sends the
+encrypted key to the server, such that the server can decrypt the key and all
+messages can thereafter be encrypted using the client-specific key.
+
+A wrapped (encrypted and authenticated) client-specific key can also contain
+metadata.  The metadata is wrapped together with the key, and can be used to
+allow servers to identify clients and/or key validity.  This allows the server
+to abort the connection immediately after receiving the first packet, rather
+than performing an entire TLS handshake.  Aborting the connection this early
+greatly improves the DoS resilience and reduces attack service against
+malicious clients that have the ``tls-crypt`` or ``tls-auth`` key.  This is
+particularly relevant for large deployments (think lost key or disgruntled
+employee) and VPN providers (clients are not trusted).
+
+To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a
+server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or
+``tls-auth``.  This is achieved by introducing a P_CONTROL_HARD_RESET_CLIENT_V3
+opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the
+current connection.
+
+For an exact specification and more details, read the Implementation section.
+
+
+Implementation
+--------------
+
+When setting up a tls-crypt-v2 group (similar to generating a tls-crypt or
+tls-auth key previously):
+
+1. Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey``.  This key
+   contains 4 512-bit keys, of which we use:
+
+   * the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke``
+   * the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka``
+
+2. Add the tls-crypt-v2 server key to all server configs
+   (``tls-crypt-v2 /path/to/server.key``)
+
+
+When provisioning a client, create a client-specific tls-crypt key:
+
+1. Generate 2048 bits client-specific key ``Kc``
+2. Optionally generate metadata
+3. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant
+   SIV conruction we use for tls-crypt:
+
+   ``T = HMAC-SHA256(Ka, Kc || metadata)``
+
+   ``IV = 128 most significant bits of T``
+
+   ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata)``
+
+4. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a
+   file, using the header ``-----BEGIN OpenVPN tls-crypt-v2 client key-----``
+   and the footer ``-----END OpenVPN tls-crypt-v2 client key-----``.  (The PEM
+   format is simple, and following PEM allows us to use the crypto lib function
+   for en/decoding.)
+5. Add the tls-crypt-v2 client key to the client config
+   (``tls-crypt-v2 /path/to/client-specific.key``)
+
+
+When setting up the openvpn connection:
+
+1. The client reads the tls-crypt-v2 key from its config, and:
+
+   1. loads ``Kc`` as its tls-crypt key,
+   2. stores ``WKc`` in memory for sending to the server.
+
+2. To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3
+   message without payload, wraps it with tls-crypt using ``Kc`` as the key,
+   and appends ``WKc``.  (``WKc`` must not be encrypted, to prevent a
+   chicken-and-egg problem.)
+
+3. The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and
+
+   a. unwraps ``WKc`` and strips ``WKc`` from the message.
+   b. uses unwrapped ``Kc`` to verify the remaining
+      P_CONTROL_HARD_RESET_CLIENT_V3 message's authentication.
+
+   The message is dropped and no error response is sent when either a or b
+   fails (DoS protection).
+
+4. Server optionally checks metadata using a --tls-crypt-v2-verify script
+
+   Metadata could for example contain the users certificate serial, such that
+   the incoming connection can be verified against a CRL, or a notAfter
+   timestamp that limits the key's validity period.
+
+   This allows early abort of connection, *before* we expose any of the
+   notoriously dangerous TLS, X.509 and ASN.1 parsers and thereby reduces the
+   attack surface of the server.
+
+   The metadata is checked *after* the OpenVPN three-way handshake has
+   completed, to prevent DoS attacks.  (That is, once the client has proved to
+   the server that it possesses Kc, by authenticating a packet that contains the
+   session ID picked by the server.)
+
+   RFC: should the server send a 'key rejected' message if the key is e.g.
+   revoked or expired?  That allows for better client-side error reporting, but
+   also reduces the DoS resilience.
+
+6. Client and server use ``Kc`` for (un)wrapping any following control channel
+   messages.
+
+
+Considerations
+--------------
+
+To allow for a smooth transition, the server implementation allows
+``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``.
+This specification does not allow simultaneously using ``tls-crypt-v2`` and
+connections without any control channel wrapping, because that would break DoS
+resilience.  RFC: should we add an option along the lines of
+--tls-crypt-v2-allow-insecure-fallback to allow admins to enable this anyway?
+It might help with transitioning.
+
+``tls-crypt-v2`` uses fixed crypto algorithms, because:
+
+ * The crypto is used before we can do any negotiation, so the algorithms have
+   to be predefined.
+ * The crypto primitives are chosen conservatively, making problems with these
+   primitives unlikely.
+ * Making anything configurable adds complexity, both in implementation and
+   usage.  We should not add anymore complexity than is absolutely necessary.
+
+Potential ``tls-crypt-v2`` risks:
+
+ * Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap)
+   than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth).
+ * Flexible metadata allow mistakes
+   (So we should make it easy to do it right.  Provide tooling to create client
+   keys based on cert serial + CA fingerprint, provide script that uses CRL (if
+   available) to drop revoked keys.)