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,