[openssl] master update

dev at ddvo.net dev at ddvo.net
Fri Sep 11 05:47:04 UTC 2020


The branch master has been updated
       via  82bdd6419361136e7be533d31a990ba0476fced3 (commit)
       via  e41a2c4c609a8f64dfab2d832e975b0b37ff286d (commit)
       via  d72c8b457b77c31a20cf66e9c92aa19a4b7b5884 (commit)
       via  bb377c8d6c61920d889b961bd5c862eaac8b28e4 (commit)
       via  da6c691d6d417ad413fdc1e7a7a183d005e7fefd (commit)
       via  89f13ca4342be5b541b0885e3058617e5cce0de8 (commit)
       via  8a639b9d7234ed490f85ea46e4e8c74620452acd (commit)
       via  1e41dadfa7b9f792ed0f4714a3d3d36f070cf30e (commit)
      from  b0a4cbead384e2ac8dbb697795ace242e1b07c18 (commit)


- Log -----------------------------------------------------------------
commit 82bdd6419361136e7be533d31a990ba0476fced3
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Sep 8 09:39:33 2020 +0200

    check_chain_extensions(): Require X.509 v3 if extensions are present
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit e41a2c4c609a8f64dfab2d832e975b0b37ff286d
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Sep 7 22:38:46 2020 +0200

    check_chain_extensions(): Change exclusion condition w.r.t. RFC 6818 section 2
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit d72c8b457b77c31a20cf66e9c92aa19a4b7b5884
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Aug 26 09:45:11 2020 +0200

    x509_vfy.c: Make sure that strict checks are not done for self-issued EE certs
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit bb377c8d6c61920d889b961bd5c862eaac8b28e4
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Aug 25 16:58:36 2020 +0200

    check_chain_extensions(): Add check that CA cert includes key usage extension
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit da6c691d6d417ad413fdc1e7a7a183d005e7fefd
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Aug 25 16:46:18 2020 +0200

    check_chain_extensions(): Add check that on empty Subject the SAN must be marked critical
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit 89f13ca4342be5b541b0885e3058617e5cce0de8
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Aug 25 16:13:40 2020 +0200

    check_chain_extensions(): Add check that AKID and SKID are not marked critical
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit 8a639b9d7234ed490f85ea46e4e8c74620452acd
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Aug 25 15:37:46 2020 +0200

    check_chain_extensions(): Add check that Basic Constraints of CA cert are marked critical
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

commit 1e41dadfa7b9f792ed0f4714a3d3d36f070cf30e
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Sat Jun 27 16:16:12 2020 +0200

    Extend X509 cert checks and error reporting in v3_{purp,crld}.c and x509_{set,vfy}.c
    
    add various checks for malformedness to static check_chain_extensions() in x509_vfc.c
    improve error reporting of X509v3_cache_extensions() in v3_purp.c
    add error reporting to x509_init_sig_info() in x509_set.c
    improve static setup_dp() and related functions in v3_purp.c and v3_crld.c
    add test case for non-conforming cert from https://tools.ietf.org/html/rfc8410#section-10.2
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12478)

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

Summary of changes:
 crypto/err/openssl.txt                        |   7 +
 crypto/x509/v3_crld.c                         |  27 ++--
 crypto/x509/v3_purp.c                         | 118 +++++++++++++----
 crypto/x509/v3err.c                           |   5 +
 crypto/x509/x509_err.c                        |   7 +
 crypto/x509/x509_set.c                        |  97 ++++++++------
 crypto/x509/x509_txt.c                        |  42 +++++-
 crypto/x509/x509_vfy.c                        |  78 ++++++++++-
 doc/internal/man3/x509v3_cache_extensions.pod |  40 ++++++
 doc/man1/openssl.pod                          |   1 +
 include/crypto/x509.h                         |   6 +-
 include/openssl/x509_vfy.h                    | 179 ++++++++++++++------------
 include/openssl/x509err.h                     |   4 +
 include/openssl/x509v3.h                      |  11 +-
 include/openssl/x509v3err.h                   |   3 +
 test/recipes/25-test_verify.t                 |   7 +-
 test/testx509.pem                             |  16 +--
 17 files changed, 463 insertions(+), 185 deletions(-)
 create mode 100644 doc/internal/man3/x509v3_cache_extensions.pod

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index df8a7af26c..d0ba9c47be 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -3487,6 +3487,7 @@ X509V3_R_BN_TO_ASN1_INTEGER_ERROR:101:bn to asn1 integer error
 X509V3_R_DIRNAME_ERROR:149:dirname error
 X509V3_R_DISTPOINT_ALREADY_SET:160:distpoint already set
 X509V3_R_DUPLICATE_ZONE_ID:133:duplicate zone id
+X509V3_R_EMPTY_KEY_USAGE:169:empty key usage
 X509V3_R_ERROR_CONVERTING_ZONE:131:error converting zone
 X509V3_R_ERROR_CREATING_EXTENSION:144:error creating extension
 X509V3_R_ERROR_IN_EXTENSION:128:error in extension
@@ -3501,6 +3502,7 @@ X509V3_R_INCORRECT_POLICY_SYNTAX_TAG:152:incorrect policy syntax tag
 X509V3_R_INVALID_ASNUMBER:162:invalid asnumber
 X509V3_R_INVALID_ASRANGE:163:invalid asrange
 X509V3_R_INVALID_BOOLEAN_STRING:104:invalid boolean string
+X509V3_R_INVALID_CERTIFICATE:158:invalid certificate
 X509V3_R_INVALID_EMPTY_NAME:108:invalid empty name
 X509V3_R_INVALID_EXTENSION_STRING:105:invalid extension string
 X509V3_R_INVALID_INHERITANCE:165:invalid inheritance
@@ -3522,6 +3524,7 @@ X509V3_R_INVALID_SYNTAX:143:invalid syntax
 X509V3_R_ISSUER_DECODE_ERROR:126:issuer decode error
 X509V3_R_MISSING_VALUE:124:missing value
 X509V3_R_NEED_ORGANIZATION_AND_NUMBERS:142:need organization and numbers
+X509V3_R_NEGATIVE_PATHLEN:168:negative pathlen
 X509V3_R_NO_CONFIG_DATABASE:136:no config database
 X509V3_R_NO_ISSUER_CERTIFICATE:121:no issuer certificate
 X509V3_R_NO_ISSUER_DETAILS:127:no issuer details
