From ffd2df135a5d9f6d2627bd125f362298430fdc06 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 18 Dec 2018 09:14:51 +0100 Subject: [PATCH] X509_check_issued: check that signature algo matches signing key algo This implements 3.5.18 "Consistent Public Key and Signature Algorithms" from RFC 4158 "Internet X.509 Public Key Infrastructure: Certification Path Building" Ref: https://tools.ietf.org/html/rfc4158#section-3.5.18 Fixes #7899 Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/7919) --- crypto/x509/x509_txt.c | 4 ++++ crypto/x509v3/v3_purp.c | 23 +++++++++++++++++++++-- include/openssl/x509_vfy.h | 4 ++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 299c355123..767d33b48a 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -174,6 +174,10 @@ const char *X509_verify_cert_error_string(long n) return "OCSP verification failed"; case X509_V_ERR_OCSP_CERT_UNKNOWN: return "OCSP unknown cert"; + case X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH: + return "Subject signature algorithm and issuer public key algorithm mismatch"; + case X509_V_ERR_NO_ISSUER_PUBLIC_KEY: + return "Issuer certificate doesn't have a public key"; default: /* Printing an error number into a static buffer is not thread-safe */ diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 2080adbe67..d0ac7e6ed9 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -764,8 +764,9 @@ static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) * subject name. * These are: * 1. Check issuer_name(subject) == subject_name(issuer) - * 2. If akid(subject) exists check it matches issuer - * 3. If key_usage(issuer) exists check it supports certificate signing + * 2. If akid(subject) exists, check that it matches issuer + * 3. Check that issuer public key algorithm matches subject signature algorithm + * 4. If key_usage(issuer) exists, check that it supports certificate signing * returns 0 for OK, positive for reason for mismatch, reasons match * codes for X509_verify_cert() */ @@ -785,6 +786,24 @@ int X509_check_issued(X509 *issuer, X509 *subject) return ret; } + { + /* + * Check if the subject signature algorithm matches the issuer's PUBKEY + * algorithm + */ + EVP_PKEY *i_pkey = X509_get0_pubkey(issuer); + X509_ALGOR *s_algor = &subject->cert_info.signature; + int s_pknid = NID_undef, s_mdnid = NID_undef; + + if (i_pkey == NULL) + return X509_V_ERR_NO_ISSUER_PUBLIC_KEY; + + if (!OBJ_find_sigid_algs(OBJ_obj2nid(s_algor->algorithm), + &s_mdnid, &s_pknid) + || EVP_PKEY_type(s_pknid) != EVP_PKEY_base_id(i_pkey)) + return X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH; + } + if (subject->ex_flags & EXFLAG_PROXY) { if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h index cfc8c89aac..0df8028233 100644 --- a/include/openssl/x509_vfy.h +++ b/include/openssl/x509_vfy.h @@ -185,6 +185,10 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); # define X509_V_ERR_OCSP_VERIFY_FAILED 74 /* Couldn't verify cert through OCSP */ # define X509_V_ERR_OCSP_CERT_UNKNOWN 75 /* Certificate wasn't recognized by the OCSP responder */ +# define X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH 76 +# define X509_V_ERR_NO_ISSUER_PUBLIC_KEY 77 + + /* Certificate verify flags */ # if !OPENSSL_API_1_1_0 -- 2.25.1