Browse code

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 <steffan.karger@fox-it.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
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 <gert@greenie.muc.de>

Steffan Karger authored on 2016/11/15 22:29:46
Showing 14 changed files
... ...
@@ -111,6 +111,11 @@ AIX platform support
111 111
 	AIX platform support has been added. The support only includes tap
112 112
     devices since AIX does not provide tun interface.
113 113
 
114
+Control channel encryption (``--tls-crypt``)
115
+    Use a pre-shared static key (like the ``--tls-auth`` key) to encrypt control
116
+    channel packets.  Provides more privacy, some obfuscation and poor-man's
117
+    post-quantum security.
118
+
114 119
 
115 120
 Deprecated features
116 121
 -------------------
... ...
@@ -3471,8 +3471,10 @@ DoS scenario, legitimate connections might also be refused.
3471 3471
 For the best protection against DoS attacks in server mode,
3472 3472
 use
3473 3473
 .B \-\-proto udp
3474
-and
3475
-.B \-\-tls\-auth.
3474
+and either
3475
+.B \-\-tls\-auth
3476
+or
3477
+.B \-\-tls\-crypt\fR.
3476 3478
 .\"*********************************************************
3477 3479
 .TP
3478 3480
 .B \-\-learn\-address cmd
... ...
@@ -4938,8 +4940,8 @@ Exit on TLS negotiation failure.
4938 4938
 .\"*********************************************************
4939 4939
 .TP
4940 4940
 .B \-\-tls\-auth file [direction]
4941
-Add an additional layer of HMAC authentication on top of the TLS
4942
-control channel to protect against DoS attacks.
4941
+Add an additional layer of HMAC authentication on top of the TLS control channel
4942
+to mitigate DoS attacks and attacks on the TLS stack.
4943 4943
 
4944 4944
 In a nutshell,
4945 4945
 .B \-\-tls\-auth
... ...
@@ -5010,12 +5012,39 @@ option which will keep OpenVPN's replay protection state
5010 5010
 in a file so that it is not lost across restarts.
5011 5011
 
5012 5012
 It should be emphasized that this feature is optional and that the
5013
-passphrase/key file used with
5013
+key file used with
5014 5014
 .B \-\-tls\-auth
5015 5015
 gives a peer nothing more than the power to initiate a TLS
5016 5016
 handshake.  It is not used to encrypt or authenticate any tunnel data.
5017 5017
 .\"*********************************************************
5018 5018
 .TP
5019
+.B \-\-tls\-crypt keyfile
5020
+
5021
+Encrypt and authenticate all control channel packets with the key from
5022
+.B keyfile.
5023
+(See
5024
+.B \-\-tls\-auth
5025
+for more background.)
5026
+
5027
+Encrypting (and authenticating) control channel packets:
5028
+.RS
5029
+.IP \[bu] 2
5030
+provides more privacy by hiding the certificate used for the TLS connection,
5031
+.IP \[bu]
5032
+makes it harder to identify OpenVPN traffic as such,
5033
+.IP \[bu]
5034
+provides "poor-man's" post-quantum security, against attackers who will never
5035
+know the pre-shared key (i.e. no forward secrecy).
5036
+.RE
5037
+
5038
+.IP
5039
+In contrast to
5040
+.B \-\-tls\-auth\fR,
5041
+.B \-\-tls\-crypt
5042
+does *not* require the user to set
5043
+.B \-\-key\-direction\fR.
5044
+.\"*********************************************************
5045
+.TP
5019 5046
 .B \-\-askpass [file]
5020 5047
 Get certificate password from console or
5021 5048
 .B file
... ...
@@ -113,6 +113,7 @@ openvpn_SOURCES = \
113 113
 	ssl_verify_mbedtls.c ssl_verify_mbedtls.h \
114 114
 	status.c status.h \
115 115
 	syshead.h \
116
+	tls_crypt.c tls_crypt.h \
116 117
 	tun.c tun.h \
117 118
 	win32.h win32.c \
118 119
 	cryptoapi.h cryptoapi.c
... ...
@@ -6,7 +6,7 @@
6 6
  *             packet compression.
7 7
  *
8 8
  *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9
- *  Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
9
+ *  Copyright (C) 2010-2016 Fox Crypto B.V. <openvpn@fox-it.com>
10 10
  *
11 11
  *  This program is free software; you can redistribute it and/or modify
12 12
  *  it under the terms of the GNU General Public License version 2
... ...
@@ -63,9 +63,6 @@
63 63
  * happen unless the frame parameters are wrong.
64 64
  */
65 65
 
66
-#define CRYPT_ERROR(format) \
67
-  do { msg (D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false)
68
-
69 66
 static void
70 67
 openvpn_encrypt_aead (struct buffer *buf, struct buffer work,
71 68
 	 struct crypto_options *opt) {
... ...
@@ -326,17 +323,7 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,
326 326
     }
327 327
 }
328 328
 
