Update crypto negotation to draft 15.
BUG=77
Change-Id: If568412655aae240b072c29d763a5b17bb5ca3f7
Reviewed-on: https://boringssl-review.googlesource.com/10840
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 9e146e6..984cc5c 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -51,32 +51,11 @@
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
-static int resolve_psk_secret(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
- if (ssl->s3->tmp.new_cipher->algorithm_auth != SSL_aPSK) {
- return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
- }
-
- uint8_t resumption_psk[EVP_MAX_MD_SIZE];
- if (!tls13_resumption_psk(ssl, resumption_psk, hs->hash_len,
- ssl->s3->new_session) ||
- !tls13_advance_key_schedule(ssl, resumption_psk, hs->hash_len)) {
- return 0;
- }
-
- return 1;
-}
-
static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
struct ssl_early_callback_ctx *early_ctx) {
*out_need_retry = 0;
- SSL_HANDSHAKE *hs = ssl->s3->hs;
- if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
- return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
- }
-
+ /* We only support connections that include an ECDHE key exchange. */
CBS key_share;
if (!ssl_early_callback_get_extension(early_ctx, &key_share,
TLSEXT_TYPE_key_share)) {
@@ -139,13 +118,11 @@
return 0;
}
- uint16_t resumption_cipher;
if (session != NULL &&
/* Only resume if the session's version matches. */
(session->ssl_version != ssl->version ||
- !ssl_cipher_get_ecdhe_psk_cipher(session->cipher, &resumption_cipher) ||
- !ssl_client_cipher_list_contains_cipher(&client_hello,
- resumption_cipher))) {
+ !ssl_client_cipher_list_contains_cipher(
+ &client_hello, (uint16_t)SSL_CIPHER_get_id(session->cipher)))) {
SSL_SESSION_free(session);
session = NULL;
}
@@ -227,39 +204,32 @@
}
ssl->s3->new_session->cipher = cipher;
- ssl->s3->tmp.new_cipher = cipher;
- } else {
- uint16_t resumption_cipher;
- if (!ssl_cipher_get_ecdhe_psk_cipher(ssl->s3->new_session->cipher,
- &resumption_cipher)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- return ssl_hs_error;
- }
- ssl->s3->tmp.new_cipher = SSL_get_cipher_by_value(resumption_cipher);
}
+ ssl->s3->tmp.new_cipher = ssl->s3->new_session->cipher;
ssl->method->received_flight(ssl);
- /* The PRF hash is now known. Set up the key schedule and hash the
- * ClientHello. */
- size_t resumption_ctx_len =
+
+ /* The PRF hash is now known. */
+ size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
+
+ /* Derive resumption material. */
+ uint8_t resumption_ctx[EVP_MAX_MD_SIZE] = {0};
+ uint8_t psk_secret[EVP_MAX_MD_SIZE] = {0};
if (ssl->s3->session_reused) {
- uint8_t resumption_ctx[EVP_MAX_MD_SIZE];
- if (!tls13_resumption_context(ssl, resumption_ctx, resumption_ctx_len,
+ if (!tls13_resumption_context(ssl, resumption_ctx, hash_len,
ssl->s3->new_session) ||
- !tls13_init_key_schedule(ssl, resumption_ctx, resumption_ctx_len)) {
- return ssl_hs_error;
- }
- } else {
- if (!tls13_init_key_schedule(ssl, kZeroes, resumption_ctx_len)) {
+ !tls13_resumption_psk(ssl, psk_secret, hash_len,
+ ssl->s3->new_session)) {
return ssl_hs_error;
}
}
- /* Resolve PSK and incorporate it into the secret. */
- if (!resolve_psk_secret(ssl)) {
+ /* Set up the key schedule, hash in the ClientHello, and incorporate the PSK
+ * into the running secret. */
+ if (!tls13_init_key_schedule(ssl, resumption_ctx, hash_len) ||
+ !tls13_advance_key_schedule(ssl, psk_secret, hash_len)) {
return ssl_hs_error;
}
@@ -345,14 +315,27 @@
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ssl_ext_pre_shared_key_add_serverhello(ssl, &extensions) ||
- !ssl_ext_key_share_add_serverhello(ssl, &extensions) ||
- !ssl->method->finish_message(ssl, &cbb)) {
- CBB_cleanup(&cbb);
- return ssl_hs_error;
+ !ssl_ext_key_share_add_serverhello(ssl, &extensions)) {
+ goto err;
+ }
+
+ if (!ssl->s3->session_reused) {
+ if (!CBB_add_u16(&extensions, TLSEXT_TYPE_signature_algorithms) ||
+ !CBB_add_u16(&extensions, 0)) {
+ goto err;
+ }
+ }
+
+ if (!ssl->method->finish_message(ssl, &cbb)) {
+ goto err;
}
hs->state = state_send_encrypted_extensions;
return ssl_hs_write_message;
+
+err:
+ CBB_cleanup(&cbb);
+ return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
@@ -378,8 +361,8 @@
SSL_HANDSHAKE *hs) {
/* Determine whether to request a client certificate. */
ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
- /* CertificateRequest may only be sent in certificate-based ciphers. */
- if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ /* CertificateRequest may only be sent in non-resumption handshakes. */
+ if (ssl->s3->session_reused) {
ssl->s3->tmp.cert_request = 0;
}
@@ -424,7 +407,7 @@
static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
- if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ if (ssl->s3->session_reused) {
hs->state = state_send_server_finished;
return ssl_hs_ok;
}