Browse code

Implement HMAC based session id for tls-crypt v2

Tls-crypt v2 is more complicated to implement a proper stateless
handshake. To allow state handshake this commit does

- introduce a new packet CONTROL_WKC_V1 that repeats the wrapped
client key.
- introduce a way to negotiate the support for this packet in the
three way handshake

Details about the protocol changes are in tls-crypt-v2.txt. Optional
arguments to the tls-crypt-v2 option have been added to explicitly
allow or disallow client that do not support the stateless handshake.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>

Patch v3: improve grammar, style, comments, fix unit tests
Patch v4: remove explicit flag for ability to resend WKc,
clean up comments, improve code style in some instances
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20220505130348.1183195-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg24287.html

Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2022/05/05 22:03:48
Showing 13 changed files
... ...
@@ -69,6 +69,16 @@ Improved ``--mssfix`` and ``--fragment`` calculation
69 69
     account and the resulting size is specified as the total size of the VPN packets
70 70
     including IP and UDP headers.
71 71
 
72
+Cookie based handshake for UDP server
73
+    Instead of allocating a connection for each client on the initial packet
74
+    OpenVPN server will now use an HMAC based cookie as its session id. This
75
+    way the server can verify it on completing the handshake without keeping
76
+    state. This eliminates the amplification and resource exhaustion attacks.
77
+    For tls-crypt-v2 clients, this requires OpenVPN 2.6 clients or later
78
+    because the client needs to resend its client key on completing the hand
79
+    shake. The tls-crypt-v2 option allows controlling if older clients are
80
+    accepted.
81
+
72 82
 Deprecated features
73 83
 -------------------
74 84
 ``inetd`` has been removed
... ...
@@ -486,6 +486,13 @@ certificates and keys: https://github.com/OpenVPN/easy-rsa
486 486
   8000 years'.
487 487
 
488 488
 --tls-crypt-v2 keyfile
489
+
490
+  Valid syntax:
491
+  ::
492
+     tls-crypt-v2 keyfile
493
+     tls-crypt-v2 keyfile force-cookie
494
+     tls-crypt-v2 keyfile allow-noncookie
495
+
489 496
   Use client-specific tls-crypt keys.
490 497
 
491 498
   For clients, ``keyfile`` is a client-specific tls-crypt key. Such a key
... ...
@@ -501,6 +508,13 @@ certificates and keys: https://github.com/OpenVPN/easy-rsa
501 501
   client is using client-specific keys, and automatically select the right
502 502
   mode.
503 503
 
504
+  The optional parameters :code:`force-cookie` allows only tls-crypt-v2
505
+  clients that support a cookie based stateless three way handshake that
506
+  avoids replay attacks and state exhaustion on the server side (OpenVPN
507
+  2.6 and later). The option :code:`allow-noncookie` explicitly allows
508
+  older tls-crypt-v2 clients. The default is (currently)
509
+  :code:`allow-noncookie`.
510
+
504 511
 --tls-crypt-v2-verify cmd
505 512
   Run command ``cmd`` to verify the metadata of the client-specific
506 513
   tls-crypt-v2 key of a connecting client. This allows server
... ...
@@ -157,6 +157,50 @@ When setting up the openvpn connection:
157 157
    messages.
158 158
 
159 159
 
