Decide whether or not to request client certificates early.
This allows us to merge two of the ssl3_digest_cached_records calls which were
almost, but not completely, redundant. Also catches a missing case: the buffer
may be discarded if doing session resumption but otherwise enabling client
authentication.
BUG=492371
Change-Id: I78e9a4a9cca665e89899ef97b815454c6f5c7e02
Reviewed-on: https://boringssl-review.googlesource.com/4885
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index c6aa03b..e49a3f0 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -273,25 +273,17 @@
case SSL3_ST_SW_CERT_REQ_A:
case SSL3_ST_SW_CERT_REQ_B:
- if (/* don't request cert unless asked for it: */
- !(s->verify_mode & SSL_VERIFY_PEER) ||
- /* With normal PSK Certificates and
- * Certificate Requests are omitted */
- (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
- /* no cert request */
- skip = 1;
- s->s3->tmp.cert_request = 0;
- s->state = SSL3_ST_SW_SRVR_DONE_A;
- } else {
- s->s3->tmp.cert_request = 1;
+ if (s->s3->tmp.cert_request) {
dtls1_start_timer(s);
ret = ssl3_send_certificate_request(s);
if (ret <= 0) {
goto end;
}
- s->state = SSL3_ST_SW_SRVR_DONE_A;
- s->init_num = 0;
+ } else {
+ skip = 1;
}
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+ s->init_num = 0;
break;
case SSL3_ST_SW_SRVR_DONE_A:
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index f997c86..df46d3d 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -337,31 +337,16 @@
case SSL3_ST_SW_CERT_REQ_A:
case SSL3_ST_SW_CERT_REQ_B:
- if (/* don't request cert unless asked for it: */
- !(s->verify_mode & SSL_VERIFY_PEER) ||
- /* Don't request a certificate if an obc was presented */
- ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
- s->s3->tlsext_channel_id_valid) ||
- /* With normal PSK Certificates and
- * Certificate Requests are omitted */
- (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
- /* no cert request */
- skip = 1;
- s->s3->tmp.cert_request = 0;
- s->state = SSL3_ST_SW_SRVR_DONE_A;
- if (s->s3->handshake_buffer &&
- !ssl3_digest_cached_records(s, free_handshake_buffer)) {
- return -1;
- }
- } else {
- s->s3->tmp.cert_request = 1;
+ if (s->s3->tmp.cert_request) {
ret = ssl3_send_certificate_request(s);
if (ret <= 0) {
goto end;
}
- s->state = SSL3_ST_SW_SRVR_DONE_A;
- s->init_num = 0;
+ } else {
+ skip = 1;
}
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+ s->init_num = 0;
break;
case SSL3_ST_SW_SRVR_DONE_A:
@@ -1069,12 +1054,27 @@
goto f_err;
}
s->s3->tmp.new_cipher = c;
+
+ /* Determine whether to request a client certificate. */
+ s->s3->tmp.cert_request = !!(s->verify_mode & SSL_VERIFY_PEER);
+ /* Only request a certificate if Channel ID isn't negotiated. */
+ if ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+ s->s3->tlsext_channel_id_valid) {
+ s->s3->tmp.cert_request = 0;
+ }
+ /* Plain PSK forbids Certificate and CertificateRequest. */
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) {
+ s->s3->tmp.cert_request = 0;
+ }
} else {
/* Session-id reuse */
s->s3->tmp.new_cipher = s->session->cipher;
+ s->s3->tmp.cert_request = 0;
}
- if ((!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) &&
+ /* In TLS 1.2, client authentication requires hashing the handshake transcript
+ * under a different hash. Otherwise, release the handshake buffer. */
+ if ((!SSL_USE_SIGALGS(s) || !s->s3->tmp.cert_request) &&
!ssl3_digest_cached_records(s, free_handshake_buffer)) {
goto f_err;
}