diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 517c9f4803491df36a55fb7efa3abe4e7c29c8f3..4b3c55b01079c7e18928766b7b524b2844ab72d3 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2320,6 +2320,8 @@ SSL_R_ILLEGAL_POINT_COMPRESSION:162:illegal point compression SSL_R_ILLEGAL_SUITEB_DIGEST:380:illegal Suite B digest SSL_R_INAPPROPRIATE_FALLBACK:373:inappropriate fallback SSL_R_INCONSISTENT_COMPRESSION:340:inconsistent compression +SSL_R_INCONSISTENT_EARLY_DATA_ALPN:222:inconsistent early data alpn +SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms SSL_R_INVALID_ALERT:205:invalid alert SSL_R_INVALID_COMMAND:280:invalid command diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index bc4c17e4d19dbef5d0ef0cd620d9b7076a6d1b0c..91f6d21fb4bc4580fc038d631e11145b900dbd59 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -458,6 +458,8 @@ int ERR_load_SSL_strings(void); # define SSL_R_ILLEGAL_SUITEB_DIGEST 380 # define SSL_R_INAPPROPRIATE_FALLBACK 373 # define SSL_R_INCONSISTENT_COMPRESSION 340 +# define SSL_R_INCONSISTENT_EARLY_DATA_ALPN 222 +# define SSL_R_INCONSISTENT_EARLY_DATA_SNI 231 # define SSL_R_INCONSISTENT_EXTMS 104 # define SSL_R_INVALID_ALERT 205 # define SSL_R_INVALID_COMMAND 280 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index dc1d439b1b248acbe3739c3e515b546eed4241ba..0ce7f271f32c564de8a7c90ea181a280a565aa89 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 86a1cab9ae81b4b63f459b82c2953ff173a811c8..3a198f421c988d902b265e1f44285b22026d4f86 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)