提交 4be3a7c7 编写于 作者: M Matt Caswell

Client side sanity check of ALPN after server has accepted early_data

Reviewed-by: NBen Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3926)
上级 fff202e5
...@@ -844,7 +844,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent, ...@@ -844,7 +844,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
case SSL_TLSEXT_ERR_NOACK: case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0; s->servername_done = 0;
if (s->session->ext.hostname != NULL) if (s->server && s->session->ext.hostname != NULL)
s->ext.early_data_ok = 0; s->ext.early_data_ok = 0;
return 1; return 1;
...@@ -945,6 +945,9 @@ static int init_alpn(SSL *s, unsigned int context) ...@@ -945,6 +945,9 @@ static int init_alpn(SSL *s, unsigned int context)
static int final_alpn(SSL *s, unsigned int context, int sent, int *al) static int final_alpn(SSL *s, unsigned int context, int sent, int *al)
{ {
if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
s->ext.early_data_ok = 0;
if (!s->server || !SSL_IS_TLS13(s)) if (!s->server || !SSL_IS_TLS13(s))
return 1; return 1;
...@@ -1387,8 +1390,24 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, ...@@ -1387,8 +1390,24 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
static int final_early_data(SSL *s, unsigned int context, int sent, int *al) static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
{ {
if (!s->server || !sent) if (!sent)
return 1;
if (!s->server) {
if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
&& sent
&& !s->ext.early_data_ok) {
/*
* If we get here then the server accepted our early_data but we
* later realised that it shouldn't have done (e.g. inconsistent
* ALPN)
*/
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
return 1; return 1;
}
if (s->max_early_data == 0 if (s->max_early_data == 0
|| !s->hit || !s->hit
......
...@@ -771,6 +771,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, ...@@ -771,6 +771,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
* extension, we set it to accepted. * extension, we set it to accepted.
*/ */
s->ext.early_data = SSL_EARLY_DATA_REJECTED; s->ext.early_data = SSL_EARLY_DATA_REJECTED;
s->ext.early_data_ok = 1;
return EXT_RETURN_SENT; return EXT_RETURN_SENT;
} }
...@@ -1400,15 +1401,22 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, ...@@ -1400,15 +1401,22 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
} }
s->s3->alpn_selected_len = len; s->s3->alpn_selected_len = len;
/* We also put a copy in the session */ if (s->session->ext.alpn_selected != NULL
OPENSSL_free(s->session->ext.alpn_selected); && (s->session->ext.alpn_selected_len != len
s->session->ext.alpn_selected = OPENSSL_memdup(s->s3->alpn_selected, || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected,
s->s3->alpn_selected_len); len) != 0)) {
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len; /* ALPN not consistent with the old session so cannot use early_data */
s->ext.early_data_ok = 0;
if (s->session->ext.alpn_selected == NULL) { }
*al = SSL_AD_INTERNAL_ERROR; if (!s->hit) {
return 0; /* If a new session then update it with the selected ALPN */
s->session->ext.alpn_selected =
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
} }
return 1; return 1;
...@@ -1637,12 +1645,13 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, ...@@ -1637,12 +1645,13 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
return 0; return 0;
} }
if (s->ext.early_data != SSL_EARLY_DATA_REJECTED if (!s->ext.early_data_ok
|| !s->hit || !s->hit
|| s->session->ext.tick_identity != 0) { || s->session->ext.tick_identity != 0) {
/* /*
* If we get here then we didn't send early data, or we didn't resume * If we get here then we didn't send early data, or we didn't resume
* using the first identity so the server should not be accepting it. * using the first identity, or the SNI/ALPN is not consistent so the
* server should not be accepting it.
*/ */
*al = SSL_AD_ILLEGAL_PARAMETER; *al = SSL_AD_ILLEGAL_PARAMETER;
return 0; return 0;
......
...@@ -1962,14 +1962,26 @@ int tls_handle_alpn(SSL *s, int *al) ...@@ -1962,14 +1962,26 @@ int tls_handle_alpn(SSL *s, int *al)
s->s3->npn_seen = 0; s->s3->npn_seen = 0;
#endif #endif
/* Check ALPN is consistent with early_data */ /* Check ALPN is consistent with session */
if (s->ext.early_data_ok if (s->session->ext.alpn_selected == NULL
&& (s->session->ext.alpn_selected == NULL
|| selected_len != s->session->ext.alpn_selected_len || selected_len != s->session->ext.alpn_selected_len
|| memcmp(selected, s->session->ext.alpn_selected, || memcmp(selected, s->session->ext.alpn_selected,
selected_len) != 0)) selected_len) != 0) {
/* Not consistent so can't be used for early_data */
s->ext.early_data_ok = 0; s->ext.early_data_ok = 0;
if (!s->hit) {
/* If a new session update it with the new ALPN value */
s->session->ext.alpn_selected = OPENSSL_memdup(selected,
selected_len);
if (s->session->ext.alpn_selected == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
s->session->ext.alpn_selected_len = selected_len;
}
}
return 1; return 1;
} else if (r != SSL_TLSEXT_ERR_NOACK) { } else if (r != SSL_TLSEXT_ERR_NOACK) {
*al = SSL_AD_NO_APPLICATION_PROTOCOL; *al = SSL_AD_NO_APPLICATION_PROTOCOL;
...@@ -1981,9 +1993,11 @@ int tls_handle_alpn(SSL *s, int *al) ...@@ -1981,9 +1993,11 @@ int tls_handle_alpn(SSL *s, int *al)
*/ */
} }
/* Check ALPN is consistent with early_data */ /* Check ALPN is consistent with session */
if (s->ext.early_data_ok && s->session->ext.alpn_selected != NULL) if (s->session->ext.alpn_selected != NULL) {
/* Not consistent so can't be used for early_data */
s->ext.early_data_ok = 0; s->ext.early_data_ok = 0;
}
return 1; return 1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册