summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>2020-12-30 09:49:20 +0100
committerDr. David von Oheimb <dev@ddvo.net>2021-01-13 11:19:17 +0100
commitf2a0458731f15fd4d45f5574a221177f4591b1d8 (patch)
tree85b1a3cba117540231cad28e1e64062c50807f83 /crypto
parent3339606a38cc9023c807428b429e01cfa1fde4d9 (diff)
X509_cmp(): Fix comparison in case x509v3_cache_extensions() failed to due to invalid cert
This is the upstream fix for #13698 reported for v1.1.1 Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/13755)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/x509/v3_purp.c16
-rw-r--r--crypto/x509/x509_cmp.c24
-rw-r--r--crypto/x509/x509_lu.c2
-rw-r--r--crypto/x509/x_all.c4
-rw-r--r--crypto/x509/x_crl.c4
5 files changed, 29 insertions, 21 deletions
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index a3673e63fa..d9ce52faa4 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -387,6 +387,7 @@ static int check_sig_alg_match(const EVP_PKEY *pkey, const X509 *subject)
/*
* Cache info on various X.509v3 extensions and further derived information,
* e.g., if cert 'x' is self-issued, in x->ex_flags and other internal fields.
+ * x->sha1_hash is filled in, or else EXFLAG_NO_FINGERPRINT is set in x->flags.
* X509_SIG_INFO_VALID is set in x->flags if x->siginf was filled successfully.
* Set EXFLAG_INVALID and return 0 in case the certificate is invalid.
*/
@@ -411,15 +412,12 @@ int x509v3_cache_extensions(X509 *x)
CRYPTO_THREAD_unlock(x->lock);
return (x->ex_flags & EXFLAG_INVALID) == 0;
}
- ERR_set_mark();
/* Cache the SHA1 digest of the cert */
if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
- /*
- * Note that the cert is marked invalid also on internal malloc failure
- * or on failure of EVP_MD_fetch(), potentially called by X509_digest().
- */
- x->ex_flags |= EXFLAG_INVALID;
+ x->ex_flags |= EXFLAG_NO_FINGERPRINT;
+
+ ERR_set_mark();
/* V1 should mean no extensions ... */
if (X509_get_version(x) == 0)
@@ -625,11 +623,13 @@ int x509v3_cache_extensions(X509 *x)
*/
#endif
ERR_pop_to_mark();
- if ((x->ex_flags & EXFLAG_INVALID) == 0) {
+ if ((x->ex_flags & (EXFLAG_INVALID | EXFLAG_NO_FINGERPRINT)) == 0) {
CRYPTO_THREAD_unlock(x->lock);
return 1;
}
- ERR_raise(ERR_LIB_X509, X509V3_R_INVALID_CERTIFICATE);
+ if ((x->ex_flags & EXFLAG_INVALID) != 0)
+ ERR_raise(ERR_LIB_X509, X509V3_R_INVALID_CERTIFICATE);
+ /* If computing sha1_hash failed the error queue already reflects this. */
err:
x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 1231fb4be1..d18d1e2b67 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -81,7 +81,13 @@ int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
- int rv = memcmp(a->sha1_hash, b->sha1_hash, 20);
+ int rv;
+
+ if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0
+ && (b->flags & EXFLAG_NO_FINGERPRINT) == 0)
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ else
+ return -2;
return rv < 0 ? -1 : rv > 0;
}
@@ -140,19 +146,21 @@ unsigned long X509_subject_name_hash_old(X509 *x)
*/
int X509_cmp(const X509 *a, const X509 *b)
{
- int rv;
+ int rv = 0;
if (a == b) /* for efficiency */
return 0;
- /* ensure hash is valid */
- if (X509_check_purpose((X509 *)a, -1, 0) != 1)
- return -2;
- if (X509_check_purpose((X509 *)b, -1, 0) != 1)
- return -2;
- rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ /* attempt to compute cert hash */
+ (void)X509_check_purpose((X509 *)a, -1, 0);
+ (void)X509_check_purpose((X509 *)b, -1, 0);
+
+ if ((a->ex_flags & EXFLAG_NO_FINGERPRINT) == 0
+ && (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0)
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv != 0)
return rv < 0 ? -1 : 1;
+
/* Check for match against stored encoding too */
if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
if (a->cert_info.enc.len < b->cert_info.enc.len)
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index eb730bb24d..00d45ea809 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -702,7 +702,7 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
if (!X509_cmp(obj->data.x509, x->data.x509))
return obj;
} else if (x->type == X509_LU_CRL) {
- if (!X509_CRL_match(obj->data.crl, x->data.crl))
+ if (X509_CRL_match(obj->data.crl, x->data.crl) == 0)
return obj;
} else
return obj;
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 680a1cf48c..9d9079f7f5 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -392,7 +392,7 @@ int X509_digest(const X509 *cert, const EVP_MD *md, unsigned char *data,
unsigned int *len)
{
if (EVP_MD_is_a(md, SN_sha1) && (cert->ex_flags & EXFLAG_SET) != 0
- && (cert->ex_flags & EXFLAG_INVALID) == 0) {
+ && (cert->ex_flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1 and we already computed it. */
if (len != NULL)
*len = sizeof(cert->sha1_hash);
@@ -436,7 +436,7 @@ int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0
- && (data->flags & EXFLAG_INVALID) == 0) {
+ && (data->flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1; always computed in CRL d2i. */
if (len != NULL)
*len = sizeof(data->sha1_hash);
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index 164d425ab2..ef54a9a3cd 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -147,7 +147,7 @@ static int crl_set_issuers(X509_CRL *crl)
/*
* The X509_CRL structure needs a bit of customisation. Cache some extensions
- * and hash of the whole CRL.
+ * and hash of the whole CRL or set EXFLAG_NO_FINGERPRINT if this fails.
*/
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
@@ -185,7 +185,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
case ASN1_OP_D2I_POST:
if (!X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL))
- crl->flags |= EXFLAG_INVALID;
+ crl->flags |= EXFLAG_NO_FINGERPRINT;
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, &i,
NULL);