X509: Add "code sign" as purpose for verification of certificates

Code signing certificates have other properties as for example described in
CA Browser Forum documents. This leads to "unsupported certificate purpose" errors when
verifying signed objects.
This patch adds the purpose "codesign" to the table in X.509 certificate verification and
the verification parameter "code_sign" to X509_VERIFY_PARAM.

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18567)
This commit is contained in:
Lutz Jaenicke 2021-10-14 15:24:18 +02:00 committed by Tomas Mraz
parent 1a68a3e421
commit 178696d602
6 changed files with 74 additions and 3 deletions

View File

@ -32,6 +32,8 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
int require_ca);
static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
int require_ca);
static int check_purpose_code_sign(const X509_PURPOSE *xp, const X509 *x,
int require_ca);
static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
int require_ca);
static int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x,
@ -61,6 +63,9 @@ static X509_PURPOSE xstandard[] = {
{X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign",
NULL},
{X509_PURPOSE_CODE_SIGN, X509_TRUST_OBJECT_SIGN, 0,
check_purpose_code_sign, "Code signing", "codesign",
NULL},
};
#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard)
@ -865,6 +870,57 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
return 1;
}
static int check_purpose_code_sign(const X509_PURPOSE *xp, const X509 *x,
int require_ca)
{
int i_ext;
/* If ca is true we must return if this is a valid CA certificate. */
if (require_ca)
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
* PubliclyTrusted 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.
* Other properties like CRL Distribution Points and Authoriy
* Information Access (AIA) are 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;
if (i_ext >= 0) {
X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
if (!X509_EXTENSION_get_critical(ext))
return 0;
}
/* Extended Key Usage */
if ((x->ex_flags & EXFLAG_XKUSAGE) == 0)
return 0;
if ((x->ex_xkusage & XKU_CODE_SIGN) == 0)
return 0;
if ((x->ex_xkusage & (XKU_ANYEKU | XKU_SSL_SERVER)) != 0)
return 0;
return 1;
}
static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
int require_ca)
{

View File

@ -502,6 +502,18 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
*/
static const X509_VERIFY_PARAM default_table[] = {
{
"code_sign", /* Code sign parameters */
0, /* check time to use */
0, /* inheritance flags */
0, /* flags */
X509_PURPOSE_CODE_SIGN, /* purpose */
X509_TRUST_OBJECT_SIGN, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id
},
{
"default", /* X509 default parameters */
0, /* check time to use */

View File

@ -458,7 +458,7 @@ Set policy variable inhibit-policy-mapping (see RFC5280).
The intended use for the certificate.
Currently defined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
C<smimesign>, C<smimeencrypt>, C<crlsign>, C<ocsphelper>, C<timestampsign>,
and C<any>.
C<codesign> and C<any>.
If peer certificate verification is enabled, by default the TLS implementation
as well as the commands B<s_client> and B<s_server> check for consistency
with TLS server or TLS client use, respectively.

View File

@ -187,7 +187,8 @@ verified in the I<ctx>. Built-in available values for the I<purpose> argument
are B<X509_PURPOSE_SSL_CLIENT>, B<X509_PURPOSE_SSL_SERVER>,
B<X509_PURPOSE_NS_SSL_SERVER>, B<X509_PURPOSE_SMIME_SIGN>,
B<X509_PURPOSE_SMIME_ENCRYPT>, B<X509_PURPOSE_CRL_SIGN>, B<X509_PURPOSE_ANY>,
B<X509_PURPOSE_OCSP_HELPER> and B<X509_PURPOSE_TIMESTAMP_SIGN>. It is also
B<X509_PURPOSE_OCSP_HELPER>, B<X509_PURPOSE_TIMESTAMP_SIGN> and
B<X509_PURPOSE_CODE_SIGN>. It is also
possible to create a custom purpose value. Setting a purpose will ensure that
the key usage declared within certificates in the chain being verified is
consistent with that purpose as well as, potentially, other checks. Every

View File

@ -29,6 +29,7 @@ Below are the potential ID's that can be checked:
# define X509_PURPOSE_ANY 7
# define X509_PURPOSE_OCSP_HELPER 8
# define X509_PURPOSE_TIMESTAMP_SIGN 9
# define X509_PURPOSE_CODE_SIGN 10
The checks performed take into account the X.509 extensions
keyUsage, extendedKeyUsage, and basicConstraints.

View File

@ -478,9 +478,10 @@ typedef struct x509_purpose_st {
# define X509_PURPOSE_ANY 7
# define X509_PURPOSE_OCSP_HELPER 8
# define X509_PURPOSE_TIMESTAMP_SIGN 9
# define X509_PURPOSE_CODE_SIGN 10
# define X509_PURPOSE_MIN 1
# define X509_PURPOSE_MAX 9
# define X509_PURPOSE_MAX 10
/* Flags for X509V3_EXT_print() */