Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions crypto/x509/x509_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4874,11 +4874,13 @@ TEST(X509Test, SignatureVerification) {
Verify(leaf.valid.get(), {root.valid.get()},
{intermediate.bad_key_type.get()}, {}));

// Bad keys in the leaf are ignored. The leaf's key is used by the caller.
EXPECT_EQ(X509_V_OK, Verify(leaf.bad_key.get(), {root.valid.get()},
{intermediate.valid.get()}, {}));
EXPECT_EQ(X509_V_OK, Verify(leaf.bad_key_type.get(), {root.valid.get()},
{intermediate.valid.get()}, {}));
// Bad keys in the leaf are rejected.
EXPECT_EQ(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY,
Verify(leaf.bad_key.get(), {root.valid.get()},
{intermediate.valid.get()}, {}));
EXPECT_EQ(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY,
Verify(leaf.bad_key_type.get(), {root.valid.get()},
{intermediate.valid.get()}, {}));

// At the time we go to verify signatures, it is possible that we have a
// single-element certificate chain with a certificate that isn't self-signed.
Expand Down
2 changes: 2 additions & 0 deletions crypto/x509/x509_txt.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ const char *X509_verify_cert_error_string(long err) {
return "Invalid certificate verification context";
case X509_V_ERR_STORE_LOOKUP:
return "Issuer certificate lookup error";
case X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:
return "Unable to get leaf certificate's public key";

default:
return "unknown certificate verification error";
Expand Down
14 changes: 14 additions & 0 deletions crypto/x509/x509_vfy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,20 @@ static int internal_verify(X509_STORE_CTX *ctx) {
xs = sk_X509_value(ctx->chain, n);
}
}

// Check that the final certificate subject (leaf)
// has a public key we actually support. Otherwise
// we shouldn't consider the certificate okay.
//
// This covers situations like invalid curves or points.
EVP_PKEY *pkey = X509_get0_pubkey(xs);
if(pkey == NULL) {
ctx->error = X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY;
ctx->current_cert = xi;
ok = 0;
goto end;
}

ok = 1;
end:
return ok;
Expand Down
3 changes: 2 additions & 1 deletion include/openssl/x509.h
Original file line number Diff line number Diff line change
Expand Up @@ -2736,6 +2736,7 @@ OPENSSL_EXPORT void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x);
#define X509_V_ERR_EE_KEY_TOO_SMALL 68
#define X509_V_ERR_CA_KEY_TOO_SMALL 69
#define X509_V_ERR_CA_MD_TOO_WEAK 70
#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 71

// X509_STORE_CTX_get_error, after |X509_verify_cert| returns, returns
// |X509_V_OK| if verification succeeded or an |X509_V_ERR_*| describing why
Expand Down Expand Up @@ -3086,7 +3087,7 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
// X509_CHECK_FLAG_NO_WILDCARDS disables wildcard matching for DNS names.
#define X509_CHECK_FLAG_NO_WILDCARDS 0x2

// X509_CHECK_FLAG_NEVER_CHECK_SUBJECT constrains host name patterns passed to |X509_check_host|
// X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS constrains host name patterns passed to |X509_check_host|
// starting with '.' to only match a single label / subdomain.
//
// For example, by default the host name '.example.com' would match a certificate DNS name like
Expand Down
1 change: 1 addition & 0 deletions ssl/ssl_x509.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,7 @@ int SSL_alert_from_verify_result(long result) {
return SSL_AD_HANDSHAKE_FAILURE;

case X509_V_ERR_INVALID_PURPOSE:
case X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:
return SSL_AD_UNSUPPORTED_CERTIFICATE;

default:
Expand Down
Loading