329
-/**
330
- * Check packet ID for replay, and perform replay administration.
331
- *
332
- * @param opt	Crypto options for this packet, contains replay state.
333
- * @param pin	Packet ID read from packet.
334
- * @param error_prefix	Prefix to use when printing error messages.
335
- * @param gc	Garbage collector to use.
336
- *
337
- * @return true if packet ID is validated to be not a replay, false otherwise.
338
- */
339
-static bool crypto_check_replay(struct crypto_options *opt,
329
+bool crypto_check_replay(struct crypto_options *opt,
340 330
     const struct packet_id_net *pin, const char *error_prefix,
341 331
     struct gc_arena *gc) {
342 332
   bool ret = false;
... ...
@@ -266,6 +266,9 @@ struct crypto_options
266 266
                                  *   security operation functions. */
267 267
 };
268 268
 
269
+#define CRYPT_ERROR(format) \
270
+  do { msg (D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false)
271
+
269 272
 /**
270 273
  * Minimal IV length for AEAD mode ciphers (in bytes):
271 274
  * 4-byte packet id + 8 bytes implicit IV.
... ...
@@ -397,6 +400,21 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,
397 397
 
398 398
 /** @} name Functions for performing security operations on data channel packets */
399 399
 
400
+/**
401
+ * Check packet ID for replay, and perform replay administration.
402
+ *
403
+ * @param opt	Crypto options for this packet, contains replay state.
404
+ * @param pin	Packet ID read from packet.
405
+ * @param error_prefix	Prefix to use when printing error messages.
406
+ * @param gc	Garbage collector to use.
407
+ *
408
+ * @return true if packet ID is validated to be not a replay, false otherwise.
409
+ */
410
+bool crypto_check_replay(struct crypto_options *opt,
411
+    const struct packet_id_net *pin, const char *error_prefix,
412
+    struct gc_arena *gc);
413
+
414
+
400 415
 /** Calculate crypto overhead and adjust frame to account for that */
401 416
 void crypto_adjust_frame_parameters(struct frame *frame,
402 417
 				    const struct key_type* kt,
... ...
@@ -44,6 +44,7 @@
44 44
 #include "ping.h"
45 45
 #include "mstats.h"
46 46
 #include "ssl_verify.h"
47
+#include "tls_crypt.h"
47 48
 #include "forward-inline.h"
48 49
 
49 50
 #include "memdbg.h"
... ...
@@ -2078,7 +2079,7 @@ key_schedule_free (struct key_schedule *ks, bool free_ssl_ctx)
2078 2078
   if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx)
2079 2079
     {
2080 2080
       tls_ctx_free (&ks->ssl_ctx);
2081
-      free_key_ctx_bi (&ks->tls_auth_key);
2081
+      free_key_ctx_bi (&ks->tls_wrap_key);
2082 2082
     }
2083 2083
 #endif /* ENABLE_CRYPTO */
2084 2084
   CLEAR (*ks);
... ...
@@ -2232,11 +2233,17 @@ do_init_crypto_tls_c1 (struct context *c)
2232 2232
 	    }
2233 2233
 
2234 2234
 	  crypto_read_openvpn_key (&c->c1.ks.tls_auth_key_type,
2235
-	      &c->c1.ks.tls_auth_key, options->tls_auth_file,
2235
+	      &c->c1.ks.tls_wrap_key, options->tls_auth_file,
2236 2236
 	      options->tls_auth_file_inline, options->key_direction,
2237 2237
 	      "Control Channel Authentication", "tls-auth");
2238 2238
 	}
2239 2239
 
2240
+      /* TLS handshake encryption+authentication (--tls-crypt) */
2241
+      if (options->tls_crypt_file) {
2242
+	  tls_crypt_init_key (&c->c1.ks.tls_wrap_key, options->tls_crypt_file,
2243
+	      options->tls_crypt_inline, options->tls_server);
2244
+      }
2245
+
2240 2246
       c->c1.ciphername = options->ciphername;
2241 2247
       c->c1.authname = options->authname;
2242 2248
       c->c1.keysize = options->keysize;
... ...
@@ -2421,14 +2428,25 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2421 2421
   /* TLS handshake authentication (--tls-auth) */
2422 2422
   if (options->tls_auth_file)
2423 2423
     {
2424
-      to.tls_auth.key_ctx_bi = c->c1.ks.tls_auth_key;
2425
-      to.tls_auth.pid_persist = &c->c1.pid_persist;
2426
-      to.tls_auth.flags |= CO_PACKET_ID_LONG_FORM;
2424
+      to.tls_wrap.mode = TLS_WRAP_AUTH;
2425
+      to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key;
2426
+      to.tls_wrap.opt.pid_persist = &c->c1.pid_persist;
2427
+      to.tls_wrap.opt.flags |= CO_PACKET_ID_LONG_FORM;
2427 2428
       crypto_adjust_frame_parameters (&to.frame,
2428 2429
 				      &c->c1.ks.tls_auth_key_type,
2429 2430
 				      false, true, true);
2430 2431
     }
2431 2432
 
2433
+  /* TLS handshake encryption (--tls-crypt) */
2434
+  if (options->tls_crypt_file)
2435
+    {
2436
+      to.tls_wrap.mode = TLS_WRAP_CRYPT;
2437
+      to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key;
2438
+      to.tls_wrap.opt.pid_persist = &c->c1.pid_persist;
2439
+      to.tls_wrap.opt.flags |= CO_PACKET_ID_LONG_FORM;
2440
+      tls_crypt_adjust_frame_parameters (&to.frame);
2441
+    }
2442
+
2432 2443
   /* If we are running over TCP, allow for
2433 2444
      length prefix */
2434 2445
   socket_adjust_frame_parameters (&to.frame, options->ce.proto);