160
+HMAC Cookie support
161
+-------------------
162
+To avoid exhaustion attack and keeping state for connections that fail to
163
+complete the three-way handshake, the OpenVPN server will use its own session
164
+id as challenge that the client must repeat in the third packet of the
165
+handshake. This introduces a problem. If the server does not keep the wrapped
166
+client key from the initial packet, the server cannot decode the third packet.
167
+Therefore, tls-crypt-v2 in 2.6 allows resending the wrapped key in the third
168
+packet of the handshake with the P_CONTROL_WKC_V1 message. The modified
169
+handshake is as follows (the rest of the handshake is unmodified):
170
+
171
+1. The client creates the P_CONTROL_HARD_RESET_CLIENT_V3 message as before
172
+   but indicates that it supports resending the wrapped key. This is done
173
+   by setting the packet id of the replay id to 0x0f000000. The first byte
174
+   indicates the early negotiation support and the next byte the flags.
175
+   All tls-crypt-v2 implementations that support early negotiation, must
176
+   also support resending the wrapped key. The flags byte is therefore
177
+   empty.
178
+
179
+2. The server responds with a P_CONTROL_HARD_RESET_V2 message. Instead of having
180
+   an empty payload like normally, the payload consists of TLV (type (uint16),
181
+   length (uint16), value) packets. TLV was chosen
182
+   to allow extensibility in the future. Currently only the following TLV is
183
+   defined:
184
+
185
+   flags - type 0x01, length 2.
186
+
187
+   Bit 1 indicates that the client needs to resend the WKc in the third packet.
188
+
189
+3. Instead of normal P_ACK_V1 or P_CONTROL_V1 packet, the client will send a
190
+   P_CONTROL_WKC_V1 packet. The P_CONTROL_WKC_V1 is identical to a normal
191
+   P_CONTROL_V1 packet but with the WKc appended.
192
+
193
+   Normally the first message of the client is either P_ACK_V1, directly
194
+   followed by a P_CONTROL_V1 message that contains the TLS Client Hello or
195
+   just a P_CONTROL_V1 message. Instead of a P_ACK_V1 message the client should
196
+   send a P_CONTROL_WKC_V1 message with an empty payload. This message must
197
+   also include an ACK for the P_CONTROL_HARD_RESET_V2 message.
198
+
199
+   When directly sending the TLS Client Hello message in the P_CONTROL_WKC_V1
200
+   message, the client must ensure that the resulting P_CONTROL_WKC_V1 message
201
+   with the appended WKc does not extend the control message length.
202
+
203
+
160 204
 Considerations
161 205
 --------------
162 206
 
... ...
@@ -256,6 +256,14 @@ struct crypto_options
256 256
     /**< Bit-flag indicating that data channel key derivation
257 257
      * is done using TLS keying material export [RFC5705]
258 258
      */
259
+#define CO_RESEND_WKC (1<<4)
260
+    /**< Bit-flag indicating that the client is expected to
261
+     * resend the wrapped client key with the 2nd packet (packet-id 1)
262
+     * like with the HARD_RESET_CLIENT_V3 packet */
263
+#define CO_FORCE_TLSCRYPTV2_COOKIE  (1<<5)
264
+    /**< Bit-flag indicating that we do not allow clients that do
265
+     * not support resending the wrapped client key (WKc) with the
266
+     * third packet of the three-way handshake */
259 267
     unsigned int flags;         /**< Bit-flags determining behavior of
260 268
                                  *   security operation functions. */
261 269
 };
... ...
@@ -2960,6 +2960,10 @@ do_init_crypto_tls(struct context *c, const unsigned int flags)
2960 2960
         {
2961 2961
             to.tls_wrap.tls_crypt_v2_server_key = c->c1.ks.tls_crypt_v2_server_key;
2962 2962
             to.tls_crypt_v2_verify_script = c->options.tls_crypt_v2_verify_script;
2963
+            if (options->ce.tls_crypt_v2_force_cookie)
2964
+            {
2965
+                to.tls_wrap.opt.flags |= CO_FORCE_TLSCRYPTV2_COOKIE;
2966
+            }
2963 2967
         }
2964 2968
     }
2965 2969
 
... ...
@@ -40,7 +40,31 @@
40 40
 #include <sys/inotify.h>
41 41
 #endif
42 42
 
43
-/* Return true if this packet should create a new session */
43
+static void
44
+send_hmac_reset_packet(struct multi_context *m,
45
+                       struct tls_pre_decrypt_state *state,
46
+                       struct tls_auth_standalone *tas,
47
+                       struct session_id *sid,
48
+                       bool request_resend_wkc)
49
+{
50
+    reset_packet_id_send(&state->tls_wrap_tmp.opt.packet_id.send);
51
+    state->tls_wrap_tmp.opt.packet_id.rec.initialized = true;
52
+    uint8_t header = 0 | (P_CONTROL_HARD_RESET_SERVER_V2 << P_OPCODE_SHIFT);
53
+    struct buffer buf = tls_reset_standalone(&state->tls_wrap_tmp, tas, sid,
54
+                                             &state->peer_session_id, header,
55
+                                             request_resend_wkc);
56
+
57
+    struct context *c = &m->top;
58
+
59
+    buf_reset_len(&c->c2.buffers->aux_buf);
60
+    buf_copy(&c->c2.buffers->aux_buf, &buf);
61
+    m->hmac_reply = c->c2.buffers->aux_buf;
62
+    m->hmac_reply_dest = &m->top.c2.from;
63
+    msg(D_MULTI_DEBUG, "Reset packet from client, sending HMAC based reset challenge");
64
+}
65
+
66
+
67
+/* Returns true if this packet should create a new session */
44 68
 static bool
