Critical extension enforcement (introduced in #
8a639b9) is incorrect. These
checks were intended as CA requirements to prevent misinterpretation by
verifiers that don't support certain extensions. However, since we do support
these extensions, we have no requirement for them to be marked critical,
enforcing that is a mistake.
As noted in: #30233 (comment)
Co-authored-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Thu Mar 5 14:22:07 2026
(Merged from https://github.com/openssl/openssl/pull/30249)
*Bob Beck*
+ * Critical extension enforcement for EXFLAG_BCONS_CRITICAL,
+ EXFLAG_AKID_CRITICAL, EXFLAG_SKID_CRITICAL, and EXFLAG_SAN_CRITICAL is
+ incorrect. These checks were intended as CA requirements to prevent
+ misinterpretation by verifiers that don't support certain extensions
+ However, since we do support these extensions, there is no requirement for
+ them to be marked as critical. Enforcing that on X509_V_FLAG_X509_STRICT was a mistake.
+
+ *Daniel Kubec*
+
* Made `X509_ATTRIBUTE` accessor functions const-correct. The functions
`X509_ATTRIBUTE_get0_object()`, `X509_ATTRIBUTE_get0_type()`, and
`X509_ATTRIBUTE_get0_data()` now accept `const X509_ATTRIBUTE *` and
tmp_ex_flags |= EXFLAG_CRITICAL;
break;
}
- switch (nid) {
- case NID_basic_constraints:
- tmp_ex_flags |= EXFLAG_BCONS_CRITICAL;
- break;
- case NID_authority_key_identifier:
- tmp_ex_flags |= EXFLAG_AKID_CRITICAL;
- break;
- case NID_subject_key_identifier:
- tmp_ex_flags |= EXFLAG_SKID_CRITICAL;
- break;
- case NID_subject_alt_name:
- tmp_ex_flags |= EXFLAG_SAN_CRITICAL;
- break;
- default:
- break;
- }
}
/* Set x->siginf, ignoring errors due to unsupported algos */
CB_FAIL_IF((x->ex_kusage & KU_KEY_CERT_SIGN) == 0, ctx,
x, i, X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN);
}
- CB_FAIL_IF((x->ex_flags & EXFLAG_CA) != 0
- && (x->ex_flags & EXFLAG_BCONS) != 0
- && (x->ex_flags & EXFLAG_BCONS_CRITICAL) == 0,
- ctx, x, i, 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) {
CB_FAIL_IF((x->ex_flags & EXFLAG_KUSAGE) == 0,
|| x->altname == NULL)
&& X509_NAME_entry_count(X509_get_subject_name(x)) == 0,
ctx, x, i, X509_V_ERR_SUBJECT_NAME_EMPTY);
- CB_FAIL_IF(X509_NAME_entry_count(X509_get_subject_name(x)) == 0
- && x->altname != NULL
- && (x->ex_flags & EXFLAG_SAN_CRITICAL) == 0,
- ctx, x, i, X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL);
/* Check SAN is non-empty according to RFC 5280 section 4.2.1.6 */
CB_FAIL_IF(x->altname != NULL
&& sk_GENERAL_NAME_num(x->altname) <= 0,
/* Check sig alg consistency acc. to RFC 5280 section 4.1.1.2 */
CB_FAIL_IF(X509_ALGOR_cmp(&x->sig_alg, &x->cert_info.signature) != 0,
ctx, x, i, X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY);
- CB_FAIL_IF(x->akid != NULL
- && (x->ex_flags & EXFLAG_AKID_CRITICAL) != 0,
- ctx, x, i, X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL);
- CB_FAIL_IF(x->skid != NULL
- && (x->ex_flags & EXFLAG_SKID_CRITICAL) != 0,
- ctx, x, i, X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL);
if (X509_get_version(x) >= X509_VERSION_3) {
/* Check AKID presence acc. to RFC 5280 section 4.2.1.1 */
/*
=item *
-The basicConstraints of CA certificates must be marked critical.
-
-=item *
-
CA certificates must explicitly include the keyUsage extension.
=item *
=item *
-Any given authorityKeyIdentifier and any given subjectKeyIdentifier
-must not be marked critical.
-
-=item *
-
The authorityKeyIdentifier must be given for X.509v3 certs unless they
are self-signed.
Since OpenSSL 1.1.0, the B<-trusted_first> option is always enabled.
-The checks enabled by B<-x509_strict> have been extended in OpenSSL 3.0.
+The checks enabled by B<-x509_strict> have been extended in OpenSSL 3.0,
+which has been partially reverted in OpenSSL 4.0.
=head1 COPYRIGHT
#define EXFLAG_FRESHEST 0x1000
#define EXFLAG_SS 0x2000 /* cert is apparently self-signed */
+#define EXFLAG_NO_FINGERPRINT 0x100000
+
+/*
+ * The following flags are no longer used. On X509_V_FLAG_X509_STRICT they were
+ * previously enforced as checks on critical extensions but this behavior has
+ * been removed.
+ */
#define EXFLAG_BCONS_CRITICAL 0x10000
#define EXFLAG_AKID_CRITICAL 0x20000
#define EXFLAG_SKID_CRITICAL 0x40000
#define EXFLAG_SAN_CRITICAL 0x80000
-#define EXFLAG_NO_FINGERPRINT 0x100000
/* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3 */
#define KU_DIGITAL_SIGNATURE X509v3_KU_DIGITAL_SIGNATURE