Add basic TLSv1.3 cookie support
authorMatt Caswell <matt@openssl.org>
Thu, 2 Mar 2017 17:37:03 +0000 (17:37 +0000)
committerMatt Caswell <matt@openssl.org>
Sat, 4 Mar 2017 23:32:39 +0000 (23:32 +0000)
We do not allow the generation of TLSv1.3 cookies. But if we receive one
in an HRR we will echo it back in the ClientHello.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2839)

include/openssl/ssl.h
include/openssl/tls1.h
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/statem/extensions.c
ssl/statem/extensions_clnt.c
ssl/statem/statem_locl.h

index 64a312c5889001ca71a762450922db761c0e32e1..c569407701889a87553c84a2cfadfec3d6644416 100644 (file)
@@ -2348,6 +2348,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY                489
 # define SSL_F_TLS_CONSTRUCT_CTOS_ALPN                    466
 # define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE             355
+# define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE                  535
 # define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA              530
 # define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS           467
 # define SSL_F_TLS_CONSTRUCT_CTOS_EMS                     468
@@ -2408,6 +2409,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_PARSE_CTOS_PSK                         505
 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE                 464
 # define SSL_F_TLS_PARSE_CTOS_USE_SRTP                    465
+# define SSL_F_TLS_PARSE_STOC_COOKIE                      534
 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO             528
 # define SSL_F_TLS_PARSE_STOC_KEY_SHARE                   445
 # define SSL_F_TLS_PARSE_STOC_PSK                         502
index 10544872b3b5dc95cc947865d406543aa67c204a..280d131c6f2a0a25ccab67cec6bb39f54b96e3a1 100644 (file)
@@ -181,6 +181,7 @@ extern "C" {
 # define TLSEXT_TYPE_psk                         41
 # define TLSEXT_TYPE_early_data                  42
 # define TLSEXT_TYPE_supported_versions          43
+# define TLSEXT_TYPE_cookie                      44
 # define TLSEXT_TYPE_psk_kex_modes               45
 # define TLSEXT_TYPE_early_data_info             46
 
index 0ace985cf25cacecdadbfc74cf11bd4c7d9858b0..ee1ca6293c410c2bd242351e57368c6d5b7d7fd9 100644 (file)
@@ -304,6 +304,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_ALPN), "tls_construct_ctos_alpn"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE),
      "TLS_CONSTRUCT_CTOS_CERTIFICATE"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_COOKIE), "tls_construct_ctos_cookie"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA),
      "tls_construct_ctos_early_data"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS),
@@ -401,6 +402,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE),
      "tls_parse_ctos_renegotiate"},
     {ERR_FUNC(SSL_F_TLS_PARSE_CTOS_USE_SRTP), "tls_parse_ctos_use_srtp"},
+    {ERR_FUNC(SSL_F_TLS_PARSE_STOC_COOKIE), "tls_parse_stoc_cookie"},
     {ERR_FUNC(SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO),
      "tls_parse_stoc_early_data_info"},
     {ERR_FUNC(SSL_F_TLS_PARSE_STOC_KEY_SHARE), "tls_parse_stoc_key_share"},
index fcf4f4d347e49a707c961278b6b0d9b67cb3abd8..f0e8639d61e4f645df5d92aa6a36e3b1f6ecf2fd 100644 (file)
@@ -1017,6 +1017,7 @@ void SSL_free(SSL *s)
 #endif
     OPENSSL_free(s->ext.ocsp.resp);
     OPENSSL_free(s->ext.alpn);
+    OPENSSL_free(s->ext.tls13_cookie);
     OPENSSL_free(s->clienthello);
 
     sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
index 6811b4f3f4a95fe6d912d5d4739244163fa412ae..f4860ea1fd282e133158ac8edc7c186b8978536a 100644 (file)
@@ -1211,6 +1211,10 @@ struct ssl_st {
         int early_data;
         /* Is the session suitable for early data? */
         int early_data_ok;
+
+        /* May be sent by a server in HRR. Must be echoed back in ClientHello */
+        unsigned char *tls13_cookie;
+        size_t tls13_cookie_len;
     } ext;
 
     /* Parsed form of the ClientHello, kept around across early_cb calls. */
@@ -1801,6 +1805,7 @@ typedef enum tlsext_index_en {
     TLSEXT_IDX_supported_versions,
     TLSEXT_IDX_psk_kex_modes,
     TLSEXT_IDX_key_share,
+    TLSEXT_IDX_cookie,
     TLSEXT_IDX_cryptopro_bug,
     TLSEXT_IDX_early_data,
     TLSEXT_IDX_padding,
index edcfe718c422f223cb84c44a8c099553e21a6656..8c4013e416e87d26d3dfcfc24225e6e29f368e89 100644 (file)
@@ -269,6 +269,13 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         final_key_share
     },
 #endif
+    {
+        TLSEXT_TYPE_cookie,
+        EXT_CLIENT_HELLO | EXT_TLS1_3_HELLO_RETRY_REQUEST
+        | EXT_TLS_IMPLEMENTATION_ONLY | EXT_TLS1_3_ONLY,
+        NULL, NULL, tls_parse_stoc_cookie, NULL, tls_construct_ctos_cookie,
+        NULL
+    },
     {
         /*
          * Special unsolicited ServerHello extension only used when
index 0af4d1b5888ac839761f908ce8db558440c86964..23dc8d3363b719f653fb3caf0509c5cd0a5b7a9a 100644 (file)
@@ -636,6 +636,33 @@ int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al)
+{
+    int ret = 0;
+
+    /* Should only be set if we've had an HRR */
+    if (s->ext.tls13_cookie_len == 0)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
+               /* Extension data sub-packet */
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
+                                       s->ext.tls13_cookie_len)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_COOKIE, ERR_R_INTERNAL_ERROR);
+        goto end;
+    }
+
+    ret = 1;
+ end:
+    OPENSSL_free(s->ext.tls13_cookie);
+    s->ext.tls13_cookie_len = 0;
+
+    return ret;
+}
+
 int tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, unsigned int context,
                                   X509 *x, size_t chainidx, int *al)
 {
@@ -1338,6 +1365,22 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     return 1;
 }
 
+int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+                       size_t chainidx, int *al)
+{
+    PACKET cookie;
+
+    if (!PACKET_as_length_prefixed_2(pkt, &cookie)
+            || !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
+                              &s->ext.tls13_cookie_len)) {
+        *al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_TLS_PARSE_STOC_COOKIE, SSL_R_LENGTH_MISMATCH);
+        return 0;
+    }
+
+    return 1;
+}
+
 int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
                               X509 *x, size_t chainidx, int *al)
 {
index c52ce2bd16b15d31f5de9a0aea02a7b794dcd754..68160c9bc7276d098730aa6536fcfaf62fe64484 100644 (file)
@@ -332,6 +332,8 @@ int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al);
 int tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, unsigned int context,
                                      X509 *x, size_t chainidx, int *al);
+int tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al);
 int tls_construct_ctos_padding(SSL *s, WPACKET *pkt, unsigned int context,
                                X509 *x, size_t chainidx, int *al);
 int tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
@@ -374,5 +376,7 @@ int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al);
 int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                              size_t chainidx, int *al);
+int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+                       size_t chainidx, int *al);
 int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al);