@@ -3557,9 +3560,12 @@ X509_R_CERTIFICATE_VERIFICATION_FAILED:139:certificate verification failed
 X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table
 X509_R_CRL_ALREADY_DELTA:127:crl already delta
 X509_R_CRL_VERIFY_FAILURE:131:crl verify failure
+X509_R_ERROR_GETTING_MD_BY_NID:141:error getting md by nid
+X509_R_ERROR_USING_SIGINF_SET:142:error using siginf set
 X509_R_IDP_MISMATCH:128:idp mismatch
 X509_R_INVALID_ATTRIBUTES:138:invalid attributes
 X509_R_INVALID_DIRECTORY:113:invalid directory
+X509_R_INVALID_DISTPOINT:143:invalid distpoint
 X509_R_INVALID_FIELD_NAME:119:invalid field name
 X509_R_INVALID_TRUST:123:invalid trust
 X509_R_ISSUER_MISMATCH:129:issuer mismatch
@@ -3583,6 +3589,7 @@ X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:108:unable to get certs public key
 X509_R_UNKNOWN_KEY_TYPE:117:unknown key type
 X509_R_UNKNOWN_NID:109:unknown nid
 X509_R_UNKNOWN_PURPOSE_ID:121:unknown purpose id
+X509_R_UNKNOWN_SIGID_ALGS:144:unknown sigid algs
 X509_R_UNKNOWN_TRUST_ID:120:unknown trust id
 X509_R_UNSUPPORTED_ALGORITHM:111:unsupported algorithm
 X509_R_WRONG_LOOKUP_TYPE:112:wrong lookup type
diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c
index b54346d036..8b4e100714 100644
--- a/crypto/x509/v3_crld.c
+++ b/crypto/x509/v3_crld.c
@@ -485,30 +485,31 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
     return 1;
 }
 
+/* Append any nameRelativeToCRLIssuer in dpn to iname, set in dpn->dpname */
 int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname)
 {
     int i;
     STACK_OF(X509_NAME_ENTRY) *frag;
     X509_NAME_ENTRY *ne;
-    if (!dpn || (dpn->type != 1))
+
+    if (dpn == NULL || dpn->type != 1)
         return 1;
     frag = dpn->name.relativename;
+    X509_NAME_free(dpn->dpname); /* just in case it was already set */
     dpn->dpname = X509_NAME_dup(iname);
-    if (!dpn->dpname)
+    if (dpn->dpname == NULL)
         return 0;
     for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
         ne = sk_X509_NAME_ENTRY_value(frag, i);
-        if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
-            X509_NAME_free(dpn->dpname);
-            dpn->dpname = NULL;
-            return 0;
-        }
+        if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
+            goto err;
     }
     /* generate cached encoding of name */
-    if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
-        X509_NAME_free(dpn->dpname);
-        dpn->dpname = NULL;
-        return 0;
-    }
-    return 1;
+    if (i2d_X509_NAME(dpn->dpname, NULL) >= 0)
+        return 1;
+
+ err:
+    X509_NAME_free(dpn->dpname);
+    dpn->dpname = NULL;
+    return 0;
 }
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index d7d0aae3b3..2d4098b629 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -305,34 +305,49 @@ int X509_supported_extension(X509_EXTENSION *ex)
     return 0;
 }
 
-static int setup_dp(X509 *x, DIST_POINT *dp)
+/* return 1 on success, 0 if x is invalid, -1 on (internal) error */
+static int setup_dp(const X509 *x, DIST_POINT *dp)
 {
     const X509_NAME *iname = NULL;
     int i;
 
-    if (dp->reasons) {
+    if (dp->distpoint == NULL && sk_GENERAL_NAME_num(dp->CRLissuer) <= 0) {
+        X509err(0, X509_R_INVALID_DISTPOINT);
+        return 0;
+    }
+    if (dp->reasons != NULL) {
         if (dp->reasons->length > 0)
             dp->dp_reasons = dp->reasons->data[0];
         if (dp->reasons->length > 1)
             dp->dp_reasons |= (dp->reasons->data[1] << 8);
         dp->dp_reasons &= CRLDP_ALL_REASONS;
-    } else
+    } else {
         dp->dp_reasons = CRLDP_ALL_REASONS;
-    if (!dp->distpoint || (dp->distpoint->type != 1))
+    }
+    if (dp->distpoint == NULL || dp->distpoint->type != 1)
         return 1;
+
+    /* handle name fragment given by nameRelativeToCRLIssuer */
+    /*
+     * Note that the below way of determining iname is not really compliant
+     * with https://tools.ietf.org/html/rfc5280#section-4.2.1.13
+     * According to it, sk_GENERAL_NAME_num(dp->CRLissuer) MUST be <= 1
+     * and any CRLissuer could be of type different to GEN_DIRNAME.
+     */
     for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
         GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+
         if (gen->type == GEN_DIRNAME) {
             iname = gen->d.directoryName;
             break;
         }
     }
-    if (!iname)
+    if (iname == NULL)
         iname = X509_get_issuer_name(x);
-
-    return DIST_POINT_set_dpname(dp->distpoint, iname);
+    return DIST_POINT_set_dpname(dp->distpoint, iname) ? 1 : -1;
 }
 
+/* return 1 on success, 0 if x is invalid, -1 on (internal) error */
 static int setup_crldp(X509 *x)
 {
     int i;
@@ -340,9 +355,12 @@ static int setup_crldp(X509 *x)
     x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL);
     if (x->crldp == NULL && i != -1)
         return 0;
+
     for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
-        if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i)))
-            return 0;
+        int res = setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+
+        if (res < 1)
+            return res;
     }
     return 1;
 }
@@ -373,6 +391,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.
+ * 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.
  */
 int x509v3_cache_extensions(X509 *x)
@@ -382,8 +401,8 @@ int x509v3_cache_extensions(X509 *x)
     ASN1_BIT_STRING *usage;
     ASN1_BIT_STRING *ns;
     EXTENDED_KEY_USAGE *extusage;
-    X509_EXTENSION *ex;
     int i;
+    int res;
 
 #ifdef tsan_ld_acq
     /* fast lock-free check, see end of the function for details. */
@@ -398,30 +417,34 @@ int x509v3_cache_extensions(X509 *x)
     }
     ERR_set_mark();
 
+    /* Cache the SHA1 digest of the cert */
     if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
-            x->ex_flags |= EXFLAG_INVALID;
+        /*
+         * 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;
 
     /* V1 should mean no extensions ... */
     if (X509_get_version(x) == 0)
         x->ex_flags |= EXFLAG_V1;
 
     /* Handle basic constraints */
