Support delegated credentials verison 06
This version adds signature algorithms to the extension
Change-Id: I91dc78d33ee81cb7a6221c7bdeefc8ea460a2d6c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42424
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 07a39d2..96ba53b 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -953,6 +953,18 @@
OPENSSL_EXPORT size_t
SSL_get0_peer_verify_algorithms(const SSL *ssl, const uint16_t **out_sigalgs);
+// SSL_get0_peer_delegation_algorithms sets |*out_sigalgs| to an array
+// containing the signature algorithms the peer is willing to use with delegated
+// credentials. It returns the length of the array. If not sent, the empty
+// array is returned.
+//
+// The behavior of this function is undefined except during the callbacks set by
+// by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or when the
+// handshake is paused because of them.
+OPENSSL_EXPORT size_t
+SSL_get0_peer_delegation_algorithms(const SSL *ssl,
+ const uint16_t **out_sigalgs);
+
// SSL_certs_clear resets the private key, leaf certificate, and certificate
// chain of |ssl|.
OPENSSL_EXPORT void SSL_certs_clear(SSL *ssl);
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 64ed762..13545dd 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -232,9 +232,8 @@
// ExtensionType value from RFC5746
#define TLSEXT_TYPE_renegotiate 0xff01
-// ExtensionType value from draft-ietf-tls-subcerts. This is not an IANA defined
-// extension number.
-#define TLSEXT_TYPE_delegated_credential 0xff02
+// ExtensionType value from draft-ietf-tls-subcerts.
+#define TLSEXT_TYPE_delegated_credential 0x22
// ExtensionType value from RFC6962
#define TLSEXT_TYPE_certificate_timestamp 18
diff --git a/ssl/internal.h b/ssl/internal.h
index 2000409..e08505f 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1650,6 +1650,10 @@
// advertise this extension to the client.
Array<uint16_t> peer_supported_group_list;
+ // peer_delegated_credential_sigalgs are the signature algorithms the peer
+ // supports with delegated credentials.
+ Array<uint16_t> peer_delegated_credential_sigalgs;
+
// peer_key is the peer's ECDH key for a TLS 1.2 client.
Array<uint8_t> peer_key;
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 6bac3a9..c64303a 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -821,16 +821,13 @@
}
// Check that the DC signature algorithm is supported by the peer.
- Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs);
- bool sigalg_found = false;
+ Span<const uint16_t> peer_sigalgs = hs->peer_delegated_credential_sigalgs;
for (uint16_t peer_sigalg : peer_sigalgs) {
if (dc->expected_cert_verify_algorithm == peer_sigalg) {
- sigalg_found = true;
- break;
+ return true;
}
}
-
- return sigalg_found;
+ return false;
}
bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs) {
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 90c265e..10a97ea 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -2360,6 +2360,16 @@
return sigalgs.size();
}
+size_t SSL_get0_peer_delegation_algorithms(const SSL *ssl,
+ const uint16_t **out_sigalgs){
+ Span<const uint16_t> sigalgs;
+ if (ssl->s3->hs != nullptr) {
+ sigalgs = ssl->s3->hs->peer_delegated_credential_sigalgs;
+ }
+ *out_sigalgs = sigalgs.data();
+ return sigalgs.size();
+}
+
EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
if (!ssl->config) {
assert(ssl->config);
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index f274b11..4a2bbcf 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -2673,20 +2673,22 @@
static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
- assert(TLSEXT_TYPE_delegated_credential == 0xff02);
- // TODO: Check that the extension is empty.
- //
- // As of draft-03, the client sends an empty extension in order indicate
- // support for delegated credentials. This could change, however, since the
- // spec is not yet finalized. This assertion is here to remind us to enforce
- // this check once the extension ID is assigned.
-
if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
// Don't use delegated credentials unless we're negotiating TLS 1.3 or
// higher.
return true;
}
+ // The contents of the extension are the signature algorithms the client will
+ // accept for a delegated credential.
+ CBS sigalg_list;
+ if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) ||
+ CBS_len(&sigalg_list) == 0 ||
+ CBS_len(contents) != 0 ||
+ !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
+ return false;
+ }
+
hs->delegated_credential_requested = true;
return true;
}
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 3a104d9..6a744db 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -124,7 +124,7 @@
extensionRenegotiationInfo uint16 = 0xff01
extensionQUICTransportParams uint16 = 0xffa5 // draft-ietf-quic-tls-13
extensionChannelID uint16 = 30032 // not IANA assigned
- extensionDelegatedCredentials uint16 = 0xff02 // not IANA assigned
+ extensionDelegatedCredentials uint16 = 0x22 // draft-ietf-tls-subcerts-06
)
// TLS signaling cipher suite values
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index a1ce421..9d3b6bc 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -596,7 +596,11 @@
}
if m.delegatedCredentials {
extensions.addU16(extensionDelegatedCredentials)
- extensions.addU16(0) // Length is always 0
+ body := extensions.addU16LengthPrefixed()
+ signatureSchemeList := body.addU16LengthPrefixed()
+ for _, sigAlg := range m.signatureAlgorithms {
+ signatureSchemeList.addU16(uint16(sigAlg))
+ }
}
// The PSK extension must be last. See https://tools.ietf.org/html/rfc8446#section-4.2.11
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 5527f96..aac4567 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -9499,7 +9499,8 @@
signatureRSAPKCS1WithSHA1,
},
Bugs: ProtocolBugs{
- NoSignatureAlgorithms: true,
+ NoSignatureAlgorithms: true,
+ DisableDelegatedCredentials: true,
},
},
shouldFail: true,