45 69
 do_pre_decrypt_check(struct multi_context *m,
46 70
                      struct tls_pre_decrypt_state *state,
... ...
@@ -58,37 +82,64 @@ do_pre_decrypt_check(struct multi_context *m,
58 58
     struct openvpn_sockaddr *from = &m->top.c2.from.dest;
59 59
     int handwindow = m->top.options.handshake_window;
60 60
 
61
-
62 61
     if (verdict == VERDICT_VALID_RESET_V3)
63 62
     {
64
-        /* For tls-crypt-v2 we need to keep the state of the first packet to
65
-         * store the unwrapped key */
66
-        return true;
63
+        /* Extract the packet id to check if it has the special format that
64
+         * indicates early negotiation support */
65
+        struct packet_id_net pin;
66
+        struct buffer tmp = m->top.c2.buf;
67
+        ASSERT(buf_advance(&tmp, 1 + SID_SIZE));
68
+        ASSERT(packet_id_read(&pin, &tmp, true));
69
+
70
+        /* The most significant byte is 0x0f if early negotiation is supported */
71
+        bool early_neg_support = (pin.id & EARLY_NEG_MASK) == EARLY_NEG_START;
72
+
73
+        /* All clients that support early negotiation and tls-crypt are assumed
74
+         * to also support resending the WKc in the 2nd packet */
75
+        if (early_neg_support)
76
+        {
77
+            /* Calculate the session ID HMAC for our reply and create reset packet */
78
+            struct session_id sid = calculate_session_id_hmac(state->peer_session_id,
79
+                                                              from, hmac, handwindow, 0);
80
+            send_hmac_reset_packet(m, state, tas, &sid, true);
81
+
82
+            return false;
83
+        }
84
+        else
85
+        {
86
+            /* For tls-crypt-v2 we need to keep the state of the first packet
87
+             * to store the unwrapped key if the client doesn't support resending
88
+             * the wrapped key. Unless the user specifically disallowed
89
+             * compatibility with such clients to avoid state exhaustion */
90
+            if (tas->tls_wrap.opt.flags & CO_FORCE_TLSCRYPTV2_COOKIE)
91
+            {
92
+                struct gc_arena gc = gc_new();
93
+                const char *peer = print_link_socket_actual(&m->top.c2.from, &gc);
94
+                msg(D_MULTI_DEBUG, "tls-crypt-v2 force-cookie is enabled, "
95
+                    "ignoring connection attempt from old client (%s)", peer);
96
+                gc_free(&gc);
97
+                return false;
98
+            }
99
+            else
100
+            {
101
+                return true;
102
+            }
103
+        }
67 104
     }
68 105
     else if (verdict == VERDICT_VALID_RESET_V2)
69 106
     {
70 107
         /* Calculate the session ID HMAC for our reply and create reset packet */
71 108
         struct session_id sid = calculate_session_id_hmac(state->peer_session_id,
72 109
                                                           from, hmac, handwindow, 0);
73
-        reset_packet_id_send(&tas->tls_wrap.opt.packet_id.send);
74
-        tas->tls_wrap.opt.packet_id.rec.initialized = true;
75
-        uint8_t header = 0 | (P_CONTROL_HARD_RESET_SERVER_V2 << P_OPCODE_SHIFT);
76
-        struct buffer buf = tls_reset_standalone(tas, &sid,
77
-                                                 &state->peer_session_id, header);
78
-
79 110
 
80
-        struct context *c = &m->top;
111
+        send_hmac_reset_packet(m, state, tas, &sid, false);
81 112
 
82
-        buf_reset_len(&c->c2.buffers->aux_buf);
83
-        buf_copy(&c->c2.buffers->aux_buf, &buf);
84
-        m->hmac_reply = c->c2.buffers->aux_buf;
85
-        m->hmac_reply_dest = &m->top.c2.from;
86
-        msg(D_MULTI_DEBUG, "Reset packet from client, sending HMAC based reset challenge");
87 113
         /* We have a reply do not create a new session */
88 114
         return false;
89 115
 
90 116
     }
91
-    else if (verdict == VERDICT_VALID_CONTROL_V1 || verdict == VERDICT_VALID_ACK_V1)
117
+    else if (verdict == VERDICT_VALID_CONTROL_V1 || verdict == VERDICT_VALID_ACK_V1
118
+             || verdict == VERDICT_VALID_WKC_V1)
92 119
     {
93 120
         /* ACK_V1 contains the peer id (our id) while CONTROL_V1 can but does not
94 121
          * need to contain the peer id */
... ...
@@ -8896,6 +8896,19 @@ add_option(struct options *options,
8896 8896
             options->ce.tls_crypt_v2_file = p[1];
8897 8897
             options->ce.tls_crypt_v2_file_inline = is_inline;
8898 8898
         }
8899
+
8900
+        if (p[2] && streq(p[2], "force-cookie"))
8901
+        {
8902
+            options->ce.tls_crypt_v2_force_cookie = true;
8903
+        }
8904
+        else if (p[2] && streq(p[2], "allow-noncookie"))
8905
+        {
8906
+            options->ce.tls_crypt_v2_force_cookie = false;
8907
+        }
8908
+        else if (p[2])
8909
+        {
8910
+            msg(msglevel, "Unsupported tls-crypt-v2 argument: %s", p[2]);
8911
+        }
8899 8912
     }
8900 8913
     else if (streq(p[0], "tls-crypt-v2-verify") && p[1] && !p[2])
8901 8914
     {
... ...
@@ -162,6 +162,9 @@ struct connection_entry
162 162
      * authenticated encryption v2 */
163 163
     const char *tls_crypt_v2_file;
164 164
     bool tls_crypt_v2_file_inline;
165
+
166
+    /* Allow only client that support resending the wrapped client key */
167
+    bool tls_crypt_v2_force_cookie;
165 168
 };
166 169
 
167 170
 struct remote_entry
... ...
@@ -361,8 +361,6 @@ struct reliable_entry *reliable_get_entry_sequenced(struct reliable *rel);
361 361
  *
362 362
  * @param rel The reliable structure associated with the given buffer.
363 363
  * @param buf The buffer of the reliable entry which is to be removed.
364
- * @param inc_pid If true, the reliable structure's packet ID counter
365
- *     will be incremented.
366 364
  */
367 365
 void reliable_mark_deleted(struct reliable *rel, struct buffer *buf);
368 366
 
... ...
@@ -1099,6 +1099,14 @@ tls_session_init(struct tls_multi *multi, struct tls_session *session)
1099 1099
                    session->opt->replay_time,
1100 1100
                    "TLS_WRAP", session->key_id);
1101 1101
 
1102
+    /* If we are using tls-crypt-v2 we manipulate the packet id to be (ab)used
1103
+     * to indicate early protocol negotiation */
1104
+    if (session->opt->tls_crypt_v2)
1105
+    {
1106
+        session->tls_wrap.opt.packet_id.send.time = now;
1107
+        session->tls_wrap.opt.packet_id.send.id = EARLY_NEG_START;
1108
+    }
1109
+
1102 1110
     /* load most recent packet-id to replay protect on --tls-auth */
1103 1111
     packet_id_persist_load_obj(session->tls_wrap.opt.pid_persist,
1104 1112
                                &session->tls_wrap.opt.packet_id);
... ...
@@ -2525,6 +2533,54 @@ session_skip_to_pre_start(struct tls_session *session,
2525 2525
 }
2526 2526
 
2527 2527
 /**
2528
+ * Parses the TLVs (type, length, value) in the early negotiation
2529
+ */
2530
+static bool
2531
+parse_early_negotiation_tlvs(struct buffer *buf, struct key_state *ks)
2532
+{
2533
+    while (buf->len > 0)
2534
+    {
2535
+        if (buf_len(buf) < 4)
2536
+        {
2537
+            goto error;
2538
+        }
2539
+        /* read type */
2540
+        uint16_t type = buf_read_u16(buf);
2541
+        uint16_t len = buf_read_u16(buf);
2542
+        if (buf_len(buf) < len)
2543
+        {
2544
+            goto error;
2545
+        }
2546
+
2547
+        switch (type)
2548
+        {
2549
+            case TLV_TYPE_EARLY_NEG_FLAGS:
2550
+                if (len != sizeof(uint16_t))
2551
+                {
2552
+                    goto error;
2553
+                }
2554
+                uint16_t flags = buf_read_u16(buf);
2555
+
2556
+                if (flags & EARLY_NEG_FLAG_RESEND_WKC)
2557
+                {
2558
+                    ks->crypto_options.flags |= CO_RESEND_WKC;
2559
+                }
2560
+                break;
2561
+
2562
+            default:
2563
+                /* Skip types we do not parse */
2564
+                buf_advance(buf, len);
2565
+        }
2566
+    }
2567
+    reliable_mark_deleted(ks->rec_reliable, buf);
2568
+
2569
+    return true;
2570
+error:
2571
+    msg(D_TLS_ERRORS, "TLS Error: Early negotiation malformed packet");
2572
+    return false;
2573
+}
2574
+
2575
+/**
2528 2576
  * Read incoming ciphertext and passes it to the buffer of the SSL library.
2529 2577
  * Returns false if an error is encountered that should abort the session.
2530 2578
  */
... ...
@@ -2556,6 +2612,13 @@ read_incoming_tls_ciphertext(struct buffer *buf, struct key_state *ks,
2556 2556
     return true;
2557 2557
 }
2558 2558
 
2559
+static bool
2560
+control_packet_needs_wkc(const struct key_state *ks)
2561
+{
2562
+    return (ks->crypto_options.flags & CO_RESEND_WKC)
2563
+           && (ks->send_reliable->packet_id == 1);
2564
+}
2565
+
2559 2566
 
2560 2567
 static bool
2561 2568
 tls_process_state(struct tls_multi *multi,
... ...
@@ -2625,9 +2688,21 @@ tls_process_state(struct tls_multi *multi,
2625 2625
     struct reliable_entry *entry = reliable_get_entry_sequenced(ks->rec_reliable);
2626 2626
     if (entry)
2627 2627
     {
2628
-        if (!read_incoming_tls_ciphertext(&entry->buf, ks, &state_change))
2628
+        /* The first packet from the peer (the reset packet) is special and
2629
+         * contains early protocol negotiation */
2630
+        if (entry->packet_id == 0 && is_hard_reset_method2(entry->opcode))
2629 2631
         {
2630
-            goto error;
2632
+            if (!parse_early_negotiation_tlvs(&entry->buf, ks))
2633
+            {
2634
+                goto error;
2635
+            }
2636
+        }
2637
+        else
2638
+        {
2639
+            if (!read_incoming_tls_ciphertext(&entry->buf, ks, &state_change))
2640
+            {
2641
+                goto error;
2642
+            }
2631 2643
         }
2632 2644
     }
2633 2645
 
... ...
@@ -2720,7 +2795,12 @@ tls_process_state(struct tls_multi *multi,
2720 2720
             }
2721 2721
             if (status == 1)
2722 2722
             {
2723
-                reliable_mark_active_outgoing(ks->send_reliable, buf, P_CONTROL_V1);
2723
+                int opcode = P_CONTROL_V1;
2724
+                if (control_packet_needs_wkc(ks))
2725
+                {
2726
+                    opcode = P_CONTROL_WKC_V1;
2727
+                }
2728
+                reliable_mark_active_outgoing(ks->send_reliable, buf, opcode);
2724 2729
                 INCR_GENERATED;
2725 2730
                 state_change = true;
2726 2731
                 dmsg(D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable");
... ...
@@ -2810,15 +2890,37 @@ tls_process(struct tls_multi *multi,
2810 2810
 
2811 2811
     update_time();
2812 2812
 
2813
+    /* We often send acks back to back to a following control packet. This
2814
+     * normally does not create a problem (apart from an extra packet).
2815
+     * However, with the P_CONTROL_WKC_V1 we need to ensure that the packet
2816
+     * gets resent if not received by remote, so instead we use an empty
2817
+     * control packet in this special case */
2818
+
2813 2819
     /* Send 1 or more ACKs (each received control packet gets one ACK) */
2814 2820
     if (!to_link->len && !reliable_ack_empty(ks->rec_ack))
2815 2821
     {
2816
-        struct buffer buf = ks->ack_write_buf;
2817
-        ASSERT(buf_init(&buf, multi->opt.frame.buf.headroom));
2818
-        write_control_auth(session, ks, &buf, to_link_addr, P_ACK_V1,
2819
-                           RELIABLE_ACK_SIZE, false);
2820
-        *to_link = buf;
2821
-        dmsg(D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP");
2822
+        if (control_packet_needs_wkc(ks))
2823
+        {
2824
+            struct buffer *buf = reliable_get_buf_output_sequenced(ks->send_reliable);
2825
+            if (!buf)
2826
+            {
2827
+                return false;
2828
+            }
2829
+
2830
+            /* We do not write anything to the buffer, this way this will be
2831
+             * an empty control packet that gets the ack piggybacked and
2832
+             * also appended the wrapped client key since it has a WCK opcode */
2833
+            reliable_mark_active_outgoing(ks->send_reliable, buf, P_CONTROL_WKC_V1);
2834
+        }
2835
+        else
2836
+        {
2837
+            struct buffer buf = ks->ack_write_buf;
2838
+            ASSERT(buf_init(&buf, multi->opt.frame.buf.headroom));
2839
+            write_control_auth(session, ks, &buf, to_link_addr, P_ACK_V1,
2840
+                               RELIABLE_ACK_SIZE, false);
2841
+            *to_link = buf;
2842
+            dmsg(D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP");
2843
+        }
2822 2844
     }
2823 2845
 
2824 2846
     /* When should we wake up again? */
... ...
@@ -3463,7 +3565,8 @@ tls_pre_decrypt(struct tls_multi *multi,
3463 3463
     }
3464 3464
 
3465 3465
     /*
3466
-     * We have an authenticated control channel packet (if --tls-auth was set).
3466
+     * We have an authenticated control channel packet (if --tls-auth/tls-crypt
3467
+     * or tls-crypt-v2 was set).
3467 3468
      * Now pass to our reliability layer which deals with
3468 3469
      * packet acknowledgements, retransmits, sequencing, etc.
3469 3470
      */
... ...
@@ -3892,7 +3995,7 @@ protocol_dump(struct buffer *buffer, unsigned int flags, struct gc_arena *gc)
3892 3892
 
3893 3893
     if (op == P_ACK_V1)
3894 3894
     {
3895
-        goto done;
3895
+        goto print_data;
3896 3896
     }
3897 3897
 
3898 3898
     /*
... ...
@@ -148,7 +148,8 @@ tls_wrap_control(struct tls_wrap_ctx *ctx, uint8_t header, struct buffer *buf,
148 148
             return;
149 149
         }
150 150
 
151
-        if ((header >> P_OPCODE_SHIFT) == P_CONTROL_HARD_RESET_CLIENT_V3)
151
+        if ((header >> P_OPCODE_SHIFT) == P_CONTROL_HARD_RESET_CLIENT_V3
152
+            || (header >> P_OPCODE_SHIFT) == P_CONTROL_WKC_V1)
152 153
         {
153 154
             if (!buf_copy(&ctx->work,
154 155
                           ctx->tls_crypt_v2_wkc))
... ...
@@ -197,7 +198,8 @@ read_control_auth(struct buffer *buf,
197 197
     bool ret = false;
198 198
 
199 199
     const uint8_t opcode = *(BPTR(buf)) >> P_OPCODE_SHIFT;
200
-    if (opcode == P_CONTROL_HARD_RESET_CLIENT_V3
200
+    if ((opcode == P_CONTROL_HARD_RESET_CLIENT_V3
201
+         || opcode == P_CONTROL_WKC_V1)
201 202
         && !tls_crypt_v2_extract_client_key(buf, ctx, opt))
202 203
     {
203 204
         msg(D_TLS_ERRORS,
... ...
@@ -321,6 +323,7 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,
321 321
     if (op != P_CONTROL_HARD_RESET_CLIENT_V2
322 322
         && op != P_CONTROL_HARD_RESET_CLIENT_V3
323 323
         && op != P_CONTROL_V1
324
+        && op != P_CONTROL_WKC_V1
324 325
         && op != P_ACK_V1)
325 326
     {
326 327
         /*
... ...
@@ -397,6 +400,10 @@ tls_pre_decrypt_lite(const struct tls_auth_standalone *tas,
397 397
     {
398 398
         return VERDICT_VALID_RESET_V3;
399 399
     }
400
+    else if (op == P_CONTROL_WKC_V1)
401
+    {
402
+        return VERDICT_VALID_WKC_V1;
403
+    }
400 404
     else
401 405
     {
402 406
         return VERDICT_VALID_RESET_V2;
... ...
@@ -410,10 +417,12 @@ error:
410 410
 
411 411
 
412 412
 struct buffer
413
-tls_reset_standalone(struct tls_auth_standalone *tas,
413
+tls_reset_standalone(struct tls_wrap_ctx *ctx,
414
+                     struct tls_auth_standalone *tas,
414 415
                      struct session_id *own_sid,
415 416
                      struct session_id *remote_sid,
416
-                     uint8_t header)
417
+                     uint8_t header,
418
+                     bool request_resend_wkc)
417 419
 {
418 420
     struct buffer buf = alloc_buf(tas->frame.buf.payload_size);
419 421
     ASSERT(buf_init(&buf, tas->frame.buf.headroom));
... ...
@@ -434,8 +443,16 @@ tls_reset_standalone(struct tls_auth_standalone *tas,
434 434
 
435 435
     ASSERT(buf_write(&buf, &net_pid, sizeof(net_pid)));
436 436
 
437
+    /* Add indication for tls-crypt-v2 to resend the WKc with the reply */
438
+    if (request_resend_wkc)
439
+    {
440
+        buf_write_u16(&buf, TLV_TYPE_EARLY_NEG_FLAGS); /* TYPE: flags */
441
+        buf_write_u16(&buf, sizeof(uint16_t));
442
+        buf_write_u16(&buf, EARLY_NEG_FLAG_RESEND_WKC);
443
+    }
444
+
437 445
     /* Add tls-auth/tls-crypt wrapping, this might replace buf */
438
-    tls_wrap_control(&tas->tls_wrap, header, &buf, own_sid);
446
+    tls_wrap_control(ctx, header, &buf, own_sid);
439 447
 
440 448
     return buf;
441 449
 }
... ...
@@ -54,11 +54,15 @@
54 54
 /* indicates key_method >= 2 and client-specific tls-crypt key */
55 55
 #define P_CONTROL_HARD_RESET_CLIENT_V3 10    /* initial key from client, forget previous state */
56 56
 
57
+/* Variant of P_CONTROL_V1 but with appended wrapped key
58
+ * like P_CONTROL_HARD_RESET_CLIENT_V3 */
59
+#define P_CONTROL_WKC_V1               11
60
+
57 61
 /* define the range of legal opcodes
58 62
  * Since we do no longer support key-method 1 we consider
59 63
  * the v1 op codes invalid */
60 64
 #define P_FIRST_OPCODE                 3
61
-#define P_LAST_OPCODE                  10
65
+#define P_LAST_OPCODE                  11
62 66
 
63 67
 /*
64 68
  * Define number of buffers for send and receive in the reliability layer.
... ...
@@ -86,6 +90,8 @@ enum first_packet_verdict {
86 86
     /** This packet is a valid ACK control packet from the peer,
87 87
      * i.e. it has a valid session id hmac in it */
88 88
     VERDICT_VALID_ACK_V1,
89
+    /** The packet is a valid control packet with appended wrapped client key */
90
+    VERDICT_VALID_WKC_V1,
89 91
     /** the packet failed on of the various checks */
90 92
     VERDICT_INVALID
91 93
 };
... ...
@@ -217,10 +223,12 @@ read_control_auth(struct buffer *buf,
217 217
  * The returned buf needs to be free with \c free_buf
218 218
  */
219 219
 struct buffer
220
-tls_reset_standalone(struct tls_auth_standalone *tas,
220
+tls_reset_standalone(struct tls_wrap_ctx *ctx,
221
+                     struct tls_auth_standalone *tas,
221 222
                      struct session_id *own_sid,
222 223
                      struct session_id *remote_sid,
223
-                     uint8_t header);
224
+                     uint8_t header,
225
+                     bool request_resend_wkc);
224 226
 
225 227
 static inline const char *
226 228
 packet_opcode_name(int op)
... ...
@@ -248,6 +256,9 @@ packet_opcode_name(int op)
248 248
         case P_CONTROL_V1:
249 249
             return "P_CONTROL_V1";
250 250
 
251
+        case P_CONTROL_WKC_V1:
252
+            return "P_CONTROL_WKC_V1";
253
+
251 254
         case P_ACK_V1:
252 255
             return "P_ACK_V1";
253 256
 
... ...
@@ -261,4 +272,20 @@ packet_opcode_name(int op)
261 261
             return "P_???";
262 262
     }
263 263
 }
264
+
265
+/* initial packet id (instead of 0) that indicates that the peer supports
266
+ * early protocol negotiation. This will make the packet id turn a bit faster
267
+ * but the network time part of the packet id takes care of that. And
268
+ * this is also a rather theoretical scenario as it still needs more than
269
+ * 2^31 control channel packets to happen */
270
+#define EARLY_NEG_MASK          0xff000000
271
+#define EARLY_NEG_START         0x0f000000
272
+
273
+
274
+/* Early negotiation that part of the server response in the RESET_V2 packet.
275
+ * Since clients that announce early negotiation support will treat the payload
276
+ * of reset packets special and parse it as TLV messages.
277
+ * as TLV (type, length, value) */
278
+#define TLV_TYPE_EARLY_NEG_FLAGS        0x0001
279
+#define EARLY_NEG_FLAG_RESEND_WKC       0x0001
264 280
 #endif /* ifndef SSL_PKT_H */
... ...
@@ -536,7 +536,7 @@ test_generate_reset_packet_plain(void **ut_state)
536 536
 
537 537
     uint8_t header = 0 | (P_CONTROL_HARD_RESET_CLIENT_V2 << P_OPCODE_SHIFT);
538 538
 
539
-    struct buffer buf = tls_reset_standalone(&tas, &client_id, &server_id, header);
539
+    struct buffer buf = tls_reset_standalone(&tas.tls_wrap, &tas, &client_id, &server_id, header, false);
540 540
 
541 541
 
542 542
     verdict = tls_pre_decrypt_lite(&tas, &state, &from, &buf);
... ...
@@ -544,7 +544,7 @@ test_generate_reset_packet_plain(void **ut_state)
544 544
 
545 545
     /* Assure repeated generation of reset is deterministic/stateless*/
546 546
     assert_memory_equal(state.peer_session_id.id, client_id.id, SID_SIZE);
547
-    struct buffer buf2 = tls_reset_standalone(&tas, &client_id, &server_id, header);
547
+    struct buffer buf2 = tls_reset_standalone(&tas.tls_wrap, &tas, &client_id, &server_id, header, false);
548 548
     assert_int_equal(BLEN(&buf), BLEN(&buf2));
549 549
     assert_memory_equal(BPTR(&buf), BPTR(&buf2), BLEN(&buf));
550 550
     free_buf(&buf2);
... ...
@@ -571,7 +571,7 @@ test_generate_reset_packet_tls_auth(void **ut_state)
571 571
 
572 572
     now = 0x22446688;
573 573
     reset_packet_id_send(&tas_client.tls_wrap.opt.packet_id.send);
574
-    struct buffer buf = tls_reset_standalone(&tas_client, &client_id, &server_id, header);
574
+    struct buffer buf = tls_reset_standalone(&tas_client.tls_wrap, &tas_client, &client_id, &server_id, header, false);
575 575
 
576 576
     enum first_packet_verdict verdict = tls_pre_decrypt_lite(&tas_server, &state, &from, &buf);
577 577
     assert_int_equal(verdict, VERDICT_VALID_RESET_V2);
... ...
@@ -580,11 +580,11 @@ test_generate_reset_packet_tls_auth(void **ut_state)
580 580
 
581 581
     /* Assure repeated generation of reset is deterministic/stateless*/
582 582
     reset_packet_id_send(&tas_client.tls_wrap.opt.packet_id.send);
583
-    struct buffer buf2 = tls_reset_standalone(&tas_client, &client_id, &server_id, header);
583
+    struct buffer buf2 = tls_reset_standalone(&tas_client.tls_wrap, &tas_client, &client_id, &server_id, header,false);
584 584
     assert_int_equal(BLEN(&buf), BLEN(&buf2));
585 585
     assert_memory_equal(BPTR(&buf), BPTR(&buf2), BLEN(&buf));
586
-    free_buf(&buf2);
587 586
 
587
+    free_buf(&buf2);
588 588
     free_tls_pre_decrypt_state(&state);
589 589
 
590 590
     packet_id_free(&tas_client.tls_wrap.opt.packet_id);