Complain if we are writing early data but SNI or ALPN is incorrect
authorMatt Caswell <matt@openssl.org>
Fri, 21 Jul 2017 10:41:05 +0000 (11:41 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 31 Aug 2017 14:03:34 +0000 (15:03 +0100)
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)

crypto/err/openssl.txt
include/openssl/sslerr.h
ssl/ssl_err.c
ssl/statem/extensions_clnt.c

index 517c9f4..4b3c55b 100644 (file)
@@ -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
index bc4c17e..91f6d21 100644 (file)
@@ -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
index dc1d439..0ce7f27 100644 (file)
@@ -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"},
index 86a1cab..3a198f4 100644 (file)
@@ -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)