Browse code

tls-crypt-v2: implement tls-crypt-v2 handshake

This makes clients send-and-use, and servers receive-unwrap-and-use
tls-crypt-v2 client keys, which completes the on-the-wire work.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <1540208715-14044-5-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17787.html
Signed-off-by: David Sommerseth <davids@openvpn.net>

Steffan Karger authored on 2018/10/22 20:45:14
Showing 7 changed files
... ...
@@ -2464,6 +2464,7 @@ key_schedule_free(struct key_schedule *ks, bool free_ssl_ctx)
2464 2464
     if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx)
2465 2465
     {
2466 2466
         tls_ctx_free(&ks->ssl_ctx);
2467
+        free_key_ctx(&ks->tls_crypt_v2_server_key);
2467 2468
     }
2468 2469
     CLEAR(*ks);
2469 2470
 }
... ...
@@ -2647,6 +2648,24 @@ do_init_crypto_tls_c1(struct context *c)
2647 2647
         /* initialize tls-auth/crypt key */
2648 2648
         do_init_tls_wrap_key(c);
2649 2649
 
2650
+        /* tls-crypt with client-specific keys (--tls-crypt-v2) */
2651
+        if (options->tls_crypt_v2_file)
2652
+        {
2653
+            if (options->tls_server)
2654
+            {
2655
+                tls_crypt_v2_init_server_key(&c->c1.ks.tls_crypt_v2_server_key,
2656
+                                             true, options->tls_crypt_v2_file,
2657
+                                             options->tls_crypt_v2_inline);
2658
+            }
2659
+            else
2660
+            {
2661
+                tls_crypt_v2_init_client_key(&c->c1.ks.tls_wrap_key,
2662
+                                             &c->c1.ks.tls_crypt_v2_wkc,
2663
+                                             options->tls_crypt_v2_file,
2664
+                                             options->tls_crypt_v2_inline);
2665
+            }
2666
+        }
2667
+
2650 2668
 #if 0 /* was: #if ENABLE_INLINE_FILES --  Note that enabling this code will break restarts */
2651 2669
         if (options->priv_key_file_inline)
2652 2670
         {
... ...
@@ -2863,13 +2882,28 @@ do_init_crypto_tls(struct context *c, const unsigned int flags)
2863 2863
     }
2864 2864
 
2865 2865
     /* TLS handshake encryption (--tls-crypt) */
2866
-    if (options->ce.tls_crypt_file)
2866
+    if (options->ce.tls_crypt_file
2867
+        || (options->ce.tls_crypt_v2_file && options->tls_client))
2867 2868
     {
2868 2869
         to.tls_wrap.mode = TLS_WRAP_CRYPT;
2869 2870
         to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key;
2870 2871
         to.tls_wrap.opt.pid_persist = &c->c1.pid_persist;
2871 2872
         to.tls_wrap.opt.flags |= CO_PACKET_ID_LONG_FORM;
2872 2873
         tls_crypt_adjust_frame_parameters(&to.frame);
2874
+
2875
+        if (options->tls_crypt_v2_file)
2876
+        {
2877
+            to.tls_wrap.tls_crypt_v2_wkc = &c->c1.ks.tls_crypt_v2_wkc;
2878
+        }
2879
+    }
2880
+
2881
+    if (options->tls_crypt_v2_file)
2882
+    {
2883
+        to.tls_crypt_v2 = true;
2884
+        if (options->tls_server)
2885
+        {
2886
+            to.tls_wrap.tls_crypt_v2_server_key = c->c1.ks.tls_crypt_v2_server_key;
2887
+        }
2873 2888
     }
2874 2889
 
2875 2890
     /* If we are running over TCP, allow for
... ...
@@ -3473,6 +3507,8 @@ do_close_free_key_schedule(struct context *c, bool free_ssl_ctx)
3473 3473
      */
3474 3474
     free_key_ctx_bi(&c->c1.ks.tls_wrap_key);
3475 3475
     CLEAR(c->c1.ks.tls_wrap_key);
3476
+    buf_clear(&c->c1.ks.tls_crypt_v2_wkc);
3477
+    free_buf(&c->c1.ks.tls_crypt_v2_wkc);
3476 3478
 
3477 3479
     if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_key))
