+ if (i_ext >= 0
+ && !X509_EXTENSION_get_critical(X509_get_ext((X509 *)x, i_ext)))
+ return 0;
+ return 1;
+}
+
+static int check_purpose_code_sign(const X509_PURPOSE *xp, const X509 *x,
+ int non_leaf)
+{
+ int i_ext;
+
+ /*
+ * If non_leaf is true we must check if this is a valid CA certificate.
+ * The extra requirements by the CA/Browser Forum are not checked.
+ */
+ if (non_leaf)
+ return check_ca(x);
+
+ /*
+ * Check the key usage and extended key usage fields:
+ *
+ * Reference: CA/Browser Forum,
+ * Baseline Requirements for the Issuance and Management of
+ * Publicly‐Trusted Code Signing Certificates, Version 3.0.0,
+ * Section 7.1.2.3: Code signing and Timestamp Certificate
+ *
+ * Checking covers Key Usage and Extended Key Usage attributes.
+ * The certificatePolicies, cRLDistributionPoints (CDP), and
+ * authorityInformationAccess (AIA) extensions are so far not checked.
+ */
+ /* Key Usage */
+ if ((x->ex_flags & EXFLAG_KUSAGE) == 0)
+ return 0;
+ if ((x->ex_kusage & KU_DIGITAL_SIGNATURE) == 0)
+ return 0;
+ if ((x->ex_kusage & (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) != 0)
+ return 0;
+
+ /* Key Usage MUST be critical */
+ i_ext = X509_get_ext_by_NID(x, NID_key_usage, -1);
+ if (i_ext < 0)
+ return 0;