Skip to content

Commit

Permalink
Account for cipher auth with multiple cert slots
Browse files Browse the repository at this point in the history
  • Loading branch information
samuel40791765 committed Nov 1, 2024
1 parent 318c34c commit 05f7434
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 15 deletions.
43 changes: 29 additions & 14 deletions ssl/ssl_privkey.cc
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,14 @@ static bool ssl_public_key_rsa_pss_check(EVP_PKEY *pubkey, uint16_t sigalg) {
bool ssl_public_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
uint16_t sigalg) {
SSL *const ssl = hs->ssl;
if (!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg)) {
// We may have a public key that supports the signature algorithm, but the
// negotiated cipher needs to also allow it. This behavior is only done on
// TLS 1.2 servers in OpenSSL.
const uint32_t auth_allowed =
!SSL_is_server(ssl) || (hs->new_cipher->algorithm_auth &
(ssl_cipher_auth_mask_for_key(hs->local_pubkey.get()) | SSL_aGENERIC));
if (!auth_allowed ||
!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg)) {
return false;
}

Expand Down Expand Up @@ -457,20 +464,28 @@ bool ssl_cert_private_keys_supports_signature_algorithm(SSL_HANDSHAKE *hs,
for (size_t i = 0; i < cert->cert_private_keys.size(); i++) {
EVP_PKEY *private_key = cert->cert_private_keys[i].privatekey.get();
UniquePtr<EVP_PKEY> public_key =
ssl_cert_parse_leaf_pubkey(cert->cert_private_keys[i].chain.get());
if (private_key != nullptr && public_key != nullptr &&
pkey_supports_algorithm(ssl, private_key, sigalg)) {
if (!ssl_public_key_rsa_pss_check(public_key.get(), sigalg)) {
return false;
}
ssl_cert_parse_leaf_pubkey(cert->cert_private_keys[i].chain.get());
if (private_key != nullptr && public_key != nullptr) {
// We may have a private key that supports the signature algorithm,
// but we need to verify that the negotiated cipher allows it. This
// behavior is only done on TLS 1.2 servers in OpenSSL.
const uint32_t auth_allowed =
!SSL_is_server(ssl) ||
hs->new_cipher->algorithm_auth &
(ssl_cipher_auth_mask_for_key(private_key) | SSL_aGENERIC);
if (auth_allowed && pkey_supports_algorithm(ssl, private_key, sigalg)) {
if (!ssl_public_key_rsa_pss_check(public_key.get(), sigalg)) {
return false;
}

// Update certificate slot index if all checks have passed.
//
// If the server has a valid private key available to use, we switch to
// using that certificate for the rest of the connection.
cert->cert_private_key_idx = (int)i;
hs->local_pubkey = std::move(public_key);
return true;
// Update certificate slot index if all checks have passed.
//
// If the server has a valid private key available to use, we switch to
// using that certificate for the rest of the connection.
cert->cert_private_key_idx = (int)i;
hs->local_pubkey = std::move(public_key);
return true;
}
}
}
return false;
Expand Down
2 changes: 1 addition & 1 deletion ssl/ssl_x509.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static UniquePtr<STACK_OF(CRYPTO_BUFFER)> new_leafless_chain(void) {

// ssl_cert_set_chain sets elements 1.. of |cert->chain| to the serialised
// forms of elements of |chain|. It returns one on success or zero on error, in
// which case no change to |cert->chain| is made. It preverses the existing
// which case no change to |cert->chain| is made. It preserves the existing
// leaf from |cert->chain|, if any.
static bool ssl_cert_set_chain(CERT *cert, STACK_OF(X509) *chain) {
if (!ssl_cert_check_cert_private_keys_usage(cert)) {
Expand Down

0 comments on commit 05f7434

Please sign in to comment.