3478 3480
     {
... ...
@@ -4408,6 +4444,7 @@ inherit_context_child(struct context *dest,
4408 4408
     dest->c1.ks.ssl_ctx = src->c1.ks.ssl_ctx;
4409 4409
     dest->c1.ks.tls_wrap_key = src->c1.ks.tls_wrap_key;
4410 4410
     dest->c1.ks.tls_auth_key_type = src->c1.ks.tls_auth_key_type;
4411
+    dest->c1.ks.tls_crypt_v2_server_key = src->c1.ks.tls_crypt_v2_server_key;
4411 4412
     /* inherit pre-NCP ciphers */
4412 4413
     dest->c1.ciphername = src->c1.ciphername;
4413 4414
     dest->c1.authname = src->c1.authname;
... ...
@@ -66,6 +66,8 @@ struct key_schedule
66 66
     /* optional TLS control channel wrapping */
67 67
     struct key_type tls_auth_key_type;
68 68
     struct key_ctx_bi tls_wrap_key;
69
+    struct key_ctx tls_crypt_v2_server_key;
70
+    struct buffer tls_crypt_v2_wkc;             /**< Wrapped client key */
69 71
 };
70 72
 
71 73
 /*
... ...
@@ -1048,6 +1048,23 @@ tls_session_user_pass_enabled(struct tls_session *session)
1048 1048
 /** @addtogroup control_processor
1049 1049
  *  @{ */
1050 1050
 
1051
+/** Free the elements of a tls_wrap_ctx structure */
1052
+static void tls_wrap_free(struct tls_wrap_ctx *tls_wrap)
1053
+{
1054
+    if (packet_id_initialized(&tls_wrap->opt.packet_id))
1055
+    {
1056
+        packet_id_free(&tls_wrap->opt.packet_id);
1057
+    }
1058
+
1059
+    if (tls_wrap->cleanup_key_ctx)
1060
+    {
1061
+        free_key_ctx_bi(&tls_wrap->opt.key_ctx_bi);
1062
+    }
1063
+
1064
+    free_buf(&tls_wrap->tls_crypt_v2_metadata);
1065
+    free_buf(&tls_wrap->work);
1066
+}
1067
+
1051 1068
 /** @name Functions for initialization and cleanup of tls_session structures
1052 1069
  *  @{ */
1053 1070
 
... ...
@@ -1140,16 +1157,9 @@ tls_session_init(struct tls_multi *multi, struct tls_session *session)
1140 1140
 static void
1141 1141
 tls_session_free(struct tls_session *session, bool clear)
1142 1142
 {
1143
-    int i;
1144
-
1145
-    if (packet_id_initialized(&session->tls_wrap.opt.packet_id))
1146
-    {
1147
-        packet_id_free(&session->tls_wrap.opt.packet_id);
1148
-    }
1143
+    tls_wrap_free(&session->tls_wrap);
1149 1144
 
1150
-    free_buf(&session->tls_wrap.work);
1151
-
1152
-    for (i = 0; i < KS_SIZE; ++i)
1145
+    for (size_t i = 0; i < KS_SIZE; ++i)
1153 1146
     {
1154 1147
         key_state_free(&session->key[i], false);
1155 1148
     }
... ...
@@ -1475,6 +1485,8 @@ write_control_auth(struct tls_session *session,
1475 1475
     ASSERT(reliable_ack_write
1476 1476
                (ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack));
1477 1477
 
1478
+    msg(D_TLS_DEBUG, "%s(): %s", __func__, packet_opcode_name(opcode));
1479
+
1478 1480
     if (session->tls_wrap.mode == TLS_WRAP_AUTH
1479 1481
         || session->tls_wrap.mode == TLS_WRAP_NONE)
1480 1482
     {
... ...
@@ -1492,17 +1504,26 @@ write_control_auth(struct tls_session *session,
1492 1492
         ASSERT(buf_init(&session->tls_wrap.work, buf->offset));
1493 1493
         ASSERT(buf_write(&session->tls_wrap.work, &header, sizeof(header)));
1494 1494
         ASSERT(session_id_write(&session->session_id, &session->tls_wrap.work));
1495
-        if (tls_crypt_wrap(buf, &session->tls_wrap.work, &session->tls_wrap.opt))
1496
-        {
1497
-            /* Don't change the original data in buf, it's used by the reliability
1498
-             * layer to resend on failure. */
1499
-            *buf = session->tls_wrap.work;
1500
-        }
1501
-        else
1495
+        if (!tls_crypt_wrap(buf, &session->tls_wrap.work, &session->tls_wrap.opt))
1502 1496
         {
1503 1497
             buf->len = 0;
1504 1498
             return;
1505 1499
         }
1500
+
1501
+        if (opcode == P_CONTROL_HARD_RESET_CLIENT_V3)
1502
+        {
1503
+            if (!buf_copy(&session->tls_wrap.work,
1504
+                          session->tls_wrap.tls_crypt_v2_wkc))
1505
+            {
1506
+                msg(D_TLS_ERRORS, "Could not append tls-crypt-v2 client key");
1507
+                buf->len = 0;
1508
+                return;
1509
+            }
1510
+        }
1511
+
1512
+        /* Don't change the original data in buf, it's used by the reliability
1513
+         * layer to resend on failure. */
1514
+        *buf = session->tls_wrap.work;
1506 1515
     }
1507 1516
     *to_link_addr = &ks->remote_addr;
1508 1517
 }
... ...
@@ -1518,6 +1539,16 @@ read_control_auth(struct buffer *buf,
1518 1518
     struct gc_arena gc = gc_new();
1519 1519
     bool ret = false;
1520 1520
 
1521
+    const uint8_t opcode = *(BPTR(buf)) >> P_OPCODE_SHIFT;
1522
+    if (opcode == P_CONTROL_HARD_RESET_CLIENT_V3
1523
+        && !tls_crypt_v2_extract_client_key(buf, ctx))
1524
+    {
1525
+        msg (D_TLS_ERRORS,
1526
+             "TLS Error: can not extract tls-crypt-v2 client key from %s",
1527
+             print_link_socket_actual(from, &gc));
1528
+        goto cleanup;
1529
+    }
1530
+
1521 1531
     if (ctx->mode == TLS_WRAP_AUTH)
1522 1532
     {
1523 1533
         struct buffer null = clear_buf();
... ...
@@ -1557,6 +1588,18 @@ read_control_auth(struct buffer *buf,
1557 1557
         ASSERT(buf_copy(buf, &tmp));
1558 1558
         buf_clear(&tmp);
1559 1559
     }
1560
+    else if (ctx->tls_crypt_v2_server_key.cipher)
1561
+    {
1562
+        /* If tls-crypt-v2 is enabled, require *some* wrapping */
1563
+        msg(D_TLS_ERRORS, "TLS Error: could not determine wrapping from %s",
1564
+            print_link_socket_actual(from, &gc));
1565
+        /* TODO Do we want to support using tls-crypt-v2 and no control channel
1566
+         * wrapping at all simultaneously?  That would allow server admins to
1567
+         * upgrade clients one-by-one without running a second instance, but we
1568
+         * should not enable it by default because it breaks DoS-protection.
1569
+         * So, add something like --tls-crypt-v2-allow-insecure-fallback ? */
1570
+        goto cleanup;
1571
+    }
1560 1572
 
1561 1573
     if (ctx->mode == TLS_WRAP_NONE || ctx->mode == TLS_WRAP_AUTH)
1562 1574
     {
... ...
@@ -3857,6 +3900,10 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,
3857 3857
             /* HMAC test, if --tls-auth was specified */
3858 3858
             status = read_control_auth(&newbuf, &tls_wrap_tmp, from);
3859 3859
             free_buf(&newbuf);
3860
+            if (tls_wrap_tmp.cleanup_key_ctx)
3861
+            {
3862
+                free_key_ctx_bi(&tls_wrap_tmp.opt.key_ctx_bi);
3863
+            }
3860 3864
             if (!status)
3861 3865
             {
3862 3866
                 goto error;
... ...
@@ -213,6 +213,12 @@ struct tls_wrap_ctx
213 213
     } mode;                     /**< Control channel wrapping mode */
214 214
     struct crypto_options opt;  /**< Crypto state */
215 215
     struct buffer work;         /**< Work buffer (only for --tls-crypt) */
216
+    struct key_ctx tls_crypt_v2_server_key;  /**< Decrypts client keys */
217
+    const struct buffer *tls_crypt_v2_wkc;   /**< Wrapped client key,
218
+                                                  sent to server */
219
+    struct buffer tls_crypt_v2_metadata;     /**< Received from client */
220
+    bool cleanup_key_ctx;                    /**< opt.key_ctx_bi is owned by
221
+                                                  this context */
216 222
 };
217 223
 
218 224
 /*
... ...
@@ -33,6 +33,7 @@
33 33
 #include "crypto.h"
34 34
 #include "platform.h"
35 35
 #include "session_id.h"
36
+#include "ssl.h"
36 37
 
37 38
 #include "tls_crypt.h"
38 39
 
... ...
@@ -543,6 +544,62 @@ error_exit:
543 543
     return ret;
544 544
 }
545 545
 
546
+bool
547
+tls_crypt_v2_extract_client_key(struct buffer *buf,
548
+                                struct tls_wrap_ctx *ctx)
549
+{
550
+    if (!ctx->tls_crypt_v2_server_key.cipher)
551
+    {
552
+        msg(D_TLS_ERRORS,
553
+             "Client wants tls-crypt-v2, but no server key present.");
554
+        return false;
555
+    }
556
+
557
+    msg(D_HANDSHAKE, "Control Channel: using tls-crypt-v2 key");
558
+
559
+    struct buffer wrapped_client_key = *buf;
560
+    uint16_t net_len = 0;
561
+
562
+    if (BLEN(&wrapped_client_key) < sizeof(net_len))
563
+    {
564
+        msg(D_TLS_ERRORS, "failed to read length");
565
+    }
566
+    memcpy(&net_len, BEND(&wrapped_client_key) - sizeof(net_len),
567
+           sizeof(net_len));
568
+
569
+    size_t wkc_len = ntohs(net_len);
570
+    if (!buf_advance(&wrapped_client_key, BLEN(&wrapped_client_key) - wkc_len))
571
+    {
572
+        msg(D_TLS_ERRORS, "Can not locate tls-crypt-v2 client key");
573
+        return false;
574
+    }
575
+
576
+    struct key2 client_key = { 0 };
577
+    ctx->tls_crypt_v2_metadata = alloc_buf(TLS_CRYPT_V2_MAX_METADATA_LEN);
578
+    if (!tls_crypt_v2_unwrap_client_key(&client_key,
579
+                                        &ctx->tls_crypt_v2_metadata,
580
+                                        wrapped_client_key,
581
+                                        &ctx->tls_crypt_v2_server_key))
582
+    {
583
+        msg(D_TLS_ERRORS, "Can not unwrap tls-crypt-v2 client key");
584
+        secure_memzero(&client_key, sizeof(client_key));
585
+        return false;
586
+    }
587
+
588
+    /* Load the decrypted key */
589
+    ctx->mode = TLS_WRAP_CRYPT;
590
+    ctx->cleanup_key_ctx = true;
591
+    ctx->opt.flags |= CO_PACKET_ID_LONG_FORM;
592
+    memset(&ctx->opt.key_ctx_bi, 0, sizeof(ctx->opt.key_ctx_bi));
593
+    tls_crypt_v2_load_client_key(&ctx->opt.key_ctx_bi, &client_key, true);
594
+    secure_memzero(&client_key, sizeof(client_key));
595
+
596
+    /* Remove client key from buffer so tls-crypt code can unwrap message */
597
+    ASSERT(buf_inc_len(buf, -(BLEN(&wrapped_client_key))));
598
+
599
+    return true;
600
+}
601
+
546 602
 void
547 603
 tls_crypt_v2_write_server_key_file(const char *filename)
548 604
 {
... ...
@@ -84,6 +84,7 @@
84 84
 #include "buffer.h"
85 85
 #include "crypto.h"
86 86
 #include "session_id.h"
87
+#include "ssl_common.h"
87 88
 
88 89
 #define TLS_CRYPT_TAG_SIZE (256/8)
89 90
 #define TLS_CRYPT_PID_SIZE (sizeof(packet_id_type) + sizeof(net_time_t))
... ...
@@ -184,6 +185,19 @@ void tls_crypt_v2_init_client_key(struct key_ctx_bi *key,
184 184
                                   const char *key_inline);
185 185
 
186 186
 /**
187
+ * Extract a tls-crypt-v2 client key from a P_CONTROL_HARD_RESET_CLIENT_V3
188
+ * message, and load the key into the supplied tls wrap context.
189
+ *
190
+ * @param buf   Buffer containing a received P_CONTROL_HARD_RESET_CLIENT_V3
191
+ *              message.
192
+ * @param ctx   tls-wrap context to be initialized with the client key.
193
+ *
194
+ * @returns true if a key was successfully extracted.
195
+ */
196
+bool tls_crypt_v2_extract_client_key(struct buffer *buf,
197
+                                     struct tls_wrap_ctx *ctx);
198
+
199
+/**
187 200
  * Generate a tls-crypt-v2 server key, and write to file.
188 201
  *
189 202
  * @param filename          Filename of the server key file to create.
... ...
@@ -346,6 +346,12 @@ tls_crypt_v2_wrap_unwrap_max_metadata(void **state) {
346 346
     assert_true(0 == memcmp(ctx->client_key2.keys, unwrapped_client_key2.keys,
347 347
                             sizeof(ctx->client_key2.keys)));
348 348
     assert_true(buf_equal(&ctx->metadata, &unwrap_metadata));
349
+
350
+    struct tls_wrap_ctx wrap_ctx = {
351
+            .mode = TLS_WRAP_CRYPT,
352
+            .tls_crypt_v2_server_key = ctx->server_keys.encrypt,
353
+    };
354
+    assert_true(tls_crypt_v2_extract_client_key(&ctx->wkc, &wrap_ctx));
349 355
 }
350 356
 
351 357
 /**