+    x->ex_pathlen = -1;
     if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL)) != NULL) {
         if (bs->ca)
             x->ex_flags |= EXFLAG_CA;
         if (bs->pathlen != NULL) {
+            /*
+             * the error case !bs->ca is checked by check_chain_extensions()
+             * in case ctx->param->flags & X509_V_FLAG_X509_STRICT
+             */
             if (bs->pathlen->type == V_ASN1_NEG_INTEGER) {
+                X509err(0, X509V3_R_NEGATIVE_PATHLEN);
                 x->ex_flags |= EXFLAG_INVALID;
-                x->ex_pathlen = 0;
             } else {
                 x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
-                if (!bs->ca && x->ex_pathlen != 0) {
-                    x->ex_flags |= EXFLAG_INVALID;
-                    x->ex_pathlen = 0;
-                }
             }
-        } else {
-            x->ex_pathlen = -1;
         }
         BASIC_CONSTRAINTS_free(bs);
         x->ex_flags |= EXFLAG_BCONS;
@@ -436,9 +459,9 @@ int x509v3_cache_extensions(X509 *x)
             || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
             x->ex_flags |= EXFLAG_INVALID;
         }
-        if (pci->pcPathLengthConstraint) {
+        if (pci->pcPathLengthConstraint != NULL)
             x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
-        } else
+        else
             x->ex_pcpathlen = -1;
         PROXY_CERT_INFO_EXTENSION_free(pci);
         x->ex_flags |= EXFLAG_PROXY;
@@ -446,7 +469,7 @@ int x509v3_cache_extensions(X509 *x)
         x->ex_flags |= EXFLAG_INVALID;
     }
 
-    /* Handle (basic and extended) key usage */
+    /* Handle (basic) key usage */
     if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL)) != NULL) {
         x->ex_kusage = 0;
         if (usage->length > 0) {
@@ -456,9 +479,16 @@ int x509v3_cache_extensions(X509 *x)
         }
         x->ex_flags |= EXFLAG_KUSAGE;
         ASN1_BIT_STRING_free(usage);
+        /* Check for empty key usage according to RFC 5280 section 4.2.1.3 */
+        if (x->ex_kusage == 0) {
+            X509err(0, X509V3_R_EMPTY_KEY_USAGE);
+            x->ex_flags |= EXFLAG_INVALID;
+        }
     } else if (i != -1) {
         x->ex_flags |= EXFLAG_INVALID;
     }
+
+    /* Handle extended key usage */
     x->ex_xkusage = 0;
     if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL)) != NULL) {
         x->ex_flags |= EXFLAG_XKUSAGE;
@@ -493,6 +523,7 @@ int x509v3_cache_extensions(X509 *x)
                 x->ex_xkusage |= XKU_ANYEKU;
                 break;
             default:
+                /* ignore unknown extended key usage */
                 break;
             }
         }
@@ -517,6 +548,7 @@ int x509v3_cache_extensions(X509 *x)
     x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL);
     if (x->skid == NULL && i != -1)
         x->ex_flags |= EXFLAG_INVALID;
+
     x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL);
     if (x->akid == NULL && i != -1)
         x->ex_flags |= EXFLAG_INVALID;
@@ -538,8 +570,13 @@ int x509v3_cache_extensions(X509 *x)
     x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
     if (x->nc == NULL && i != -1)
         x->ex_flags |= EXFLAG_INVALID;
-    if (!setup_crldp(x))
+
+    /* Handle CRL distribution point entries */
+    res = setup_crldp(x);
+    if (res == 0)
         x->ex_flags |= EXFLAG_INVALID;
+    else if (res < 0)
+        goto err;
 
 #ifndef OPENSSL_NO_RFC3779
     x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL);
@@ -550,9 +587,10 @@ int x509v3_cache_extensions(X509 *x)
         x->ex_flags |= EXFLAG_INVALID;
 #endif
     for (i = 0; i < X509_get_ext_count(x); i++) {
-        ex = X509_get_ext(x, i);
-        if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
-            == NID_freshest_crl)
+        X509_EXTENSION *ex = X509_get_ext(x, i);
+        int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+        if (nid == NID_freshest_crl)
             x->ex_flags |= EXFLAG_FRESHEST;
         if (!X509_EXTENSION_get_critical(ex))
             continue;
@@ -560,9 +598,26 @@ int x509v3_cache_extensions(X509 *x)
             x->ex_flags |= EXFLAG_CRITICAL;
             break;
         }
+        switch (nid) {
+        case NID_basic_constraints:
+            x->ex_flags |= EXFLAG_BCONS_CRITICAL;
+            break;
+        case NID_authority_key_identifier:
+            x->ex_flags |= EXFLAG_AKID_CRITICAL;
+            break;
+        case NID_subject_key_identifier:
+            x->ex_flags |= EXFLAG_SKID_CRITICAL;
+            break;
+        case NID_subject_alt_name:
+            x->ex_flags |= EXFLAG_SAN_CRITICAL;
+            break;
+        default:
+            break;
+        }
     }
 
-    x509_init_sig_info(x);
+    /* Set x->siginf, ignoring errors due to unsupported algos */
+    (void)x509_init_sig_info(x);
 
     x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */
 #ifdef tsan_st_rel
@@ -574,9 +629,16 @@ int x509v3_cache_extensions(X509 *x)
      */
 #endif
     ERR_pop_to_mark();
-    CRYPTO_THREAD_unlock(x->lock);
+    if ((x->ex_flags & EXFLAG_INVALID) == 0) {
+        CRYPTO_THREAD_unlock(x->lock);
+        return 1;
+    }
+    X509err(0, X509V3_R_INVALID_CERTIFICATE);
 
