static int init_npn(SSL *s, unsigned int context);
#endif
static int init_alpn(SSL *s, unsigned int context);
+static int final_alpn(SSL *s, unsigned int context, int sent, int *al);
static int init_sig_algs(SSL *s, unsigned int context);
static int init_certificate_authorities(SSL *s, unsigned int context);
static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn,
- tls_construct_stoc_alpn, tls_construct_ctos_alpn, NULL
+ tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn
},
#ifndef OPENSSL_NO_SRTP
{
case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0;
+ if (s->session->ext.hostname != NULL)
+ s->ext.early_data_ok = 0;
return 1;
default:
return 1;
}
+static int final_alpn(SSL *s, unsigned int context, int sent, int *al)
+{
+ if (!s->server || !SSL_IS_TLS13(s))
+ return 1;
+
+ /*
+ * Call alpn_select callback if needed. Has to be done after SNI and
+ * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
+ * we also have to do this before we decide whether to accept early_data.
+ * In TLSv1.3 we've already negotiated our cipher so we do this call now.
+ * For < TLSv1.3 we defer it until after cipher negotiation.
+ */
+ return tls_handle_alpn(s, al);
+}
+
static int init_sig_algs(SSL *s, unsigned int context)
{
/* Clear any signature algorithms extension received */
|| s->session->ext.tick_identity != 0
|| s->early_data_state != SSL_EARLY_DATA_ACCEPTING
|| !s->ext.early_data_ok
- || s->hello_retry_request
- || s->s3->alpn_selected_len != s->session->ext.alpn_selected_len
- || (s->s3->alpn_selected_len > 0
- && memcmp(s->s3->alpn_selected, s->session->ext.alpn_selected,
- s->s3->alpn_selected_len) != 0)) {
+ || s->hello_retry_request) {
s->ext.early_data = SSL_EARLY_DATA_REJECTED;
} else {
s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
s->servername_done = s->session->ext.hostname
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
+
+ if (!s->servername_done && s->session->ext.hostname != NULL)
+ s->ext.early_data_ok = 0;
}
return 1;
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length;
ext = 1;
- s->ext.early_data_ok = 1;
+ if (id == 0)
+ s->ext.early_data_ok = 1;
} else {
uint32_t ticket_age = 0, now, agesec, agems;
int ret = tls_decrypt_ticket(s, PACKET_data(&identity),
* Therefore we add 1000ms to our age calculation to adjust for
* rounding errors.
*/
- if (sess->timeout >= (long)agesec
+ if (id == 0
+ && sess->timeout >= (long)agesec
&& agems / (uint32_t)1000 == agesec
&& ticket_age <= agems + 1000
&& ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
/* The ciphersuite is not compatible with this session. */
SSL_SESSION_free(sess);
sess = NULL;
+ s->ext.early_data_ok = 0;
continue;
}
break;
size_t chainidx, int *al);
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx, int *al);
+
+int tls_handle_alpn(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;
/* 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;
}
}
/*
* 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;