From c6e24fa3e16c32f9b427e360fd07102f613aa5c6 Mon Sep 17 00:00:00 2001 From: Steffan Karger Date: Tue, 15 Nov 2016 14:29:46 +0100 Subject: Add control channel encryption (--tls-crypt) This adds a --tls-crypt option, which uses a pre-shared static key (like the --tls-auth key) to encrypt control channel packets. Encrypting control channel packets has three main advantages: * It provides more privacy by hiding the certificate used for the TLS connection. * It is harder to identify OpenVPN traffic as such. * It provides "poor-man's" post-quantum security, against attackers who will never know the pre-shared key (i.e. no forward secrecy). Control channel packet encryption --------------------------------- We propose to use the following encryption method, based on the SIV construction [0], to achieve nonce misuse-resistant authenticated encryption: msg = control channel plaintext header = opcode (1 byte) || session_id (8 bytes) || packet_id (8 bytes) Ka = authentication key (256 bits) Ke = encryption key (256 bits) (Ka and Ke are pre-shared keys, like with --tls-auth) auth_tag = HMAC-SHA256(Ka, header || msg) IV = 128 most-significant bits of auth_tag ciph = AES256-CTR(Ke, IV, msg) output = Header || Tag || Ciph This boils down to the following on-the-wire packet format: -opcode- || -session_id- || -packet_id- || auth_tag || * payload * Where - XXX - means authenticated, and * XXX * means authenticated and encrypted. Which is very similar to the current tls-auth packet format, and has the same overhead as "--tls-auth" with "--auth SHA256". The use of a nonce misuse-resistant authenticated encryption scheme allows us to worry less about the risks of nonce collisions. This is important, because in contrast with the data channel in TLS mode, we will not be able to rotate tls-crypt keys often or fully guarantee nonce uniqueness. For non misuse-resistant modes such as GCM [1], [2], the data channel in TLS mode only has to ensure that the packet counter never rolls over, while tls-crypt would have to provide nonce uniqueness over all control channel packets sent by all clients, for the lifetime of the tls-crypt key. Unlike with tls-auth, no --key-direction has to be specified for tls-crypt. TLS servers always use key direction 1, and TLS clients always use key direction 2, which means that client->server traffic and server->client traffic always use different keys, without requiring configuration. Using fixed, secure, encryption and authentication algorithms makes both implementation and configuration easier. If we ever want to, we can extend this to support other crypto primitives. Since tls-crypt should provide privacy as well as DoS protection, these should not be made negotiable. Security considerations: ------------------------ tls-crypt is a best-effort mechanism that aims to provide as much privacy and security as possible, while staying as simple as possible. The following are some security considerations for this scheme. 1. The same tls-crypt key is potentially shared by a lot of peers, so it is quite likely to get compromised. Once an attacker acquires the tls-crypt key, this mechanism no longer provides any security against the attacker. 2. Since many peers potentially use the tls-crypt key for a long time, a lot of data might be encrypted under the tls-crypt key. This leads to two potential problems: * The "opcode || session id || packet id" combination might collide. This might happen in larger setups, because the session id contains just 64 bits or random. Using the uniqueness requirement from the GCM spec [3] (a collision probability of less than 2^(-32)), uniqueness is achieved when using the tls-crypt key for at most 2^16 (65536) connections per process start. (The packet id includes the daemon start time in the packet ID, which should be different after stopping and (re)starting OpenPVN.) And if a collision happens, an attacker can *only* learn whether colliding packets contain the same plaintext. Attackers will not be able to learn anything else about the plaintext (unless the attacker knows the plaintext of one of these packets, of course). Since the impact is limited, I consider this an acceptable remaining risk. * The IVs used in encryption might collide. When two IVs collide, an attacker can learn the xor of the two plaintexts by xorring the ciphertexts. This is a serious loss of confidentiality. The IVs are 128-bit, so when HMAC-SHA256 is a secure PRF (an assumption that must also hold for TLS), and we use the same uniqueness requirement from [3], this limits the total amount of control channel messages for all peers in the setup to 2^48. Assuming a large setup of 2^16 (65536) clients, and a (conservative) number of 2^16 control channel packets per connection on average, this means that clients may set up 2^16 connections on average. I think these numbers are reasonable. (I have a follow-up proposal to use client-specific tls-auth/tls-crypt keys to partially mitigate these issues, but let's tackle this patch first.) References: ----------- [0] Rogaway & Shrimpton, A Provable-Security Treatment of the Key-Wrap Problem, 2006 (https://www.iacr.org/archive/eurocrypt2006/40040377/40040377.pdf) [1] Ferguson, Authentication weaknesses in GCM, 2005 (http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/comments/CWC-GCM/Ferg uson2.pdf) [2] Joux, Authentication Failures in NIST version of GCM, 2006 (http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/comments/800-38_Serie s-Drafts/GCM/Joux_comments.pdf) [3] Dworking, Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC, 2007 (http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf) Patch history: -------------- v2 - processed Arne's review comments: * Error out early with a clear error message when AES-256-CTR or HMAC-SHA-256 are not supported by the crypto library. * Clarify that cipher_ctx_reset() sets the IV. v3 - actually add error messages promised in v2... Signed-off-by: Steffan Karger Acked-by: Arne Schwabe Message-Id: <1479216586-20078-1-git-send-email-steffan.karger@fox-it.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg13069.html Signed-off-by: Gert Doering --- src/openvpn/openvpn.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/openvpn/openvpn.h') diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index 4366a42..fa5cc1d 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -65,9 +65,9 @@ struct key_schedule /* our global SSL context */ struct tls_root_ctx ssl_ctx; - /* optional authentication HMAC key for TLS control channel */ + /* optional TLS control channel wrapping */ struct key_type tls_auth_key_type; - struct key_ctx_bi tls_auth_key; + struct key_ctx_bi tls_wrap_key; #else /* ENABLE_CRYPTO */ int dummy; #endif /* ENABLE_CRYPTO */ -- cgit v1.1