[openssl] master update

Matt Caswell matt at openssl.org
Mon Mar 30 14:01:55 UTC 2020


The branch master has been updated
       via  e15d369781eb2e97656ebbabef576b8079d86b8c (commit)
       via  9f0f53b7db502ad338baa45edfd163d0ca7aabc5 (commit)
       via  33328581b83e8e9f573f08f0e2e0d6b32d095857 (commit)
      from  c2146b57d296aa5b06e27cd8d76bbd040a3444b9 (commit)


- Log -----------------------------------------------------------------
commit e15d369781eb2e97656ebbabef576b8079d86b8c
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 25 16:00:42 2020 +0000

    Document the new X509v3_cache_extensions() function
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11409)

commit 9f0f53b7db502ad338baa45edfd163d0ca7aabc5
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Mar 20 11:55:19 2020 +0000

    Explicitly cache X509v3 extensions in libssl
    
    Caching the X509v3 extensions requires an explicit libctx. We do that
    where required in libssl.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11409)

commit 33328581b83e8e9f573f08f0e2e0d6b32d095857
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Mar 20 11:52:07 2020 +0000

    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 at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11409)

-----------------------------------------------------------------------

Summary of changes:
 crypto/x509/v3_purp.c                | 32 ++++++++++++++-------------
 doc/man3/X509_check_ca.pod           |  2 ++
 doc/man3/X509v3_cache_extensions.pod | 43 ++++++++++++++++++++++++++++++++++++
 include/openssl/x509v3.h             |  3 +++
 ssl/s3_lib.c                         |  5 +++++
 ssl/ssl_cert.c                       | 13 +++++++++--
 ssl/ssl_rsa.c                        |  9 ++++++++
 util/libcrypto.num                   |  1 +
 8 files changed, 91 insertions(+), 17 deletions(-)
 create mode 100644 doc/man3/X509v3_cache_extensions.pod

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/doc/man3/X509v3_cache_extensions.pod b/doc/man3/X509v3_cache_extensions.pod
new file mode 100644
index 0000000000..952a8c2ead
--- /dev/null
+++ b/doc/man3/X509v3_cache_extensions.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+X509v3_cache_extensions
+- process any extensions in an X509 object
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+This function processes any X509v3 extensions that might be present in an X509
+object and caches the result of that processing. Many OpenSSL functions that use
+an X509 object will cause extensions to be processed and cached implicitly. If
+this is done implicitly then the default library context and property query
+string will be used. In some cases it may be desirable to use some other library
+context and property query string. If so then an application can call
+X509v3_cache_extensions() explicitly. This should be done before any function
+that needs to use those extensions is called - otherwise calling
+X509v3_cache_extensions() will have no effect. Typically this means calling this
+soon after creation of the X509 object. The X509 object to be processed is
+given in I<x> and the library context and property query string to use are given
+in I<libctx> and I<propq>.
+
+=head1 RETURN VALUES
+
+This function returns 0 if the extensions are invalid or an error occurred.
+Otherwise it returns 1.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
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/ssl/s3_lib.c b/ssl/s3_lib.c
index ffdf3a90fb..9060ee38f0 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -17,6 +17,7 @@
 #include <openssl/dh.h>
 #include <openssl/rand.h>
 #include <openssl/trace.h>
+#include <openssl/x509v3.h>
 #include "internal/cryptlib.h"
 
 #define TLS13_NUM_CIPHERS       OSSL_NELEM(tls13_ciphers)
@@ -3947,6 +3948,10 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
                 return 0;
             }
         }
+        if (!X509v3_cache_extensions((X509 *)parg, ctx->libctx, ctx->propq)) {
+            SSLerr(0, ERR_LIB_X509);
+            return 0;
+        }
         if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) {
             SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
             return 0;
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 56e3642fbd..f753bbee38 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -253,11 +253,20 @@ void ssl_cert_free(CERT *c)
 int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
 {
     int i, r;
-    CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
+    CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key;
+    SSL_CTX *realctx = s != NULL ? s->ctx : ctx;
+
     if (!cpk)
         return 0;
     for (i = 0; i < sk_X509_num(chain); i++) {
-        r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0);
+        X509 *x = sk_X509_value(chain, i);
+
+        if (!X509v3_cache_extensions(x, realctx->libctx, realctx->propq)) {
+            SSLerr(0, ERR_LIB_X509);
+            return 0;
+        }
+
+        r = ssl_security_cert(s, ctx, x, 0, 0);
         if (r != 1) {
             SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
             return 0;
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index b32a7b90bb..3a222e5571 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -14,6 +14,7 @@
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
+#include <openssl/x509v3.h>
 #include <openssl/pem.h>
 
 static int ssl_set_cert(CERT *c, X509 *x509);
@@ -31,6 +32,10 @@ int SSL_use_certificate(SSL *ssl, X509 *x)
         SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
+    if (!X509v3_cache_extensions(x, ssl->ctx->libctx, ssl->ctx->propq)) {
+        SSLerr(0, ERR_LIB_X509);
+        return 0;
+    }
     rv = ssl_security_cert(ssl, NULL, x, 0, 1);
     if (rv != 1) {
         SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv);
@@ -305,6 +310,10 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
+    if (!X509v3_cache_extensions(x, ctx->libctx, ctx->propq)) {
+        SSLerr(0, ERR_LIB_X509);
+        return 0;
+    }
     rv = ssl_security_cert(NULL, ctx, x, 0, 1);
     if (rv != 1) {
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv);
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:


More information about the openssl-commits mailing list