From: Matt Caswell Date: Thu, 2 Mar 2017 17:37:03 +0000 (+0000) Subject: Add basic TLSv1.3 cookie support X-Git-Tag: OpenSSL_1_1_1-pre1~2112 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cfef5027bf27a74098588e48829f0d058b4b0aea;p=thirdparty%2Fopenssl.git Add basic TLSv1.3 cookie support 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 (Merged from https://github.com/openssl/openssl/pull/2839) --- diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 64a312c5889..c5694077018 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -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 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 10544872b3b..280d131c6f2 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -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 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 0ace985cf25..ee1ca6293c4 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -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"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index fcf4f4d347e..f0e8639d61e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6811b4f3f4a..f4860ea1fd2 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -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, diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index edcfe718c42..8c4013e416e 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -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 diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 0af4d1b5888..23dc8d3363b 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -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) { diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h index c52ce2bd16b..68160c9bc72 100644 --- a/ssl/statem/statem_locl.h +++ b/ssl/statem/statem_locl.h @@ -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);