Adding ALPN to session.
0-RTT requires matching the selected ALPN parameters against those in the session. Stash the ALPN value in the session in TLS 1.3, so we can recover it. BUG=76 Change-Id: I8668b287651ae4deb0bf540c0885a02d189adee0 Reviewed-on: https://boringssl-review.googlesource.com/13845 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
f6d64efd19
commit
27a9e6ae1b
@ -3806,6 +3806,12 @@ struct ssl_session_st {
|
||||
* early data. If zero, 0-RTT is disallowed. */
|
||||
uint32_t ticket_max_early_data;
|
||||
|
||||
/* early_alpn is the ALPN protocol from the initial handshake. This is only
|
||||
* stored for TLS 1.3 and above in order to enforce ALPN matching for 0-RTT
|
||||
* resumptions. */
|
||||
uint8_t *early_alpn;
|
||||
size_t early_alpn_len;
|
||||
|
||||
/* extended_master_secret is true if the master secret in this session was
|
||||
* generated using EMS and thus isn't vulnerable to the Triple Handshake
|
||||
* attack. */
|
||||
|
@ -130,6 +130,7 @@
|
||||
* peerSignatureAlgorithm [23] INTEGER OPTIONAL,
|
||||
* ticketMaxEarlyData [24] INTEGER OPTIONAL,
|
||||
* authTimeout [25] INTEGER OPTIONAL, -- defaults to timeout
|
||||
* earlyALPN [26] OCTET STRING OPTIONAL,
|
||||
* }
|
||||
*
|
||||
* Note: historically this serialization has included other optional
|
||||
@ -186,6 +187,8 @@ static const int kTicketMaxEarlyDataTag =
|
||||
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24;
|
||||
static const int kAuthTimeoutTag =
|
||||
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25;
|
||||
static const int kEarlyALPNTag =
|
||||
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26;
|
||||
|
||||
static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
|
||||
size_t *out_len, int for_ticket) {
|
||||
@ -412,6 +415,16 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (in->early_alpn) {
|
||||
if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
|
||||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
|
||||
!CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
|
||||
in->early_alpn_len)) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CBB_finish(&cbb, out_data, out_len)) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
@ -800,6 +813,8 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
|
||||
kTicketMaxEarlyDataTag, 0) ||
|
||||
!SSL_SESSION_parse_long(&session, &ret->auth_timeout, kAuthTimeoutTag,
|
||||
ret->timeout) ||
|
||||
!SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
|
||||
&ret->early_alpn_len, kEarlyALPNTag) ||
|
||||
CBS_len(&session) != 0) {
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
|
||||
goto err;
|
||||
|
@ -280,6 +280,15 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
|
||||
new_session->ticket_age_add = session->ticket_age_add;
|
||||
new_session->ticket_max_early_data = session->ticket_max_early_data;
|
||||
new_session->extended_master_secret = session->extended_master_secret;
|
||||
|
||||
if (session->early_alpn != NULL) {
|
||||
new_session->early_alpn =
|
||||
BUF_memdup(session->early_alpn, session->early_alpn_len);
|
||||
if (new_session->early_alpn == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
new_session->early_alpn_len = session->early_alpn_len;
|
||||
}
|
||||
|
||||
/* Copy the ticket. */
|
||||
@ -373,6 +382,7 @@ void SSL_SESSION_free(SSL_SESSION *session) {
|
||||
OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
|
||||
OPENSSL_free(session->ocsp_response);
|
||||
OPENSSL_free(session->psk_identity);
|
||||
OPENSSL_free(session->early_alpn);
|
||||
OPENSSL_cleanse(session, sizeof(*session));
|
||||
OPENSSL_free(session);
|
||||
}
|
||||
|
@ -270,6 +270,17 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
|
||||
ssl->s3->new_session->cipher = cipher;
|
||||
ssl->s3->tmp.new_cipher = cipher;
|
||||
|
||||
/* Store the initial negotiated ALPN in the session. */
|
||||
if (ssl->s3->alpn_selected != NULL) {
|
||||
ssl->s3->new_session->early_alpn =
|
||||
BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
|
||||
if (ssl->s3->new_session->early_alpn == NULL) {
|
||||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
return ssl_hs_error;
|
||||
}
|
||||
ssl->s3->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
|
||||
}
|
||||
|
||||
/* The PRF hash is now known. Set up the key schedule. */
|
||||
if (!tls13_init_key_schedule(hs)) {
|
||||
return ssl_hs_error;
|
||||
|
@ -251,6 +251,17 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
|
||||
return ssl_hs_error;
|
||||
}
|
||||
|
||||
/* Store the initial negotiated ALPN in the session. */
|
||||
if (ssl->s3->alpn_selected != NULL) {
|
||||
ssl->s3->new_session->early_alpn =
|
||||
BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
|
||||
if (ssl->s3->new_session->early_alpn == NULL) {
|
||||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
return ssl_hs_error;
|
||||
}
|
||||
ssl->s3->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
|
||||
}
|
||||
|
||||
/* Incorporate the PSK into the running secret. */
|
||||
if (ssl->s3->session_reused) {
|
||||
if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
|
||||
|
Loading…
Reference in New Issue
Block a user