-    return (x->ex_flags & EXFLAG_INVALID) == 0;
+ err:
+    x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */
+    CRYPTO_THREAD_unlock(x->lock);
+    return 0;
 }
 
 /*-
diff --git a/crypto/x509/v3err.c b/crypto/x509/v3err.c
index 4c62e59db9..5124908089 100644
--- a/crypto/x509/v3err.c
+++ b/crypto/x509/v3err.c
@@ -24,6 +24,7 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
     "distpoint already set"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID),
     "duplicate zone id"},
+    {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EMPTY_KEY_USAGE), "empty key usage"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE),
     "error converting zone"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION),
@@ -51,6 +52,8 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING),
     "invalid boolean string"},
+    {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_CERTIFICATE),
+    "invalid certificate"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING),
     "invalid extension string"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE),
@@ -84,6 +87,8 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS),
     "need organization and numbers"},
+    {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEGATIVE_PATHLEN),
+    "negative pathlen"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE),
     "no config database"},
     {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE),
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index 450f2a7930..330fed3406 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -27,10 +27,15 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE),
     "crl verify failure"},
+    {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERROR_GETTING_MD_BY_NID),
+    "error getting md by nid"},
+    {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERROR_USING_SIGINF_SET),
+    "error using siginf set"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "idp mismatch"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_ATTRIBUTES),
     "invalid attributes"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "invalid directory"},
+    {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DISTPOINT), "invalid distpoint"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME),
     "invalid field name"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "invalid trust"},
@@ -66,6 +71,8 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "unknown nid"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID),
     "unknown purpose id"},
+    {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_SIGID_ALGS),
+    "unknown sigid algs"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM),
     "unsupported algorithm"},
diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c
index 46cabc4b42..79e4c03ca3 100644
--- a/crypto/x509/x509_set.c
+++ b/crypto/x509/x509_set.c
@@ -192,60 +192,85 @@ int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
     return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags);
 }
 
-static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
-                               const ASN1_STRING *sig)
+/* Modify *siginf according to alg and sig. Return 1 on success, else 0. */
+static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
+                              const ASN1_STRING *sig)
 {
     int pknid, mdnid;
     const EVP_MD *md;
+    const EVP_PKEY_ASN1_METHOD *ameth;
 
     siginf->mdnid = NID_undef;
     siginf->pknid = NID_undef;
     siginf->secbits = -1;
     siginf->flags = 0;
     if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)
-            || pknid == NID_undef)
-        return;
+            || pknid == NID_undef) {
+        X509err(0, X509_R_UNKNOWN_SIGID_ALGS);
+        return 0;
+    }
+    siginf->mdnid = mdnid;
     siginf->pknid = pknid;
-    if (mdnid == NID_undef) {
+
+    switch (mdnid) {
+    case NID_undef:
         /* If we have one, use a custom handler for this algorithm */
-        const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid);
+        ameth = EVP_PKEY_asn1_find(NULL, pknid);
         if (ameth == NULL || ameth->siginf_set == NULL
-                || ameth->siginf_set(siginf, alg, sig) == 0)
-            return;
-        siginf->flags |= X509_SIG_INFO_VALID;
-        return;
-    }
-    siginf->flags |= X509_SIG_INFO_VALID;
-    siginf->mdnid = mdnid;
-    md = EVP_get_digestbynid(mdnid);
-    if (md == NULL)
-        return;
-    /* Security bits: half number of bits in digest */
-    siginf->secbits = EVP_MD_size(md) * 4;
-    /*
-     * SHA1 and MD5 are known to be broken. Reduce security bits so that
-     * they're no longer accepted at security level 1. The real values don't
-     * really matter as long as they're lower than 80, which is our security
-     * level 1.
-     * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for SHA1 at
-     * 2^63.4
-     * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
-     * puts a chosen-prefix attack for MD5 at 2^39.
-     */
-    if (mdnid == NID_sha1)
+                || !ameth->siginf_set(siginf, alg, sig)) {
+            X509err(0, X509_R_ERROR_USING_SIGINF_SET);
+            return 0;
+        }
+        break;
+        /*
+         * SHA1 and MD5 are known to be broken. Reduce security bits so that
+         * they're no longer accepted at security level 1.
+         * The real values don't really matter as long as they're lower than 80,
+         * which is our security level 1.
+         */
+    case NID_sha1:
+        /*
+         * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack
+         * for SHA1 at2^63.4
+         */
         siginf->secbits = 63;
-    else if (mdnid == NID_md5)
+        break;
+    case NID_md5:
+        /*
+         * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+         * puts a chosen-prefix attack for MD5 at 2^39.
+         */
         siginf->secbits = 39;
+        break;
+    case NID_id_GostR3411_94:
+        /*
+         * There is a collision attack on GOST R 34.11-94 at 2^105, see
+         * https://link.springer.com/chapter/10.1007%2F978-3-540-85174-5_10
+         */
+        siginf->secbits = 105;
+        break;
+    default:
+        /* Security bits: half number of bits in digest */
+        if ((md = EVP_get_digestbynid(mdnid)) == NULL) {
+            X509err(0, X509_R_ERROR_GETTING_MD_BY_NID);
+            return 0;
+        }
+        siginf->secbits = EVP_MD_size(md) * 4;
+        break;
+    }
     switch (mdnid) {
-        case NID_sha1:
-        case NID_sha256:
-        case NID_sha384:
-        case NID_sha512:
+    case NID_sha1:
+    case NID_sha256:
+    case NID_sha384:
+    case NID_sha512:
         siginf->flags |= X509_SIG_INFO_TLS;
     }
+    siginf->flags |= X509_SIG_INFO_VALID;
+    return 1;
 }
 
-void x509_init_sig_info(X509 *x)
+/* Returns 1 on success, 0 on failure */
+int x509_init_sig_info(X509 *x)
 {
-    x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
+    return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
 }
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 63d8d95f3f..53b19e46df 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -69,8 +69,8 @@ const char *X509_verify_cert_error_string(long n)
         return "certificate chain too long";
     case X509_V_ERR_CERT_REVOKED:
         return "certificate revoked";
-    case X509_V_ERR_INVALID_CA:
-        return "invalid CA certificate";
+    case X509_V_ERR_NO_ISSUER_PUBLIC_KEY:
+        return "issuer certificate doesn't have a public key";
     case X509_V_ERR_PATH_LENGTH_EXCEEDED:
         return "path length constraint exceeded";
     case X509_V_ERR_INVALID_PURPOSE:
@@ -174,12 +174,42 @@ 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";
     case X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
         return "Cannot find certificate signature algorithm";
