summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-03-20 11:52:07 +0000
committerMatt Caswell <matt@openssl.org>2020-03-30 14:54:37 +0100
commit33328581b83e8e9f573f08f0e2e0d6b32d095857 (patch)
tree10f6643a2431c5ca74476197e274b71583bbc13f
parentc2146b57d296aa5b06e27cd8d76bbd040a3444b9 (diff)
Add the X509v3_cache_extensions() function
Various functions cause the results of processing extensions to be cached. The processing itself requires a libctx, and so this implicit caching means that the default ctx is used which can lead to failures. By explicitly caching the extensions we can specify the libctx to be used. Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/11409)
-rw-r--r--crypto/x509/v3_purp.c32
-rw-r--r--doc/man3/X509_check_ca.pod2
-rw-r--r--include/openssl/x509v3.h3
-rw-r--r--util/libcrypto.num1
4 files changed, 23 insertions, 15 deletions
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index eae837ea88..0d02090330 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -15,8 +15,6 @@
#include "crypto/x509.h"
#include "internal/tsan_assist.h"
-static void x509v3_cache_extensions(X509 *x);
-
static int check_ssl_ca(const X509 *x);
static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
int ca);
@@ -80,8 +78,7 @@ int X509_check_purpose(X509 *x, int id, int ca)
int idx;
const X509_PURPOSE *pt;
- x509v3_cache_extensions(x);
- if (x->ex_flags & EXFLAG_INVALID)
+ if (!X509v3_cache_extensions(x, NULL, NULL))
return -1;
/* Return if side-effect only call */
@@ -352,7 +349,7 @@ static int setup_crldp(X509 *x)
#define ns_reject(x, usage) \
(((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
-static void x509v3_cache_extensions(X509 *x)
+int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq)
{
BASIC_CONSTRAINTS *bs;
PROXY_CERT_INFO_EXTENSION *pci;
@@ -361,21 +358,25 @@ static void x509v3_cache_extensions(X509 *x)
EXTENDED_KEY_USAGE *extusage;
X509_EXTENSION *ex;
int i;
+ EVP_MD *sha1;
#ifdef tsan_ld_acq
/* fast lock-free check, see end of the function for details. */
if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached))
- return;
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
#endif
CRYPTO_THREAD_write_lock(x->lock);
if (x->ex_flags & EXFLAG_SET) {
CRYPTO_THREAD_unlock(x->lock);
- return;
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
}
- if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
- x->ex_flags |= EXFLAG_INVALID;
+ sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+ if (sha1 == NULL || !X509_digest(x, sha1, x->sha1_hash, NULL))
+ x->ex_flags |= EXFLAG_INVALID;
+ EVP_MD_free(sha1);
+
/* V1 should mean no extensions ... */
if (!X509_get_version(x))
x->ex_flags |= EXFLAG_V1;
@@ -538,6 +539,8 @@ static void x509v3_cache_extensions(X509 *x)
*/
#endif
CRYPTO_THREAD_unlock(x->lock);
+
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
}
/*-
@@ -590,7 +593,9 @@ void X509_set_proxy_pathlen(X509 *x, long l)
int X509_check_ca(X509 *x)
{
- x509v3_cache_extensions(x);
+ /* Note 0 normally means "not a CA" - but in this case means error. */
+ if (!X509v3_cache_extensions(x, NULL, NULL))
+ return 0;
return check_ca(x);
}
@@ -806,11 +811,8 @@ int X509_check_issued(X509 *issuer, X509 *subject)
X509_get_issuer_name(subject)))
return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
- x509v3_cache_extensions(issuer);
- if (issuer->ex_flags & EXFLAG_INVALID)
- return X509_V_ERR_UNSPECIFIED;
- x509v3_cache_extensions(subject);
- if (subject->ex_flags & EXFLAG_INVALID)
+ if (!X509v3_cache_extensions(issuer, NULL, NULL)
+ || !X509v3_cache_extensions(subject, NULL, NULL))
return X509_V_ERR_UNSPECIFIED;
if (subject->akid) {
diff --git a/doc/man3/X509_check_ca.pod b/doc/man3/X509_check_ca.pod
index 9fe01d1983..89adb2e3b6 100644
--- a/doc/man3/X509_check_ca.pod
+++ b/doc/man3/X509_check_ca.pod
@@ -24,6 +24,8 @@ B<keyUsage> extension with bit B<keyCertSign> set, but without
B<basicConstraints>, and 5 if it has outdated Netscape Certificate Type
extension telling that it is CA certificate.
+This function will also return 0 on error.
+
Actually, any nonzero value means that this certificate could have been
used to sign other certificates.
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index 63903efb20..e8efab2f08 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -572,6 +572,9 @@ GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, CONF_VALUE *cnf,
int is_nc);
+
+int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq);
+
void X509V3_conf_free(CONF_VALUE *val);
X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
diff --git a/util/libcrypto.num b/util/libcrypto.num
index fe6d69c2c5..9fc7cfcf18 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5029,3 +5029,4 @@ SRP_Calc_B_ex ? 3_0_0 EXIST::FUNCTION:SRP
SRP_Calc_u_ex ? 3_0_0 EXIST::FUNCTION:SRP
SRP_Calc_x_ex ? 3_0_0 EXIST::FUNCTION:SRP
SRP_Calc_client_key_ex ? 3_0_0 EXIST::FUNCTION:SRP
+X509v3_cache_extensions ? 3_0_0 EXIST::FUNCTION: