Implement ChannelID for TLS 1.3.
Channel ID for TLS 1.3 uses the same digest construction as
CertificateVerify. This message is signed with the Channel ID key and
put in the same handshake message (with the same format) as in TLS 1.2.
BUG=103
Change-Id: Ia5b2dffe5a39c39db0cecb0aa6bdc328e53accc2
Reviewed-on: https://boringssl-review.googlesource.com/11420
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>
diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c
index 87ccdc4..3b85442 100644
--- a/ssl/tls13_client.c
+++ b/ssl/tls13_client.c
@@ -41,6 +41,7 @@
state_send_client_certificate,
state_send_client_certificate_verify,
state_complete_client_certificate_verify,
+ state_send_channel_id,
state_send_client_finished,
state_flush,
state_done,
@@ -519,7 +520,7 @@
static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
/* The peer didn't request a certificate. */
if (!ssl->s3->hs->cert_request) {
- hs->state = state_send_client_finished;
+ hs->state = state_send_channel_id;
return ssl_hs_ok;
}
@@ -566,13 +567,13 @@
int is_first_run) {
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
- hs->state = state_send_client_finished;
+ hs->state = state_send_channel_id;
return ssl_hs_ok;
}
switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
case ssl_private_key_success:
- hs->state = state_send_client_finished;
+ hs->state = state_send_channel_id;
return ssl_hs_write_message;
case ssl_private_key_retry:
@@ -587,6 +588,32 @@
return ssl_hs_error;
}
+static enum ssl_hs_wait_t do_send_channel_id(SSL *ssl, SSL_HANDSHAKE *hs) {
+ if (!ssl->s3->tlsext_channel_id_valid) {
+ hs->state = state_send_client_finished;
+ return ssl_hs_ok;
+ }
+
+ if (!ssl_do_channel_id_callback(ssl)) {
+ return ssl_hs_error;
+ }
+
+ if (ssl->tlsext_channel_id_private == NULL) {
+ return ssl_hs_channel_id_lookup;
+ }
+
+ CBB cbb, body;
+ if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+ !tls1_write_channel_id(ssl, &body) ||
+ !ssl->method->finish_message(ssl, &cbb)) {
+ CBB_cleanup(&cbb);
+ return ssl_hs_error;
+ }
+
+ hs->state = state_send_client_finished;
+ return ssl_hs_write_message;
+}
+
static enum ssl_hs_wait_t do_send_client_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_prepare_finished(ssl)) {
return ssl_hs_error;
@@ -651,10 +678,13 @@
break;
case state_send_client_certificate_verify:
ret = do_send_client_certificate_verify(ssl, hs, 1 /* first run */);
- break;
+ break;
case state_complete_client_certificate_verify:
ret = do_send_client_certificate_verify(ssl, hs, 0 /* complete */);
- break;
+ break;
+ case state_send_channel_id:
+ ret = do_send_channel_id(ssl, hs);
+ break;
case state_send_client_finished:
ret = do_send_client_finished(ssl, hs);
break;