+    case X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH:
+        return "subject signature algorithm and issuer public key algorithm mismatch";
+    case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
+        return "cert info siganature and signature algorithm mismatch";
+    case X509_V_ERR_INVALID_CA:
+        return "invalid CA certificate";
+    case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA:
+        return "Path length invalid for non-CA cert";
+    case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN:
+        return "Path length given without key usage keyCertSign";
+    case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA:
+        return "Key usage keyCertSign invalid for non-CA cert";
+    case X509_V_ERR_ISSUER_NAME_EMPTY:
+        return "Issuer name empty";
+    case X509_V_ERR_SUBJECT_NAME_EMPTY:
+        return "Subject name empty";
+    case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER:
+        return "Missing Authority Key Identifier";
+    case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER:
+        return "Missing Subject Key Identifier";
+    case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME:
+        return "Empty Subject Alternative Name extension";
+    case X509_V_ERR_CA_BCONS_NOT_CRITICAL:
+        return "Basic Constraints of CA cert not marked critical";
+    case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL:
+        return "Subject empty and Subject Alt Name extension not critical";
+    case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL:
+        return "Authority Key Identifier marked critical";
+    case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL:
+        return "Subject Key Identifier marked critical";
+    case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE:
+        return "CA cert does not include key usage extension";
+    case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3:
+        return "Using cert extension requires at least X509v3";
 
     default:
         /* Printing an error number into a static buffer is not thread-safe */
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 843b65f022..4a067e5ff4 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -26,6 +26,7 @@
 #include "x509_local.h"
 
 DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF(X509_EXTENSION)
 DEFINE_STACK_OF(X509_REVOKED)
 DEFINE_STACK_OF(GENERAL_NAME)
 DEFINE_STACK_OF(X509_CRL)
@@ -479,6 +480,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
 
     for (i = 0; i < num; i++) {
         int ret;
+
         x = sk_X509_value(ctx->chain, i);
         if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
             && (x->ex_flags & EXFLAG_CRITICAL)) {
@@ -519,12 +521,78 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
                 ret = 1;
             break;
         }
-        if ((x->ex_flags & EXFLAG_CA) == 0
-            && x->ex_pathlen != -1
-            && (ctx->param->flags & X509_V_FLAG_X509_STRICT)) {
-            ctx->error = X509_V_ERR_INVALID_EXTENSION;
-            ret = 0;
+        /*
+         * Do the following set of checks only if strict checking is requrested
+         * and not for self-issued (including self-signed) EE (non-CA) certs
+         * because RFC 5280 does not apply to them according RFC 6818 section 2.
+         */
+        if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0
+            && num > 1) { /*
+                           * this should imply
+                           * !(i == 0 && (x->ex_flags & EXFLAG_CA) == 0
+                           *          && (x->ex_flags & EXFLAG_SI) != 0)
+                           */
+            /* Check Basic Constraints according to RFC 5280 section 4.2.1.9 */
+            if (x->ex_pathlen != -1) {
+                if ((x->ex_flags & EXFLAG_CA) == 0)
+                    ctx->error = X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA;
+                if ((x->ex_kusage & KU_KEY_CERT_SIGN) == 0)
+                    ctx->error = X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN;
+            }
+            if ((x->ex_flags & EXFLAG_CA) != 0
+                    && (x->ex_flags & EXFLAG_BCONS) != 0
+                    && (x->ex_flags & EXFLAG_BCONS_CRITICAL) == 0)
+                ctx->error = X509_V_ERR_CA_BCONS_NOT_CRITICAL;
+            /* Check Key Usage according to RFC 5280 section 4.2.1.3 */
+            if ((x->ex_flags & EXFLAG_CA) != 0) {
+                if ((x->ex_flags & EXFLAG_KUSAGE) == 0)
+                    ctx->error = X509_V_ERR_CA_CERT_MISSING_KEY_USAGE;
+            } else {
+                if ((x->ex_kusage & KU_KEY_CERT_SIGN) != 0)
+                    ctx->error = X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA;
+            }
+            /* Check issuer is non-empty acc. to RFC 5280 section 4.1.2.4 */
+            if (X509_NAME_entry_count(X509_get_issuer_name(x)) == 0)
+                ctx->error = X509_V_ERR_ISSUER_NAME_EMPTY;
+            /* Check subject is non-empty acc. to RFC 5280 section 4.1.2.6 */
+            if (((x->ex_flags & EXFLAG_CA) != 0
+                 || (x->ex_kusage & KU_CRL_SIGN) != 0
+                 || x->altname == NULL
+                 ) && X509_NAME_entry_count(X509_get_subject_name(x)) == 0)
+                ctx->error = X509_V_ERR_SUBJECT_NAME_EMPTY;
+            if (X509_NAME_entry_count(X509_get_subject_name(x)) == 0
+                    && x->altname != NULL
+                    && (x->ex_flags & EXFLAG_SAN_CRITICAL) == 0)
+                ctx->error = X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL;
+            /* Check SAN is non-empty according to RFC 5280 section 4.2.1.6 */
+            if (x->altname != NULL && sk_GENERAL_NAME_num(x->altname) <= 0)
+                ctx->error = X509_V_ERR_EMPTY_SUBJECT_ALT_NAME;
+            /* TODO add more checks on SAN entries */
+            /* Check sig alg consistency acc. to RFC 5280 section 4.1.1.2 */
+            if (X509_ALGOR_cmp(&x->sig_alg, &x->cert_info.signature) != 0)
+                ctx->error = X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY;
+            if (x->akid != NULL && (x->ex_flags & EXFLAG_AKID_CRITICAL) != 0)
+                ctx->error = X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL;
+            if (x->skid != NULL && (x->ex_flags & EXFLAG_SKID_CRITICAL) != 0)
+                ctx->error = X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL;
+            if (X509_get_version(x) >= 2) { /* at least X.509v3 */
+                /* Check AKID presence acc. to RFC 5280 section 4.2.1.1 */
+                if (i + 1 < num /*
+                                 * this means not last cert in chain,
+                                 * taken as "generated by conforming CAs"
+                                 */
+                        && (x->akid == NULL || x->akid->keyid == NULL))
+                    ctx->error = X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER;
+                /* Check SKID presence acc. to RFC 5280 section 4.2.1.2 */
+                if ((x->ex_flags & EXFLAG_CA) != 0 && x->skid == NULL)
+                    ctx->error = X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER;
+            } else {
+                if (sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0)
+                    ctx->error = X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3;
+            }
         }
+        if (ctx->error != X509_V_OK)
+            ret = 0;
         if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK))
             return 0;
         /* check_purpose() makes the callback as needed */
diff --git a/doc/internal/man3/x509v3_cache_extensions.pod b/doc/internal/man3/x509v3_cache_extensions.pod
new file mode 100644
index 0000000000..3fb7609daa
--- /dev/null
+++ b/doc/internal/man3/x509v3_cache_extensions.pod
@@ -0,0 +1,40 @@
+=pod
+
+=head1 NAME
+
+x509v3_cache_extensions
+- cache info on various X.509v3 extensions and further derived certificate data
+
+=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 present in an X509 object I<x>
+and caches the result of that processing as well as further derived info,
+for instance whether the certificate is self-issued or has version X.509v1.
+It computes the SHA1 digest of the certificate using the default library context
+and property query string and stores the result in x->sha1_hash.
+It sets B<X509_SIG_INFO_VALID> in x->flags if x->siginf was filled successfully,
+which may not be possible if a referenced algorithm is unknown or not available.
+Many OpenSSL functions that use an X509 object call this function implicitly.
+
+=head1 RETURN VALUES
+
+This function returns 0 if the extensions or other portions of the certificate
+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/doc/man1/openssl.pod b/doc/man1/openssl.pod
index 1f344217a2..3ae273b5bf 100644
--- a/doc/man1/openssl.pod
+++ b/doc/man1/openssl.pod
@@ -906,6 +906,7 @@ a verification time, the check is not suppressed.
 =item B<-x509_strict>
 
 This disables non-compliant workarounds for broken certificates.
+Thus errors are thrown on certificates not compliant with RFC 5280.
 
 =item B<-ignore_critical>
 
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index bd8f9ba52d..8c9a288cbc 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -304,9 +304,13 @@ int a2i_ipadd(unsigned char *ipout, const char *ipasc);
 int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
 int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags);
 int x509v3_cache_extensions(X509 *x);
+int x509_init_sig_info(X509 *x);
+int x509_check_issued_int(X509 *issuer, X509 *subject, OPENSSL_CTX *libctx,
+                          const char *propq);
+
 int x509_set0_libctx(X509 *x, OPENSSL_CTX *libctx, const char *propq);
 int x509_crl_set0_libctx(X509_CRL *x, OPENSSL_CTX *libctx, const char *propq);
-void x509_init_sig_info(X509 *x);
+int x509_init_sig_info(X509 *x);
 int asn1_item_digest_with_libctx(const ASN1_ITEM *it, const EVP_MD *type,
                                  void *data, unsigned char *md,
                                  unsigned int *len, OPENSSL_CTX *libctx,
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 2d3bd70ae2..d43a442fc7 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -124,103 +124,118 @@ X509_LOOKUP_ctrl_with_libctx((x), X509_L_LOAD_STORE, (name), 0, NULL,          \
 X509_LOOKUP_ctrl_with_libctx((x), X509_L_ADD_STORE, (name), 0, NULL,           \
                              (libctx), (propq))
 
+# define X509_V_OK                                       0
+# define X509_V_ERR_UNSPECIFIED                          1
+# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT            2
+# define X509_V_ERR_UNABLE_TO_GET_CRL                    3
+# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE     4
+# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE      5
+# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY   6
+# define X509_V_ERR_CERT_SIGNATURE_FAILURE               7
+# define X509_V_ERR_CRL_SIGNATURE_FAILURE                8
+# define X509_V_ERR_CERT_NOT_YET_VALID                   9
+# define X509_V_ERR_CERT_HAS_EXPIRED                     10
+# define X509_V_ERR_CRL_NOT_YET_VALID                    11
+# define X509_V_ERR_CRL_HAS_EXPIRED                      12
+# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD       13
+# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD        14
+# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD       15
+# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD       16
+# define X509_V_ERR_OUT_OF_MEM                           17
+# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT          18
+# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN            19
+# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY    20
+# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE      21
+# define X509_V_ERR_CERT_CHAIN_TOO_LONG                  22
+# define X509_V_ERR_CERT_REVOKED                         23
+# define X509_V_ERR_NO_ISSUER_PUBLIC_KEY                 24
+# define X509_V_ERR_PATH_LENGTH_EXCEEDED                 25
+# define X509_V_ERR_INVALID_PURPOSE                      26
+# define X509_V_ERR_CERT_UNTRUSTED                       27
+# define X509_V_ERR_CERT_REJECTED                        28
 
-# define         X509_V_OK                                       0
-# define         X509_V_ERR_UNSPECIFIED                          1
-# define         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT            2
-# define         X509_V_ERR_UNABLE_TO_GET_CRL                    3
-# define         X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE     4
-# define         X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE      5
-# define         X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY   6
-# define         X509_V_ERR_CERT_SIGNATURE_FAILURE               7
-# define         X509_V_ERR_CRL_SIGNATURE_FAILURE                8
-# define         X509_V_ERR_CERT_NOT_YET_VALID                   9
-# define         X509_V_ERR_CERT_HAS_EXPIRED                     10
-# define         X509_V_ERR_CRL_NOT_YET_VALID                    11
-# define         X509_V_ERR_CRL_HAS_EXPIRED                      12
-# define         X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD       13
-# define         X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD        14
-# define         X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD       15
-# define         X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD       16
-# define         X509_V_ERR_OUT_OF_MEM                           17
-# define         X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT          18
-# define         X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN            19
-# define         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY    20
-# define         X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE      21
-# define         X509_V_ERR_CERT_CHAIN_TOO_LONG                  22
-# define         X509_V_ERR_CERT_REVOKED                         23
-# define         X509_V_ERR_INVALID_CA                           24
-# define         X509_V_ERR_PATH_LENGTH_EXCEEDED                 25
-# define         X509_V_ERR_INVALID_PURPOSE                      26
-# define         X509_V_ERR_CERT_UNTRUSTED                       27
-# define         X509_V_ERR_CERT_REJECTED                        28
 /* These are 'informational' when looking for issuer cert */
-# define         X509_V_ERR_SUBJECT_ISSUER_MISMATCH              29
-# define         X509_V_ERR_AKID_SKID_MISMATCH                   30
-# define         X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH          31
-# define         X509_V_ERR_KEYUSAGE_NO_CERTSIGN                 32
-# define         X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER             33
-# define         X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION         34
-# define         X509_V_ERR_KEYUSAGE_NO_CRL_SIGN                 35
-# define         X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION     36
-# define         X509_V_ERR_INVALID_NON_CA                       37
-# define         X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED           38
-# define         X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE        39
-# define         X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED       40
-# define         X509_V_ERR_INVALID_EXTENSION                    41
-# define         X509_V_ERR_INVALID_POLICY_EXTENSION             42
-# define         X509_V_ERR_NO_EXPLICIT_POLICY                   43
-# define         X509_V_ERR_DIFFERENT_CRL_SCOPE                  44
-# define         X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE        45
-# define         X509_V_ERR_UNNESTED_RESOURCE                    46
-# define         X509_V_ERR_PERMITTED_VIOLATION                  47
-# define         X509_V_ERR_EXCLUDED_VIOLATION                   48
-# define         X509_V_ERR_SUBTREE_MINMAX                       49
+# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH              29
+# define X509_V_ERR_AKID_SKID_MISMATCH                   30
+# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH          31
+# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN                 32
+# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER             33
+# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION         34
+# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN                 35
+# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION     36
+# define X509_V_ERR_INVALID_NON_CA                       37
+# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED           38
+# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE        39
+# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED       40
+# define X509_V_ERR_INVALID_EXTENSION                    41
+# define X509_V_ERR_INVALID_POLICY_EXTENSION             42
+# define X509_V_ERR_NO_EXPLICIT_POLICY                   43
+# define X509_V_ERR_DIFFERENT_CRL_SCOPE                  44
+# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE        45
+# define X509_V_ERR_UNNESTED_RESOURCE                    46
+# define X509_V_ERR_PERMITTED_VIOLATION                  47
+# define X509_V_ERR_EXCLUDED_VIOLATION                   48
+# define X509_V_ERR_SUBTREE_MINMAX                       49
 /* The application is not happy */
-# define         X509_V_ERR_APPLICATION_VERIFICATION             50
-# define         X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE          51
-# define         X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX        52
-# define         X509_V_ERR_UNSUPPORTED_NAME_SYNTAX              53
-# define         X509_V_ERR_CRL_PATH_VALIDATION_ERROR            54
+# define X509_V_ERR_APPLICATION_VERIFICATION             50
+# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE          51
+# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX        52
+# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX              53
+# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR            54
 /* Another issuer check debug option */
-# define         X509_V_ERR_PATH_LOOP                            55
+# define X509_V_ERR_PATH_LOOP                            55
 /* Suite B mode algorithm violation */
-# define         X509_V_ERR_SUITE_B_INVALID_VERSION              56
-# define         X509_V_ERR_SUITE_B_INVALID_ALGORITHM            57
-# define         X509_V_ERR_SUITE_B_INVALID_CURVE                58
-# define         X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM  59
-# define         X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED              60
-# define         X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
+# define X509_V_ERR_SUITE_B_INVALID_VERSION              56
+# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM            57
+# define X509_V_ERR_SUITE_B_INVALID_CURVE                58
+# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM  59
+# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED              60
+# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
 /* Host, email and IP check errors */
-# define         X509_V_ERR_HOSTNAME_MISMATCH                    62
-# define         X509_V_ERR_EMAIL_MISMATCH                       63
-# define         X509_V_ERR_IP_ADDRESS_MISMATCH                  64
+# define X509_V_ERR_HOSTNAME_MISMATCH                    62
+# define X509_V_ERR_EMAIL_MISMATCH                       63
+# define X509_V_ERR_IP_ADDRESS_MISMATCH                  64
 /* DANE TLSA errors */
-# define         X509_V_ERR_DANE_NO_MATCH                        65
+# define X509_V_ERR_DANE_NO_MATCH                        65
 /* security level errors */
-# define         X509_V_ERR_EE_KEY_TOO_SMALL                     66
-# define         X509_V_ERR_CA_KEY_TOO_SMALL                     67
-# define         X509_V_ERR_CA_MD_TOO_WEAK                       68
+# define X509_V_ERR_EE_KEY_TOO_SMALL                     66
+# define X509_V_ERR_CA_KEY_TOO_SMALL                     67
+# define X509_V_ERR_CA_MD_TOO_WEAK                       68
 /* Caller error */
-# define         X509_V_ERR_INVALID_CALL                         69
+# define X509_V_ERR_INVALID_CALL                         69
 /* Issuer lookup error */
-# define         X509_V_ERR_STORE_LOOKUP                         70
+# define X509_V_ERR_STORE_LOOKUP                         70
 /* Certificate transparency */
-# define         X509_V_ERR_NO_VALID_SCTS                        71
+# define X509_V_ERR_NO_VALID_SCTS                        71
 
-# define         X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION         72
+# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION         72
 /* OCSP status errors */
-# define         X509_V_ERR_OCSP_VERIFY_NEEDED                   73  /* Need OCSP verification */
-# 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
-# define         X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM      78
-
+# define X509_V_ERR_OCSP_VERIFY_NEEDED                   73  /* Need OCSP verification */
+# 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_UNSUPPORTED_SIGNATURE_ALGORITHM      76
+# define X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH         77
+
+/* Errors in case a check in X509_V_FLAG_X509_STRICT mode fails */
+# define X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY    78
+# define X509_V_ERR_INVALID_CA                           79
+# define X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA           80
+# define X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN     81
+# define X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA  82
+# define X509_V_ERR_ISSUER_NAME_EMPTY                    83
+# define X509_V_ERR_SUBJECT_NAME_EMPTY                   84
+# define X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER     85
+# define X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER       86
+# define X509_V_ERR_EMPTY_SUBJECT_ALT_NAME               87
+# define X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL       88
+# define X509_V_ERR_CA_BCONS_NOT_CRITICAL                89
+# define X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL    90
+# define X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL      91
+# define X509_V_ERR_CA_CERT_MISSING_KEY_USAGE            92
+# define X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3         93
 
 /* Certificate verify flags */
-
 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
 #  define X509_V_FLAG_CB_ISSUER_CHECK             0x0   /* Deprecated */
 # endif
diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h
index 19743b5987..94c5c5b75e 100644
--- a/include/openssl/x509err.h
+++ b/include/openssl/x509err.h
@@ -107,9 +107,12 @@ int ERR_load_X509_strings(void);
 # define X509_R_CERT_ALREADY_IN_HASH_TABLE                101
 # define X509_R_CRL_ALREADY_DELTA                         127
 # define X509_R_CRL_VERIFY_FAILURE                        131
+# define X509_R_ERROR_GETTING_MD_BY_NID                   141
+# define X509_R_ERROR_USING_SIGINF_SET                    142
 # define X509_R_IDP_MISMATCH                              128
 # define X509_R_INVALID_ATTRIBUTES                        138
 # define X509_R_INVALID_DIRECTORY                         113
+# define X509_R_INVALID_DISTPOINT                         143
 # define X509_R_INVALID_FIELD_NAME                        119
 # define X509_R_INVALID_TRUST                             123
 # define X509_R_ISSUER_MISMATCH                           129
@@ -133,6 +136,7 @@ int ERR_load_X509_strings(void);
 # define X509_R_UNKNOWN_KEY_TYPE                          117
 # define X509_R_UNKNOWN_NID                               109
 # define X509_R_UNKNOWN_PURPOSE_ID                        121
+# define X509_R_UNKNOWN_SIGID_ALGS                        144
 # define X509_R_UNKNOWN_TRUST_ID                          120
 # define X509_R_UNSUPPORTED_ALGORITHM                     111
 # define X509_R_WRONG_LOOKUP_TYPE                         112
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index 24f5a361d0..a3ef7ced3a 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -364,8 +364,7 @@ struct ISSUING_DIST_POINT_st {
 # define EXFLAG_NSCERT           0x8
 
 # define EXFLAG_CA               0x10
-/* Really self issued not necessarily self signed */
-# define EXFLAG_SI               0x20
+# define EXFLAG_SI               0x20 /* self-issued, maybe not self-signed */
 # define EXFLAG_V1               0x40
 # define EXFLAG_INVALID          0x80
 /* EXFLAG_SET is set to indicate that some values have been precomputed */
@@ -375,8 +374,12 @@ struct ISSUING_DIST_POINT_st {
 
 # define EXFLAG_INVALID_POLICY   0x800
 # define EXFLAG_FRESHEST         0x1000
-/* Self signed */
-# define EXFLAG_SS               0x2000
+# define EXFLAG_SS               0x2000 /* cert is apparently self-signed */
+
+# define EXFLAG_BCONS_CRITICAL   0x10000
+# define EXFLAG_AKID_CRITICAL    0x20000
+# define EXFLAG_SKID_CRITICAL    0x40000
+# define EXFLAG_SAN_CRITICAL     0x80000
 
 # define KU_DIGITAL_SIGNATURE    0x0080
 # define KU_NON_REPUDIATION      0x0040
diff --git a/include/openssl/x509v3err.h b/include/openssl/x509v3err.h
index d7aa5da6ac..b245a63902 100644
--- a/include/openssl/x509v3err.h
+++ b/include/openssl/x509v3err.h
@@ -107,6 +107,7 @@ int ERR_load_X509V3_strings(void);
 # define X509V3_R_DIRNAME_ERROR                           149
 # define X509V3_R_DISTPOINT_ALREADY_SET                   160
 # define X509V3_R_DUPLICATE_ZONE_ID                       133
+# define X509V3_R_EMPTY_KEY_USAGE                         169
 # define X509V3_R_ERROR_CONVERTING_ZONE                   131
 # define X509V3_R_ERROR_CREATING_EXTENSION                144
 # define X509V3_R_ERROR_IN_EXTENSION                      128
@@ -121,6 +122,7 @@ int ERR_load_X509V3_strings(void);
 # define X509V3_R_INVALID_ASNUMBER                        162
 # define X509V3_R_INVALID_ASRANGE                         163
 # define X509V3_R_INVALID_BOOLEAN_STRING                  104
+# define X509V3_R_INVALID_CERTIFICATE                     158
 # define X509V3_R_INVALID_EXTENSION_STRING                105
 # define X509V3_R_INVALID_INHERITANCE                     165
 # define X509V3_R_INVALID_IPADDRESS                       166
@@ -142,6 +144,7 @@ int ERR_load_X509V3_strings(void);
 # define X509V3_R_ISSUER_DECODE_ERROR                     126
 # define X509V3_R_MISSING_VALUE                           124
 # define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS           142
+# define X509V3_R_NEGATIVE_PATHLEN                        168
 # define X509V3_R_NO_CONFIG_DATABASE                      136
 # define X509V3_R_NO_ISSUER_CERTIFICATE                   121
 # define X509V3_R_NO_ISSUER_DETAILS                       127
diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t
index 42d44dcdce..aaa7fa3d90 100644
--- a/test/recipes/25-test_verify.t
+++ b/test/recipes/25-test_verify.t
@@ -27,7 +27,7 @@ sub verify {
     run(app([@args]));
 }
 
-plan tests => 144;
+plan tests => 145;
 
 # Canonical success
 ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
@@ -372,13 +372,16 @@ ok(verify("root-cert-rsa2", "sslserver", ["root-cert-rsa2"], [], "-check_ss_sig"
        "accept trusted self-signed EE cert excluding key usage keyCertSign");
 
 SKIP: {
-    skip "Ed25519 is not supported by this OpenSSL build", 5
+    skip "Ed25519 is not supported by this OpenSSL build", 6
 	      if disabled("ec");
 
     # ED25519 certificate from draft-ietf-curdle-pkix-04
     ok(verify("ee-ed25519", "sslserver", ["root-ed25519"], []),
        "accept X25519 EE cert issued by trusted Ed25519 self-signed CA cert");
 
+    ok(!verify("ee-ed25519", "sslserver", ["root-ed25519"], [], "-x509_strict"),
+       "reject X25519 EE cert in strict mode since AKID is missing");
+
     ok(!verify("root-ed25519", "sslserver", ["ee-ed25519"], []),
        "fail Ed25519 CA and EE certs swapped");
 
diff --git a/test/testx509.pem b/test/testx509.pem
index 8a85d14964..e0c7a1f9af 100644
--- a/test/testx509.pem
+++ b/test/testx509.pem
@@ -1,10 +1,10 @@
 -----BEGIN CERTIFICATE-----
-MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV
-BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz
-MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM
-RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF
-AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO
-/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE
-Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ
-zl9HYIMxATFyqSiD9jsx
+MIIBczCCAR0CFEqkMs9xq0qfdNflIpoqdDaOU/ThMA0GCSqGSIb3DQEBBAUAMDox
+CzAJBgNVBAYTAkFVMQwwCgYDVQQIDANRTEQxHTAbBgNVBAMMFFNTTGVheSByc2Eg
+dGVzdCBjZXJ0MCAXDTIwMDczMTE3MTM0NVoYDzIxMjAwNzA3MTcxMzQ1WjA6MQsw
+CQYDVQQGEwJBVTEMMAoGA1UECAwDUUxEMR0wGwYDVQQDDBRTU0xlYXkgcnNhIHRl
+c3QgY2VydDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDUZKgYSMuJdiw2aIQIG4LD
+vm9HbUnyJyj6WgPkpw98dVKTj0jo3F6n/e3anYzvSpOiPkTuvw209yslzJs40Sf7
+AgMBAAEwDQYJKoZIhvcNAQEEBQADQQBV1bQAvyLvJQrNt7WEKmo/inigwjsvQYwd
+nxmV6zWhqpQZmo86/ixumUa6zTlq+y4+wiiFngMZ7Bt0O769Nlzx
 -----END CERTIFICATE-----


More information about the openssl-commits mailing list