diff options
author | Matt Caswell <matt@openssl.org> | 2017-07-21 11:41:05 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2017-08-31 15:03:34 +0100 |
commit | ffc5bbaaee2bfaba8d420e912c4d77b4090b896f (patch) | |
tree | 9dd6c92e4c0e5a009b21e58d8a8b342aad53e55c /ssl | |
parent | 67738645dc0b044fc7d120a3c67af5635d0d78ec (diff) | |
download | openssl-ffc5bbaaee2bfaba8d420e912c4d77b4090b896f.tar.gz |
Complain if we are writing early data but SNI or ALPN is incorrect
SNI and ALPN must be set to be consistent with the PSK. Otherwise this is
an error.
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3926)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/ssl_err.c | 4 | ||||
-rw-r--r-- | ssl/statem/extensions_clnt.c | 52 |
2 files changed, 52 insertions, 4 deletions
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index dc1d439b1b..0ce7f271f3 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -724,6 +724,10 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "inappropriate fallback"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_COMPRESSION), "inconsistent compression"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EARLY_DATA_ALPN), + "inconsistent early data alpn"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EARLY_DATA_SNI), + "inconsistent early data sni"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_ALERT), "invalid alert"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "invalid command"}, diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 86a1cab9ae..3a198f421c 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -682,13 +682,17 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, const unsigned char *id; size_t idlen; SSL_SESSION *psksess = NULL; + SSL_SESSION *edsess = NULL; const EVP_MD *handmd = NULL; if (s->hello_retry_request) handmd = ssl_handshake_md(s); if (s->psk_use_session_cb != NULL - && !s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)) { + && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess) + || (psksess != NULL + && psksess->ssl_version != TLS1_3_VERSION))) { + SSL_SESSION_free(psksess); SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, SSL_R_BAD_PSK); return EXT_RETURN_FAIL; } @@ -711,9 +715,49 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, s->max_early_data = 0; return EXT_RETURN_NOT_SENT; } - s->max_early_data = s->session->ext.max_early_data != 0 ? - s->session->ext.max_early_data - : psksess->ext.max_early_data; + edsess = s->session->ext.max_early_data != 0 ? s->session : psksess; + s->max_early_data = edsess->ext.max_early_data; + + if ((s->ext.hostname == NULL && edsess->ext.hostname != NULL) + || (s->ext.hostname != NULL + && (edsess->ext.hostname == NULL + || strcmp(s->ext.hostname, edsess->ext.hostname) != 0))) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_SNI); + return EXT_RETURN_FAIL; + } + + if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + + /* + * Verify that we are offering an ALPN protocol consistent with the early + * data. + */ + if (edsess->ext.alpn_selected != NULL) { + PACKET prots, alpnpkt; + int found = 0; + + if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) { + if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected, + edsess->ext.alpn_selected_len)) { + found = 1; + break; + } + } + if (!found) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + } if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) || !WPACKET_start_sub_packet_u16(pkt) |