... ...
@@ -3792,7 +3810,7 @@ inherit_context_child (struct context *dest,
3792 3792
   dest->c1.ks.key_type = src->c1.ks.key_type;
3793 3793
   /* inherit SSL context */
3794 3794
   dest->c1.ks.ssl_ctx = src->c1.ks.ssl_ctx;
3795
-  dest->c1.ks.tls_auth_key = src->c1.ks.tls_auth_key;
3795
+  dest->c1.ks.tls_wrap_key = src->c1.ks.tls_wrap_key;
3796 3796
   dest->c1.ks.tls_auth_key_type = src->c1.ks.tls_auth_key_type;
3797 3797
   /* inherit pre-NCP ciphers */
3798 3798
   dest->c1.ciphername = src->c1.ciphername;
... ...
@@ -65,9 +65,9 @@ struct key_schedule
65 65
   /* our global SSL context */
66 66
   struct tls_root_ctx ssl_ctx;
67 67
 
68
-  /* optional authentication HMAC key for TLS control channel */
68
+  /* optional TLS control channel wrapping */
69 69
   struct key_type tls_auth_key_type;
70
-  struct key_ctx_bi tls_auth_key;
70
+  struct key_ctx_bi tls_wrap_key;
71 71
 #else				/* ENABLE_CRYPTO */
72 72
   int dummy;
73 73
 #endif				/* ENABLE_CRYPTO */
... ...
@@ -611,10 +611,17 @@ static const char usage_message[] =
611 611
   "--single-session: Allow only one session (reset state on restart).\n"
612 612
   "--tls-exit      : Exit on TLS negotiation failure.\n"
613 613
   "--tls-auth f [d]: Add an additional layer of authentication on top of the TLS\n"
614
-  "                  control channel to protect against DoS attacks.\n"
615
-  "                  f (required) is a shared-secret passphrase file.\n"
614
+  "                  control channel to protect against attacks on the TLS stack\n"
615
+  "                  and DoS attacks.\n"
616
+  "                  f (required) is a shared-secret key file.\n"
616 617
   "                  The optional d parameter controls key directionality,\n"
617 618
   "                  see --secret option for more info.\n"
619
+  "--tls-crypt key : Add an additional layer of authenticated encryption on top\n"
620
+  "                  of the TLS control channel to hide the TLS certificate,\n"
621
+  "                  provide basic post-quantum security and protect against\n"
622
+  "                  attacks on the TLS stack and DoS attacks.\n"
623
+  "                  key (required) provides the pre-shared key file.\n"
624
+  "                  see --secret option for more info.\n"
618 625
   "--askpass [file]: Get PEM password from controlling tty before we daemonize.\n"
619 626
   "--auth-nocache  : Don't cache --askpass or --auth-user-pass passwords.\n"
620 627
   "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n"
... ...
@@ -1710,6 +1717,7 @@ show_settings (const struct options *o)
1710 1710
   SHOW_BOOL (tls_exit);
1711 1711
 
1712 1712
   SHOW_STR (tls_auth_file);
1713
+  SHOW_STR (tls_crypt_file);
1713 1714
 #endif /* ENABLE_CRYPTO */
1714 1715
 
1715 1716
 #ifdef ENABLE_PKCS11
... ...
@@ -2384,6 +2392,10 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2384 2384
 	      notnull (options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)");
2385 2385
 	    }
2386 2386
 	}
2387
+    if (options->tls_auth_file && options->tls_crypt_file)
2388
+      {
2389
+        msg (M_USAGE, "--tls-auth and --tls-crypt are mutually exclusive");
2390
+      }
2387 2391
     }
2388 2392
   else
2389 2393
     {
... ...
@@ -2415,6 +2427,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2415 2415
       MUST_BE_UNDEF (handshake_window);
2416 2416
       MUST_BE_UNDEF (transition_window);
2417 2417
       MUST_BE_UNDEF (tls_auth_file);
2418
+      MUST_BE_UNDEF (tls_crypt_file);
2418 2419
       MUST_BE_UNDEF (single_session);
2419 2420
 #ifdef ENABLE_PUSH_PEER_INFO
2420 2421
       MUST_BE_UNDEF (push_peer_info);
... ...
@@ -2880,6 +2893,8 @@ options_postprocess_filechecks (struct options *options)
2880 2880
   errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
2881 2881
 			     options->tls_auth_file, R_OK, "--tls-auth");
2882 2882
   errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
2883
+			     options->tls_crypt_file, R_OK, "--tls-crypt");
2884
+  errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE,
2883 2885
 			     options->shared_secret_file, R_OK, "--secret");
2884 2886
   errs |= check_file_access (CHKACC_DIRPATH|CHKACC_FILEXSTWR,
2885 2887
 			     options->packet_id_file, R_OK|W_OK, "--replay-persist");
