summaryrefslogtreecommitdiffstats
path: root/ssl/statem/statem_srvr.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-08-01 15:45:29 +0100
committerMatt Caswell <matt@openssl.org>2017-08-31 15:03:35 +0100
commit630369d9ce4f6bf67c4a055790362cd27b32229e (patch)
tree23092983d518d55cc09e44478c795808e6a13041 /ssl/statem/statem_srvr.c
parentae8d7d994afb38c8309770f68212bf51380b8941 (diff)
Add server side sanity checks of SNI/ALPN for use with early_data
Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/3926)
Diffstat (limited to 'ssl/statem/statem_srvr.c')
-rw-r--r--ssl/statem/statem_srvr.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 8c5f77bce5..8c2a4e97ac 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1938,7 +1938,7 @@ static int tls_handle_status_request(SSL *s, int *al)
* Call the alpn_select callback if needed. Upon success, returns 1.
* Upon failure, returns 0 and sets |*al| to the appropriate fatal alert.
*/
-static int tls_handle_alpn(SSL *s, int *al)
+int tls_handle_alpn(SSL *s, int *al)
{
const unsigned char *selected = NULL;
unsigned char selected_len = 0;
@@ -1961,15 +1961,30 @@ static int tls_handle_alpn(SSL *s, int *al)
/* ALPN takes precedence over NPN. */
s->s3->npn_seen = 0;
#endif
- } else if (r == SSL_TLSEXT_ERR_NOACK) {
- /* Behave as if no callback was present. */
+
+ /* Check ALPN is consistent with early_data */
+ if (s->ext.early_data_ok
+ && (s->session->ext.alpn_selected == NULL
+ || selected_len != s->session->ext.alpn_selected_len
+ || memcmp(selected, s->session->ext.alpn_selected,
+ selected_len) != 0))
+ s->ext.early_data_ok = 0;
+
return 1;
- } else {
+ } else if (r != SSL_TLSEXT_ERR_NOACK) {
*al = SSL_AD_NO_APPLICATION_PROTOCOL;
return 0;
}
+ /*
+ * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
+ * present.
+ */
}
+ /* Check ALPN is consistent with early_data */
+ if (s->ext.early_data_ok && s->session->ext.alpn_selected != NULL)
+ s->ext.early_data_ok = 0;
+
return 1;
}
@@ -2059,9 +2074,11 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
}
/*
* Call alpn_select callback if needed. Has to be done after SNI and
- * cipher negotiation (HTTP/2 restricts permitted ciphers).
+ * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
+ * we already did this because cipher negotiation happens earlier, and
+ * we must handle ALPN before we decide whether to accept early_data.
*/
- if (!tls_handle_alpn(s, &al)) {
+ if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s, &al)) {
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
SSL_R_CLIENTHELLO_TLSEXT);
goto f_err;