... ...
@@ -3220,6 +3235,9 @@ options_string (const struct options *o,
3220 3220
       {
3221 3221
 	if (o->tls_auth_file)
3222 3222
 	  buf_printf (&out, ",tls-auth");
3223
+	/* Not adding tls-crypt here, because we won't reach this code if
3224
+	 * tls-auth/tls-crypt does not match.  Removing tls-auth here would
3225
+	 * break stuff, so leaving that in place. */
3223 3226
 
3224 3227
 	if (o->key_method > 1)
3225 3228
 	  buf_printf (&out, ",key-method %d", o->key_method);
... ...
@@ -7242,6 +7260,15 @@ add_option (struct options *options,
7242 7242
 	}
7243 7243
       options->tls_auth_file = p[1];
7244 7244
     }
7245
+  else if (streq (p[0], "tls-crypt") && p[1] && !p[3])
7246
+    {
7247
+      VERIFY_PERMISSION (OPT_P_GENERAL);
7248
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
7249
+	{
7250
+	  options->tls_crypt_inline = p[2];
7251
+	}
7252
+      options->tls_crypt_file = p[1];
7253
+    }
7245 7254
   else if (streq (p[0], "key-method") && p[1] && !p[2])
7246 7255
     {
7247 7256
       int key_method;
... ...
@@ -558,10 +558,14 @@ struct options
558 558
   /* Old key allowed to live n seconds after new key goes active */
559 559
   int transition_window;
560 560
 
561
-  /* Special authentication MAC for TLS control channel */
562
-  const char *tls_auth_file;		/* shared secret */
561
+  /* Shared secret used for TLS control channel authentication */
562
+  const char *tls_auth_file;
563 563
   const char *tls_auth_file_inline;
564 564
 
565
+  /* Shared secret used for TLS control channel authenticated encryption */
566
+  const char *tls_crypt_file;
567
+  const char *tls_crypt_inline;
568
+
565 569
   /* Allow only one session */
566 570
   bool single_session;
567 571
 
... ...
@@ -57,6 +57,7 @@
57 57
 #include "gremlin.h"
58 58
 #include "pkcs11.h"
59 59
 #include "route.h"
60
+#include "tls_crypt.h"
60 61
 
61 62
 #include "ssl.h"
62 63
 #include "ssl_verify.h"
... ...
@@ -971,16 +972,18 @@ tls_session_init (struct tls_multi *multi, struct tls_session *session)
971 971
     }
972 972
 
973 973
   /* Initialize control channel authentication parameters */
974
-  session->tls_auth = session->opt->tls_auth;
974
+  session->tls_wrap = session->opt->tls_wrap;
975
+  session->tls_wrap.work = alloc_buf (TLS_CHANNEL_BUF_SIZE);
975 976
 
976 977
   /* initialize packet ID replay window for --tls-auth */
977
-  packet_id_init (&session->tls_auth.packet_id,
978
+  packet_id_init (&session->tls_wrap.opt.packet_id,
978 979
 		  session->opt->replay_window,
979 980
 		  session->opt->replay_time,
980
-		  "TLS_AUTH", session->key_id);
981
+		  "TLS_WRAP", session->key_id);
981 982
 
982 983
   /* load most recent packet-id to replay protect on --tls-auth */
983
-  packet_id_persist_load_obj (session->tls_auth.pid_persist, &session->tls_auth.packet_id);
984
+  packet_id_persist_load_obj (session->tls_wrap.opt.pid_persist,
985
+      &session->tls_wrap.opt.packet_id);
984 986
 
985 987
   key_state_init (session, &session->key[KS_PRIMARY]);
986 988
 
... ...
@@ -1007,8 +1010,10 @@ tls_session_free (struct tls_session *session, bool clear)
1007 1007
 {
1008 1008
   int i;
1009 1009
 
1010
-  if (packet_id_initialized(&session->tls_auth.packet_id))
1011
-    packet_id_free (&session->tls_auth.packet_id);
1010
+  if (packet_id_initialized(&session->tls_wrap.opt.packet_id))
1011
+    packet_id_free (&session->tls_wrap.opt.packet_id);
1012
+
1013
+  free_buf (&session->tls_wrap.work);
1012 1014
 
1013 1015
   for (i = 0; i < KS_SIZE; ++i)
1014 1016
     key_state_free (&session->key[i], false);
... ...
@@ -1140,9 +1145,14 @@ tls_auth_standalone_init (struct tls_options *tls_options,
1140 1140
 
1141 1141
   ALLOC_OBJ_CLEAR_GC (tas, struct tls_auth_standalone, gc);
1142 1142
 
1143
-  /* set up pointer to HMAC object for TLS packet authentication */
1144
-  tas->tls_auth_options.key_ctx_bi = tls_options->tls_auth.key_ctx_bi;
1145
-  tas->tls_auth_options.flags |= CO_PACKET_ID_LONG_FORM;
1143
+  tas->tls_wrap = tls_options->tls_wrap;
1144
+
1145
+  /*
1146
+   * Standalone tls-auth is in read-only mode with respect to TLS
1147
+   * control channel state.  After we build a new client instance
1148
+   * object, we will process this session-initiating packet for real.
1149
+   */
1150
+  tas->tls_wrap.opt.flags |= CO_IGNORE_PACKET_ID;
1146 1151
 
1147 1152
   /* get initial frame parms, still need to finalize */
1148 1153
   tas->frame = tls_options->frame;
... ...
@@ -1289,20 +1299,34 @@ write_control_auth (struct tls_session *session,
1289 1289
 		    int max_ack,
1290 1290
 		    bool prepend_ack)
1291 1291
 {
1292
-  uint8_t *header;
1292
+  uint8_t header = ks->key_id | (opcode << P_OPCODE_SHIFT);
1293 1293
   struct buffer null = clear_buf ();
1294 1294
 
1295 1295
   ASSERT (link_socket_actual_defined (&ks->remote_addr));
1296 1296
   ASSERT (reliable_ack_write
1297 1297
 	  (ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack));
1298
-  ASSERT (session_id_write_prepend (&session->session_id, buf));
1299
-  ASSERT (header = buf_prepend (buf, 1));
1300
-  *header = ks->key_id | (opcode << P_OPCODE_SHIFT);
1301
-  if (session->tls_auth.key_ctx_bi.encrypt.hmac)
1298
+
1299
+  if (session->tls_wrap.mode == TLS_WRAP_AUTH ||
1300
+      session->tls_wrap.mode == TLS_WRAP_NONE)
1301
+    {
1302
+      ASSERT (session_id_write_prepend (&session->session_id, buf));
1303
+      ASSERT (buf_write_prepend (buf, &header, sizeof(header)));
1304
+    }
1305
+  if (session->tls_wrap.mode == TLS_WRAP_AUTH)
1302 1306
     {
1303 1307
       /* no encryption, only write hmac */
1304
-      openvpn_encrypt (buf, null, &session->tls_auth);
1305
-      ASSERT (swap_hmac (buf, &session->tls_auth, false));
1308
+      openvpn_encrypt (buf, null, &session->tls_wrap.opt);
1309
+      ASSERT (swap_hmac (buf, &session->tls_wrap.opt, false));
1310
+    }
1311
+  else if (session->tls_wrap.mode == TLS_WRAP_CRYPT)
1312
+    {
1313
+      buf_init (&session->tls_wrap.work, buf->offset);
1314
+      ASSERT (buf_write (&session->tls_wrap.work, &header, sizeof(header)));
1315
+      ASSERT (session_id_write (&session->session_id, &session->tls_wrap.work));
1316
+      ASSERT (tls_crypt_wrap (buf, &session->tls_wrap.work, &session->tls_wrap.opt));
1317
+      /* Don't change the original data in buf, it's used by the reliability
1318
+       * layer to resend on failure. */
1319
+      *buf = session->tls_wrap.work;
1306 1320
     }
1307 1321
   *to_link_addr = &ks->remote_addr;
1308 1322
 }
... ...
@@ -1312,17 +1336,18 @@ write_control_auth (struct tls_session *session,
1312 1312
  */
1313 1313
 static bool
1314 1314
 read_control_auth (struct buffer *buf,
1315
-		   struct crypto_options *co,
1315
+		   struct tls_wrap_ctx *ctx,
1316 1316
 		   const struct link_socket_actual *from)
1317 1317
 {
1318 1318
   struct gc_arena gc = gc_new ();
1319
+  bool ret = false;
1319 1320
 
1320
-  if (co->key_ctx_bi.decrypt.hmac)
1321
+  if (ctx->mode == TLS_WRAP_AUTH)
1321 1322
     {
1322 1323
       struct buffer null = clear_buf ();
1323 1324
 
1324 1325
       /* move the hmac record to the front of the packet */
1325
-      if (!swap_hmac (buf, co, true))
1326
+      if (!swap_hmac (buf, &ctx->opt, true))
1326 1327
 	{
1327 1328
 	  msg (D_TLS_ERRORS,
1328 1329
 	       "TLS Error: cannot locate HMAC in incoming packet from %s",
... ...
@@ -1333,24 +1358,41 @@ read_control_auth (struct buffer *buf,
1333 1333
 
1334 1334
       /* authenticate only (no decrypt) and remove the hmac record
1335 1335
          from the head of the buffer */
1336
-      openvpn_decrypt (buf, null, co, NULL, BPTR (buf));
1336
+      openvpn_decrypt (buf, null, &ctx->opt, NULL, BPTR (buf));
1337 1337
       if (!buf->len)
1338 1338
 	{
1339 1339
 	  msg (D_TLS_ERRORS,
1340 1340
 	       "TLS Error: incoming packet authentication failed from %s",
1341 1341
 	       print_link_socket_actual (from, &gc));
1342
-	  gc_free (&gc);
1343
-	  return false;
1342
+	  goto cleanup;
1344 1343
 	}
1345 1344
 
1346 1345
     }
1346
+  else if (ctx->mode == TLS_WRAP_CRYPT)
1347
+    {
1348
+      struct buffer tmp = alloc_buf (buf_forward_capacity_total (buf));
1349
+      if (!tls_crypt_unwrap (buf, &tmp, &ctx->opt))
1350
+	{
1351
+	  msg (D_TLS_ERRORS, "TLS Error: tls-crypt unwrapping failed from %s",
1352
+	      print_link_socket_actual (from, &gc));
1353
+	  goto cleanup;
1354
+	}
1355
+      ASSERT (buf_init (buf, buf->offset));
1356
+      ASSERT (buf_copy (buf, &tmp));
1357
+      free_buf (&tmp);
1358
+    }
1347 1359
 
1348
-  /* advance buffer pointer past opcode & session_id since our caller
1349
-     already read it */
1350
-  buf_advance (buf, SID_SIZE + 1);
1360
+  if (ctx->mode == TLS_WRAP_NONE || ctx->mode == TLS_WRAP_AUTH)
1361
+    {
1362
+      /* advance buffer pointer past opcode & session_id since our caller
1363
+	 already read it */
1364
+      buf_advance (buf, SID_SIZE + 1);
1365
+    }
1351 1366
 
1367
+  ret = true;
1368
+cleanup:
1352 1369
   gc_free (&gc);
1353
-  return true;
1370
+  return ret;
1354 1371
 }
1355 1372
 
1356 1373
 /*
... ...
@@ -2731,11 +2773,11 @@ tls_process (struct tls_multi *multi,
2731 2731
   /* Send 1 or more ACKs (each received control packet gets one ACK) */
2732 2732
   if (!to_link->len && !reliable_ack_empty (ks->rec_ack))
2733 2733
     {
2734
-      buf = &ks->ack_write_buf;
2735
-      ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame)));
2736
-      write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1,
2734
+      struct buffer buf = ks->ack_write_buf;
2735
+      ASSERT (buf_init (&buf, FRAME_HEADROOM (&multi->opt.frame)));
2736
+      write_control_auth (session, ks, &buf, to_link_addr, P_ACK_V1,
2737 2737
 			  RELIABLE_ACK_SIZE, false);
2738
-      *to_link = *buf;
2738
+      *to_link = buf;
2739 2739
       active = true;
2740 2740
       state_change = true;
2741 2741
       dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP");
... ...
@@ -3233,7 +3275,7 @@ tls_pre_decrypt (struct tls_multi *multi,
3233 3233
 		  goto error;
3234 3234
 		}
3235 3235
 
3236
-	      if (!read_control_auth (buf, &session->tls_auth, from))
3236
+	      if (!read_control_auth (buf, &session->tls_wrap, from))
3237 3237
 		goto error;
3238 3238
 
3239 3239
 	      /*
... ...
@@ -3284,7 +3326,7 @@ tls_pre_decrypt (struct tls_multi *multi,
3284 3284
 	      if (op == P_CONTROL_SOFT_RESET_V1
3285 3285
 		  && DECRYPT_KEY_ENABLED (multi, ks))
3286 3286
 		{
3287
-		  if (!read_control_auth (buf, &session->tls_auth, from))
3287
+		  if (!read_control_auth (buf, &session->tls_wrap, from))
3288 3288
 		    goto error;
3289 3289
 
3290 3290
 		  key_state_soft_reset (session);
... ...
@@ -3301,7 +3343,7 @@ tls_pre_decrypt (struct tls_multi *multi,
3301 3301
 		  if (op == P_CONTROL_SOFT_RESET_V1)
3302 3302
 		    do_burst = true;
3303 3303
 
3304
-		  if (!read_control_auth (buf, &session->tls_auth, from))
3304
+		  if (!read_control_auth (buf, &session->tls_wrap, from))
3305 3305
 		    goto error;
3306 3306
 
3307 3307
 		  dmsg (D_TLS_DEBUG,
... ...
@@ -3491,18 +3533,11 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
3491 3491
 
3492 3492
       {
3493 3493
 	struct buffer newbuf = clone_buf (buf);
3494
-	struct crypto_options co = tas->tls_auth_options;
3494
+	struct tls_wrap_ctx tls_wrap_tmp = tas->tls_wrap;
3495 3495
 	bool status;
3496 3496
 
3497
-	/*
3498
-	 * We are in read-only mode at this point with respect to TLS
3499
-	 * control channel state.  After we build a new client instance
3500
-	 * object, we will process this session-initiating packet for real.
3501
-	 */
3502
-	co.flags |= CO_IGNORE_PACKET_ID;
3503
-
3504 3497
 	/* HMAC test, if --tls-auth was specified */
3505
-	status = read_control_auth (&newbuf, &co, from);
3498
+	status = read_control_auth (&newbuf, &tls_wrap_tmp, from);
3506 3499
 	free_buf (&newbuf);
3507 3500
 	if (!status)
3508 3501
 	  goto error;
... ...
@@ -136,7 +136,7 @@
136 136
  */
137 137
 struct tls_auth_standalone
138 138
 {
139
-  struct crypto_options tls_auth_options;
139
+  struct tls_wrap_ctx tls_wrap;
140 140
   struct frame frame;
141 141
 };
142 142
 
... ...
@@ -204,6 +204,18 @@ struct key_state
204 204
 #endif
205 205
 };
206 206
 
207
+/** Control channel wrapping (--tls-auth/--tls-crypt) context */
208
+struct tls_wrap_ctx
209
+{
210
+  enum {
211
+    TLS_WRAP_NONE = 0,	/**< No control channel wrapping */
212
+    TLS_WRAP_AUTH,	/**< Control channel authentication */
213
+    TLS_WRAP_CRYPT,	/**< Control channel encryption and authentication */
214
+  } mode;			/**< Control channel wrapping mode */
215
+  struct crypto_options opt;	/**< Crypto state */
216
+  struct buffer work;		/**< Work buffer (only for --tls-crypt) */
217
+};
218
+
207 219
 /*
208 220
  * Our const options, obtained directly or derived from
209 221
  * command line options.
... ...
@@ -278,8 +290,8 @@ struct tls_options
278 278
   const char *config_authname;
279 279
   bool ncp_enabled;
280 280
 
281
-  /* packet authentication for TLS handshake */
282
-  struct crypto_options tls_auth;
281
+  /** TLS handshake wrapping state */
282
+  struct tls_wrap_ctx tls_wrap;
283 283
 
284 284
   /* frame parameters for TLS control channel */
285 285
   struct frame frame;
... ...
@@ -380,7 +392,7 @@ struct tls_session
380 380
   bool burst;
381 381
 
382 382
   /* authenticate control packets */
383
-  struct crypto_options tls_auth;
383
+  struct tls_wrap_ctx tls_wrap;
384 384
 
385 385
   int initial_opcode;		/* our initial P_ opcode */
386 386
   struct session_id session_id;	/* our random session ID */
387 387
new file mode 100644
... ...
@@ -0,0 +1,254 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2016 Fox Crypto B.V. <openvpn@fox-it.com>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+#ifdef HAVE_CONFIG_H
25
+#include "config.h"
26
+#elif defined(_MSC_VER)
27
+#include "config-msvc.h"
28
+#endif
29
+
30
+#include "syshead.h"
31
+
32
+#ifdef ENABLE_CRYPTO
33
+#include "crypto.h"
34
+#include "session_id.h"
35
+
36
+#include "tls_crypt.h"
37
+
38
+int tls_crypt_buf_overhead(void)
39
+{
40
+  return packet_id_size (true) + TLS_CRYPT_TAG_SIZE + TLS_CRYPT_BLOCK_SIZE;
41
+}
42
+
43
+void
44
+tls_crypt_init_key (struct key_ctx_bi *key, const char *key_file,
45
+    const char *key_inline, bool tls_server) {
46
+  const int key_direction = tls_server ?
47
+      KEY_DIRECTION_NORMAL : KEY_DIRECTION_INVERSE;
48
+
49
+  struct key_type kt;
50
+  kt.cipher = cipher_kt_get ("AES-256-CTR");
51
+  kt.cipher_length = cipher_kt_key_size (kt.cipher);
52
+  kt.digest = md_kt_get ("SHA256");
53
+  kt.hmac_length = md_kt_size (kt.digest);
54
+
55
+  if (!kt.cipher)
56
+    {
57
+      msg (M_FATAL, "ERROR: --tls-crypt requires AES-256-CTR support.");
58
+    }
59
+  if (!kt.digest)
60
+    {
61
+      msg (M_FATAL, "ERROR: --tls-crypt requires HMAC-SHA-256 support.");
62
+    }
63
+
64
+  crypto_read_openvpn_key (&kt, key, key_file, key_inline, key_direction,
65
+			   "Control Channel Encryption", "tls-crypt");
66
+}
67
+
68
+void
69
+tls_crypt_adjust_frame_parameters(struct frame *frame)
70
+{
71
+  frame_add_to_extra_frame (frame, tls_crypt_buf_overhead());
72
+
73
+  msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for tls-crypt by %i bytes",
74
+      __func__, tls_crypt_buf_overhead());
75
+}
76
+
77
+
78
+bool
79
+tls_crypt_wrap (const struct buffer *src, struct buffer *dst,
80
+	 struct crypto_options *opt) {
81
+  const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
82
+  struct gc_arena gc;
83
+
84
+  /* IV, packet-ID and implicit IV required for this mode. */
85
+  ASSERT (ctx->cipher);
86
+  ASSERT (ctx->hmac);
87
+  ASSERT (packet_id_initialized(&opt->packet_id));
88
+  ASSERT (hmac_ctx_size(ctx->hmac) == 256/8);
89
+
90
+  gc_init (&gc);
91
+
92
+  dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP FROM: %s",
93
+      format_hex (BPTR (src), BLEN (src), 80, &gc));
94
+
95
+  /* Get packet ID */
96
+  {
97
+    struct packet_id_net pin;
98
+    packet_id_alloc_outgoing (&opt->packet_id.send, &pin, true);
99
+    packet_id_write (&pin, dst, true, false);
100
+  }
101
+
102
+  dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s",
103
+      format_hex (BPTR (dst), BLEN (dst), 0, &gc));
104
+
105
+  /* Buffer overflow check */
106
+  if (!buf_safe (dst, BLEN (src) + TLS_CRYPT_BLOCK_SIZE + TLS_CRYPT_TAG_SIZE))
107
+    {
108
+      msg (D_CRYPT_ERRORS, "TLS-CRYPT WRAP: buffer size error, "
109
+	  "sc=%d so=%d sl=%d dc=%d do=%d dl=%d", src->capacity, src->offset,
110
+	  src->len, dst->capacity, dst->offset, dst->len);
111
+      goto err;
112
+    }
113
+
114
+  /* Calculate auth tag and synthetic IV */
115
+  {
116
+    uint8_t *tag = NULL;
117
+    hmac_ctx_reset (ctx->hmac);
118
+    hmac_ctx_update (ctx->hmac, BPTR (dst), BLEN (dst));
119
+    hmac_ctx_update (ctx->hmac, BPTR (src), BLEN (src));
120
+
121
+    ASSERT (tag = buf_write_alloc (dst, TLS_CRYPT_TAG_SIZE));
122
+    hmac_ctx_final (ctx->hmac, tag);
123
+
124
+    dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP TAG: %s",
125
+        format_hex (tag, TLS_CRYPT_TAG_SIZE, 0, &gc));
126
+
127
+    /* Use the 128 most significant bits of the tag as IV */
128
+    ASSERT (cipher_ctx_reset (ctx->cipher, tag));
129
+  }
130
+
131
+  /* Encrypt src */
132
+  {
133
+    int outlen = 0;
134
+    ASSERT (cipher_ctx_update (ctx->cipher, BEND (dst), &outlen,
135
+	BPTR (src), BLEN(src)));
136
+    ASSERT (buf_inc_len (dst, outlen));
137
+    ASSERT (cipher_ctx_final (ctx->cipher, BPTR (dst), &outlen));
138
+    ASSERT (buf_inc_len (dst, outlen));
139
+  }
140
+
141
+  dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP TO: %s",
142
+      format_hex (BPTR (dst), BLEN (dst), 80, &gc));
143
+
144
+  gc_free (&gc);
145
+  return true;
146
+
147
+err:
148
+  crypto_clear_error();
149
+  dst->len = 0;
150
+  gc_free (&gc);
151
+  return false;
152
+}
153
+
154
+bool
155
+tls_crypt_unwrap (const struct buffer *src, struct buffer *dst,
156
+    struct crypto_options *opt)
157
+{
158
+  static const char error_prefix[] = "tls-crypt unwrap error";
159
+  const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
160
+  struct gc_arena gc;
161
+
162
+  gc_init (&gc);
163
+
164
+  ASSERT (opt);
165
+  ASSERT (src->len > 0);
166
+  ASSERT (ctx->cipher);
167
+  ASSERT (packet_id_initialized (&opt->packet_id) ||
168
+      (opt->flags & CO_IGNORE_PACKET_ID));
169
+
170
+  dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP FROM: %s",
171
+      format_hex (BPTR (src), BLEN (src), 80, &gc));
172
+
173
+  if (buf_len (src) < TLS_CRYPT_OFF_CT)
174
+    {
175
+      CRYPT_ERROR ("packet too short");
176
+    }
177
+
178
+  /* Decrypt cipher text */
179
+  {
180
+    int outlen = 0;
181
+
182
+    /* Buffer overflow check (should never fail) */
183
+    if (!buf_safe (dst, BLEN (src) - TLS_CRYPT_OFF_CT + TLS_CRYPT_BLOCK_SIZE))
184
+      {
185
+	CRYPT_ERROR ("potential buffer overflow");
186
+      }
187
+
188
+    if (!cipher_ctx_reset (ctx->cipher, BPTR (src) + TLS_CRYPT_OFF_TAG))
189
+      {
190
+	CRYPT_ERROR ("cipher reset failed");
191
+      }
192
+    if (!cipher_ctx_update (ctx->cipher, BPTR (dst), &outlen,
193
+	BPTR (src) + TLS_CRYPT_OFF_CT, BLEN (src) - TLS_CRYPT_OFF_CT))
194
+      {
195
+	CRYPT_ERROR ("cipher update failed");
196
+      }
197
+    ASSERT (buf_inc_len (dst, outlen));
198
+    if (!cipher_ctx_final (ctx->cipher, BPTR(dst), &outlen))
199
+      {
200
+	CRYPT_ERROR ("cipher final failed");
201
+      }
202
+    ASSERT (buf_inc_len (dst, outlen));
203
+  }
204
+
205
+  /* Check authentication */
206
+  {
207
+    const uint8_t *tag = BPTR (src) + TLS_CRYPT_OFF_TAG;
208
+    uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 };
209
+
210
+    dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP AD: %s",
211
+        format_hex (BPTR (src), TLS_CRYPT_OFF_TAG, 0, &gc));
212
+    dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP TO: %s",
213
+         format_hex (BPTR (dst), BLEN (dst), 80, &gc));
214
+
215
+    hmac_ctx_reset (ctx->hmac);
216
+    hmac_ctx_update (ctx->hmac, BPTR (src), TLS_CRYPT_OFF_TAG);
217
+    hmac_ctx_update (ctx->hmac, BPTR (dst), BLEN (dst));
218
+    hmac_ctx_final (ctx->hmac, tag_check);
219
+
220
+    if (memcmp_constant_time (tag, tag_check, sizeof(tag_check)))
221
+      {
222
+	dmsg (D_CRYPTO_DEBUG, "tag      : %s",
223
+	    format_hex (tag, sizeof(tag_check), 0, &gc));
224
+	dmsg (D_CRYPTO_DEBUG, "tag_check: %s",
225
+	    format_hex (tag_check, sizeof(tag_check), 0, &gc));
226
+	CRYPT_ERROR ("packet authentication failed");
227
+      }
228
+  }
229
+
230
+  /* Check replay */
231
+  if (!(opt->flags & CO_IGNORE_PACKET_ID))
232
+    {
233
+      struct packet_id_net pin;
234
+      struct buffer tmp = *src;
235
+      ASSERT (buf_advance (&tmp, TLS_CRYPT_OFF_PID));
236
+      ASSERT (packet_id_read (&pin, &tmp, true));
237
+      if (!crypto_check_replay (opt, &pin, error_prefix, &gc))
238
+	{
239
+	  CRYPT_ERROR ("packet replay");
240
+	}
241
+    }
242
+
243
+  gc_free (&gc);
244
+  return true;
245
+
246
+ error_exit:
247
+  crypto_clear_error();
248
+  dst->len = 0;
249
+  gc_free (&gc);
250
+  return false;
251
+}
252
+
253
+#endif /* EMABLE_CRYPTO */
0 254
new file mode 100644
... ...
@@ -0,0 +1,144 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2016 Fox Crypto B.V. <openvpn@fox-it.com>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+/**
25
+ * @defgroup tls_crypt Control channel encryption (--tls-crypt)
26
+ * @ingroup control_tls
27
+ * @{
28
+ *
29
+ * @par
30
+ * Control channel encryption uses a pre-shared static key (like the --tls-auth
31
+ * key) to encrypt control channel packets.
32
+ *
33
+ * @par
34
+ * Encrypting control channel packets has three main advantages:
35
+ *  - It provides more privacy by hiding the certificate used for the TLS
36
+ *    connection.
37
+ *  - It is harder to identify OpenVPN traffic as such.
38
+ *  - It provides "poor-man's" post-quantum security, against attackers who
39
+ *    will never know the pre-shared key (i.e. no forward secrecy).
40
+ *
41
+ * @par Specification
42
+ * Control channel encryption is based on the SIV construction [0], to achieve
43
+ * nonce misuse-resistant authenticated encryption:
44
+ *
45
+ * @par
46
+ * \code{.unparsed}
47
+ * msg      = control channel plaintext
48
+ * header   = opcode (1 byte) || session_id (8 bytes) || packet_id (8 bytes)
49
+ * Ka       = authentication key (256 bits)
50
+ * Ke       = encryption key (256 bits)
51
+ * (Ka and Ke are pre-shared keys, like with --tls-auth)
52
+ *
53
+ * auth_tag = HMAC-SHA256(Ka, header || msg)
54
+ * IV       = 128 most-significant bits of auth_tag
55
+ * ciph     = AES256-CTR(Ke, IV, msg)
56
+ *
57
+ * output   = Header || Tag || Ciph
58
+ * \endcode
59
+ *
60
+ * @par
61
+ * This boils down to the following on-the-wire packet format:
62
+ *
63
+ * @par
64
+ * \code{.unparsed}
65
+ * - opcode - || - session_id - || - packet_id - || auth_tag || * payload *
66
+ * \endcode
67
+ *
68
+ * @par
69
+ * Where
70
+ * <tt>- XXX -</tt> means authenticated, and
71
+ * <tt>* XXX *</tt> means authenticated and encrypted.
72
+ */
73
+
74
+#ifndef TLSCRYPT_H
75
+#define TLSCRYPT_H
76
+
77
+#include "buffer.h"
78
+#include "crypto.h"
79
+#include "session_id.h"
80
+
81
+#define TLS_CRYPT_TAG_SIZE (256/8)
82
+#define TLS_CRYPT_PID_SIZE (sizeof (packet_id_type) + sizeof (net_time_t))
83
+#define TLS_CRYPT_BLOCK_SIZE (128/8)
84
+
85
+#define TLS_CRYPT_OFF_PID (1 + SID_SIZE)
86
+#define TLS_CRYPT_OFF_TAG (TLS_CRYPT_OFF_PID + TLS_CRYPT_PID_SIZE)
87
+#define TLS_CRYPT_OFF_CT (TLS_CRYPT_OFF_TAG + TLS_CRYPT_TAG_SIZE)
88
+
89
+/**
90
+ * Initialize a key_ctx_bi structure for use with --tls-crypt.
91
+ *
92
+ * @param key		The key context to initialize
93
+ * @param key_file	The file to read the key from (or the inline tag to
94
+ *			indicate and inline key).
95
+ * @param key_inline	Array containing (zero-terminated) inline key, or NULL
96
+ *			if not used.
97
+ * @param tls_server	Must be set to true is this is a TLS server instance.
98
+ */
99
+void tls_crypt_init_key (struct key_ctx_bi *key, const char *key_file,
100
+    const char *key_inline, bool tls_server);
101
+
102
+/**
103
+ * Returns the maximum overhead (in bytes) added to the destination buffer by
104
+ * tls_crypt_wrap().
105
+ */
106
+int tls_crypt_buf_overhead(void);
107
+
108
+/**
109
+ * Adjust frame parameters for --tls-crypt overhead.
110
+ */
111
+void tls_crypt_adjust_frame_parameters(struct frame *frame);
112
+
113
+/**
114
+ * Wrap a control channel packet (both authenticates and encrypts the data).
115
+ *
116
+ * @param src	Data to authenticate and encrypt.
117
+ * @param dst	Any data present in this buffer is first authenticated, then
118
+ *		the wrapped packet id and data from the src buffer are appended.
119
+ *		Must have at least tls_crypt_buf_overhead()+BLEN(src) headroom.
120
+ * @param opt	The crypto state for this --tls-crypt instance.
121
+ *
122
+ * @returns true iff wrapping succeeded.
123
+ */
124
+bool tls_crypt_wrap (const struct buffer *src, struct buffer *dst,
125
+	 struct crypto_options *opt);
126
+
127
+/**
128
+ * Unwrap a control channel packet (decrypts, authenticates and performs
129
+ * replay checks).
130
+ *
131
+ * @param src	Data to decrypt and authenticate.
132
+ * @param dst	Returns the decrypted data, if unwrapping was successful.
133
+ * @param opt	The crypto state for this --tls-crypt instance.
134
+ *
135
+ * @returns true iff unwrapping succeeded (data authenticated correctly and was
136
+ * no replay).
137
+ */
138
+bool tls_crypt_unwrap (const struct buffer *src, struct buffer *dst,
139
+    struct crypto_options *opt);
140
+
141
+/** @} */
142
+
143
+#endif /* TLSCRYPT_H */