Also constify related CMS/PKCS7 functions and improve error codes thrown.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14503)
*Richard Levitte*
* Improved adherence to Enhanced Security Services (ESS, RFC 2634 and RFC 5035)
- for the TSP implementation.
+ for the TSP and CMS Advanced Electronic Signatures (CAdES) implementations.
As required by RFC 5035 check both ESSCertID and ESSCertIDv2 if both present.
Correct the semantics of checking the validation chain in case ESSCertID{,v2}
contains more than one certificate identifier: This means that all
{"sign", OPT_SIGN, '-', "Sign message"},
{"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
{"resign", OPT_RESIGN, '-', "Resign a signed message"},
- {"cades", OPT_CADES, '-', "Include signer certificate digest"},
+ {"cades", OPT_CADES, '-', "Include or check signingCertificate (CAdES-BES)"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
{"verify_retcode", OPT_VERIFY_RETCODE, '-',
"Exit non-zero on verification failure"},
if ((flags & CMS_CADES) != 0) {
if ((flags & CMS_NOATTR) != 0) {
BIO_puts(bio_err, "Incompatible options: "
- "CAdES required signed attributes\n");
+ "CAdES requires signed attributes\n");
goto opthelp;
}
if (operation == SMIME_VERIFY
&& (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) {
- BIO_puts(bio_err, "Incompatible options: CAdES validation require"
+ BIO_puts(bio_err, "Incompatible options: CAdES validation requires"
" certs and signed attributes validations\n");
goto opthelp;
}
return 0;
}
-void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid,
+void *CMS_signed_get0_data_by_OBJ(const CMS_SignerInfo *si,
+ const ASN1_OBJECT *oid,
int lastpos, int type)
{
return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type);
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_KEY), "error setting key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_RECIPIENTINFO),
"error setting recipientinfo"},
- {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE),
- "ess no signing certid attribute"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR),
"ess signing certid mismatch error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),
return 1;
}
-/*
- First, get the ESS_SIGNING_CERT(V2) signed attribute from |si|.
- Then check matching of each cert of trust |chain| with one of
- the |cert_ids|(Hash+IssuerID) list from this ESS_SIGNING_CERT.
- Derived from ts_check_signing_certs()
-*/
-int ossl_ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain)
+int ossl_cms_check_signing_certs(const CMS_SignerInfo *si,
+ const STACK_OF(X509) *chain)
{
ESS_SIGNING_CERT *ss = NULL;
ESS_SIGNING_CERT_V2 *ssv2 = NULL;
- X509 *cert;
- int i = 0, ret = 0;
-
- if (ossl_cms_signerinfo_get_signing_cert(si, &ss) > 0
- && ss->cert_ids != NULL) {
- STACK_OF(ESS_CERT_ID) *cert_ids = ss->cert_ids;
-
- cert = sk_X509_value(chain, 0);
- if (ossl_ess_find_cert(cert_ids, cert) != 0)
- goto err;
-
- /*
- * Check the other certificates of the chain.
- * Fail if no signing certificate ids found for each certificate.
- */
- if (sk_ESS_CERT_ID_num(cert_ids) > 1) {
- /* for each chain cert, try to find its cert id */
- for (i = 1; i < sk_X509_num(chain); ++i) {
- cert = sk_X509_value(chain, i);
- if (ossl_ess_find_cert(cert_ids, cert) < 0)
- goto err;
- }
- }
- } else if (ossl_cms_signerinfo_get_signing_cert_v2(si, &ssv2) > 0
- && ssv2->cert_ids!= NULL) {
- STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = ssv2->cert_ids;
-
- cert = sk_X509_value(chain, 0);
- if (ossl_ess_find_cert_v2(cert_ids_v2, cert) != 0)
- goto err;
-
- /*
- * Check the other certificates of the chain.
- * Fail if no signing certificate ids found for each certificate.
- */
- if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) {
- /* for each chain cert, try to find its cert id */
- for (i = 1; i < sk_X509_num(chain); ++i) {
- cert = sk_X509_value(chain, i);
- if (ossl_ess_find_cert_v2(cert_ids_v2, cert) < 0)
- goto err;
- }
- }
- } else {
- ERR_raise(ERR_LIB_CMS, CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE);
- return 0;
- }
- ret = 1;
- err:
- if (!ret)
- ERR_raise(ERR_LIB_CMS, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR);
+ int ret = ossl_cms_signerinfo_get_signing_cert(si, &ss) >= 0
+ && ossl_cms_signerinfo_get_signing_cert_v2(si, &ssv2) >= 0
+ && ossl_ess_check_signing_certs(ss, ssv2, chain, 1);
ESS_SIGNING_CERT_free(ss);
ESS_SIGNING_CERT_V2_free(ssv2);
/* ESS routines */
-int ossl_ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain);
+int ossl_cms_check_signing_certs(const CMS_SignerInfo *si,
+ const STACK_OF(X509) *chain);
int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt);
int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt);
if (cadesVerify) {
STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
- if (ossl_ess_check_signing_certs(si, si_chain) <= 0)
+ if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
goto err;
}
}
error reading messagedigest attribute
CMS_R_ERROR_SETTING_KEY:115:error setting key
CMS_R_ERROR_SETTING_RECIPIENTINFO:116:error setting recipientinfo
-CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE:182:ess no signing certid attribute
CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR:183:ess signing certid mismatch error
CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length
CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter
ENGINE_R_UNIMPLEMENTED_DIGEST:147:unimplemented digest
ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD:101:unimplemented public key method
ENGINE_R_VERSION_INCOMPATIBILITY:145:version incompatibility
+ESS_R_EMPTY_ESS_CERT_ID_LIST:107:empty ess cert id list
+ESS_R_ESS_CERT_DIGEST_ERROR:103:ess cert digest error
+ESS_R_ESS_CERT_ID_NOT_FOUND:104:ess cert id not found
+ESS_R_ESS_CERT_ID_WRONG_ORDER:105:ess cert id wrong order
+ESS_R_ESS_DIGEST_ALG_UNKNOWN:106:ess digest alg unknown
ESS_R_ESS_SIGNING_CERTIFICATE_ERROR:102:ess signing certificate error
ESS_R_ESS_SIGNING_CERT_ADD_ERROR:100:ess signing cert add error
ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error
+ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE:108:\
+ missing signing certificate attribute
EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed
EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed
EVP_R_BAD_ALGORITHM_NAME:200:bad algorithm name
EVP_R_NO_OPERATION_SET:149:no operation set
EVP_R_NULL_MAC_PKEY_CTX:208:null mac pkey ctx
EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
+EVP_R_OPERATION_NOT_INITIALIZED:151:operation not initialized
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
-EVP_R_OPERATION_NOT_INITIALIZED:151:operation not initialized
EVP_R_OUTPUT_WOULD_OVERFLOW:202:output would overflow
EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
* Returns < 0 if attribute is not found, 1 if found, or
* -1 on attribute parsing failure.
*/
-int ossl_cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si,
+int ossl_cms_signerinfo_get_signing_cert_v2(const CMS_SignerInfo *si,
ESS_SIGNING_CERT_V2 **psc)
{
ASN1_STRING *str;
* Returns < 0 if attribute is not found, 1 if found, or
* -1 on attribute parsing failure.
*/
-int ossl_cms_signerinfo_get_signing_cert(CMS_SignerInfo *si,
+int ossl_cms_signerinfo_get_signing_cert(const CMS_SignerInfo *si,
ESS_SIGNING_CERT **psc)
{
ASN1_STRING *str;
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 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
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA ESS_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_EMPTY_ESS_CERT_ID_LIST),
+ "empty ess cert id list"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_DIGEST_ERROR),
+ "ess cert digest error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_ID_NOT_FOUND),
+ "ess cert id not found"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_ID_WRONG_ORDER),
+ "ess cert id wrong order"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_DIGEST_ALG_UNKNOWN),
+ "ess digest alg unknown"},
{ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERTIFICATE_ERROR),
"ess signing certificate error"},
{ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_ADD_ERROR),
"ess signing cert add error"},
{ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR),
"ess signing cert v2 add error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE),
+ "missing signing certificate attribute"},
{0, NULL}
};
return NULL;
}
-ESS_SIGNING_CERT *ossl_ess_signing_cert_get(PKCS7_SIGNER_INFO *si)
+ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si)
{
ASN1_TYPE *attr;
const unsigned char *p;
return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
}
-ESS_SIGNING_CERT_V2 *ossl_ess_signing_cert_v2_get(PKCS7_SIGNER_INFO *si)
+ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si)
{
ASN1_TYPE *attr;
const unsigned char *p;
return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert));
}
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-int ossl_ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
-{
- int i;
- unsigned char cert_sha1[SHA_DIGEST_LENGTH];
-
- if (cert_ids == NULL || cert == NULL)
- return -1;
-
- /* Recompute SHA1 hash of certificate if necessary (side effect). */
- if (!x509v3_cache_extensions(cert))
- return -1;
-
- /* TODO(3.0): fetch sha1 algorithm from providers */
- if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
- return -1;
-
- /* Look for cert in the cert_ids vector. */
- for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) {
- const ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
-
- if (cid->hash->length == SHA_DIGEST_LENGTH
- && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) {
- const ESS_ISSUER_SERIAL *is = cid->issuer_serial;
-
- if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
- return i;
- }
- }
-
- return -1;
-}
-
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-int ossl_ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids,
- const X509 *cert)
-{
- int i;
- unsigned char cert_digest[EVP_MAX_MD_SIZE];
- unsigned int len;
-
- /* Look for cert in the cert_ids vector. */
- for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) {
- const ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i);
- const EVP_MD *md;
-
- if (cid == NULL)
- return -1;
- if (cid->hash_alg != NULL)
- md = EVP_get_digestbyobj(cid->hash_alg->algorithm);
- else
- md = EVP_sha256();
-
- /* TODO(3.0): fetch sha1 algorithm from providers */
- if (!X509_digest(cert, md, cert_digest, &len))
- return -1;
-
- if (cid->hash->length != (int)len)
- return -1;
-
- if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) {
- const ESS_ISSUER_SERIAL *is = cid->issuer_serial;
-
- if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
- return i;
- }
- }
-
- return -1;
-}
-
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-int ossl_ess_find_cid(const STACK_OF(X509) *certs,
- ESS_CERT_ID *cid, ESS_CERT_ID_V2 *cid_v2)
+/*
+ * Find cert referenced by |cid| (if not NULL, else |cidv2|) in |certs|.
+ * If the cid{,v2} index is 0, the cert must be in the first in |certs| list.
+ * Return 0 on not found, -1 on error, else 1 + the position in |certs|.
+ */
+static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2,
+ int index, const STACK_OF(X509) *certs)
{
+ const X509 *cert;
+ const EVP_MD *md;
unsigned char cert_digest[EVP_MAX_MD_SIZE];
unsigned int len, cid_hash_len;
- int i;
const ESS_ISSUER_SERIAL *is;
+ int i;
- if (certs == NULL || (cid == NULL && cid_v2 == NULL))
+ if (cid == NULL && cid_v2 == NULL) {
+ ERR_raise(ERR_LIB_ESS, ERR_R_PASSED_INVALID_ARGUMENT);
return -1;
+ }
/* Look for cert with cid in the certs. */
for (i = 0; i < sk_X509_num(certs); ++i) {
- const X509 *cert = sk_X509_value(certs, i);
- const EVP_MD *md;
+ cert = sk_X509_value(certs, i);
- /* TODO(3.0): fetch sha algorithm from providers */
if (cid != NULL)
md = EVP_sha1();
else
md = cid_v2->hash_alg == NULL ? EVP_sha256() :
EVP_get_digestbyobj(cid_v2->hash_alg->algorithm);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN);
+ return -1;
+ }
+
cid_hash_len = cid != NULL ? cid->hash->length : cid_v2->hash->length;
if (!X509_digest(cert, md, cert_digest, &len)
- || cid_hash_len != len)
+ || cid_hash_len != len) {
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR);
return -1;
+ }
if (memcmp(cid != NULL ? cid->hash->data : cid_v2->hash->data,
cert_digest, len) == 0) {
is = cid != NULL ? cid->issuer_serial : cid_v2->issuer_serial;
- if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
- return i;
+ /* Well, it's not really required to match the serial numbers. */
+ if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) {
+ if ((i == 0) == (index == 0))
+ return i + 1;
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER);
+ return -1;
+ }
}
}
- return -1;
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND);
+ return 0;
+}
+
+/*
+ * If ESSCertID and/or ESSCertIDv2 exist, which must be non-empty if given,
+ * check if their first ID entry matches the signer cert first in chain
+ * and each further ID entry matches any further cert in the chain.
+ */
+int ossl_ess_check_signing_certs(const ESS_SIGNING_CERT *ss,
+ const ESS_SIGNING_CERT_V2 *ssv2,
+ const STACK_OF(X509) *chain,
+ int require_signing_cert)
+{
+ int n_v1 = ss == NULL ? -1 : sk_ESS_CERT_ID_num(ss->cert_ids);
+ int n_v2 = ssv2 == NULL ? -1 : sk_ESS_CERT_ID_V2_num(ssv2->cert_ids);
+ int i;
+
+ if (require_signing_cert && ss == NULL && ssv2 == NULL) {
+ ERR_raise(ERR_LIB_CMS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE);
+ return 0;
+ }
+ if (n_v1 == 0 || n_v2 == 0) {
+ ERR_raise(ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST);
+ return 0;
+ }
+ /* If both ss and ssv2 exist, as required evaluate them independently. */
+ for (i = 0; i < n_v1; i++)
+ if (find(sk_ESS_CERT_ID_value(ss->cert_ids, i), NULL, i, chain) <= 0)
+ return 0;
+ for (i = 0; i < n_v2; i++)
+ if (find(NULL, sk_ESS_CERT_ID_V2_value(ssv2->cert_ids, i), i, chain) <= 0)
+ return 0;
+ return 1;
}
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
void *value);
-static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
+static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid);
int PKCS7_type_is_other(PKCS7 *p7)
{
return ri->issuer_and_serial;
}
-ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
+ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->auth_attr, nid);
}
-ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
+ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->unauth_attr, nid);
}
-static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
+static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid)
{
int idx;
X509_ATTRIBUTE *xa;
static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
X509 *signer, STACK_OF(X509) **chain);
-static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
- STACK_OF(X509) *chain);
+static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si,
+ const STACK_OF(X509) *chain);
static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx,
PKCS7 *token, TS_TST_INFO *tst_info);
return ret;
}
-static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
- STACK_OF(X509) *chain)
+static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si,
+ const STACK_OF(X509) *chain)
{
- ESS_SIGNING_CERT *ss = ossl_ess_signing_cert_get(si);
- ESS_SIGNING_CERT_V2 *ssv2 = ossl_ess_signing_cert_v2_get(si);
- int i, j;
- int ret = 0;
+ ESS_SIGNING_CERT *ss = ossl_ess_get_signing_cert(si);
+ ESS_SIGNING_CERT_V2 *ssv2 = ossl_ess_get_signing_cert_v2(si);
+ int ret = ossl_ess_check_signing_certs(ss, ssv2, chain, 1);
- /*
- * Check if first ESSCertIDs matches signer cert
- * and each further ESSCertIDs matches any cert in the chain.
- */
- if (ss != NULL)
- for (i = 0; i < sk_ESS_CERT_ID_num(ss->cert_ids); i++) {
- j = ossl_ess_find_cid(chain, sk_ESS_CERT_ID_value(ss->cert_ids, i),
- NULL);
- if (j < 0 || (i == 0 && j != 0))
- goto err;
- }
- if (ssv2 != NULL)
- for (i = 0; i < sk_ESS_CERT_ID_V2_num(ssv2->cert_ids); i++) {
- j = ossl_ess_find_cid(chain, NULL,
- sk_ESS_CERT_ID_V2_value(ssv2->cert_ids, i));
- if (j < 0 || (i == 0 && j != 0))
- goto err;
- }
- ret = 1;
-
- err:
- if (!ret)
- ERR_raise(ERR_LIB_TS, TS_R_ESS_SIGNING_CERTIFICATE_ERROR);
ESS_SIGNING_CERT_free(ss);
ESS_SIGNING_CERT_V2_free(ssv2);
return ret;
=item B<-cades>
-Add an ESS signing-certificate or ESS signing-certificate-v2 signed-attribute to the SignerInfo, in order to make
-the signature comply with the requirements for a CAdES Basic Electronic Signature (CAdES-BES). See the NOTES
-section for more details.
+When used with B<-sign>,
+add an ESS signingCertificate or ESS signingCertificateV2 signed-attribute
+to the SignerInfo, in order to make the signature comply with the requirements
+for a CAdES Basic Electronic Signature (CAdES-BES).
+When used with B<-verify>, require and check signer certificate digest.
+See the NOTES section for more details.
=item B<-data_create>
=head1 CADES BASIC ELECTRONIC SIGNATURE (CADES-BES)
-A CAdES Basic Electronic Signature (CAdES-BES), as defined in the European Standard ETSI EN 319 122-1 V1.1.1, contains:
+A CAdES Basic Electronic Signature (CAdES-BES),
+as defined in the European Standard ETSI EN 319 122-1 V1.1.1, contains:
=over 4
=item *
-An ESS signing-certificate or ESS signing-certificate-v2 attribute, as defined
-in Enhanced Security Services (ESS), RFC 2634 and RFC 5035.
-An ESS signing-certificate attribute only allows for the use of SHA-1 as a digest algorithm.
-An ESS signing-certificate-v2 attribute allows for the use of any digest algorithm.
+An ESS signingCertificate or ESS signingCertificateV2 attribute,
+as defined in Enhanced Security Services (ESS), RFC 2634 and RFC 5035.
+An ESS signingCertificate attribute only allows for SHA-1 as digest algorithm.
+An ESS signingCertificateV2 attribute allows for any digest algorithm.
=item *
The digital signature value computed on the user data and, when present, on the signed attributes.
NOTE that the B<-cades> option applies to the B<-sign> or B<-verify> operations.
-With this option, the B<-verify> operation also checks that the signing-certificates
-attribute is present, and its value matches the verification trust chain built
-during the verification process.
+With this option, the B<-verify> operation also requires that the
+signingCertificate attribute is present and checks that the given identifiers
+match the verification trust chain built during the verification process.
=back
The SignedData objects created by the TSA always contain the
certificate identifier of the signing certificate in a signed
-attribute (see RFC 2634, Enhanced Security Services). If this option
-is set to yes and either the B<certs> variable or the B<-chain> option
+attribute (see RFC 2634, Enhanced Security Services).
+If this variable is set to no, only this signing certificate identifier
+is included in the SigningCertificate signed attribute.
+If this variable is set to yes and the B<certs> variable or the B<-chain> option
is specified then the certificate identifiers of the chain will also
-be included in the SigningCertificate signed attribute. If this
-variable is set to no, only the signing certificate identifier is
-included. Default is no. (Optional)
+be included, where the B<-chain> option overrides the B<certs> variable.
+Default is no. (Optional)
=item B<ess_cert_id_alg>
verified, unless CMS_CADES flag is also set.
If B<CMS_CADES> is set, each signer certificate is checked against the
-"ESS signing-certificate" extension added in the signed attributes of the
-signature.
+ESS signingCertificate or ESS signingCertificateV2 extension
+that is required in the signed attributes of the signature.
If B<CMS_NO_CONTENT_VERIFY> is set then the content digest is not checked.
int ossl_cms_add1_signing_cert(CMS_SignerInfo *si, ESS_SIGNING_CERT *sc);
int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si, ESS_SIGNING_CERT_V2 *sc);
-int ossl_cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si,
+int ossl_cms_signerinfo_get_signing_cert_v2(const CMS_SignerInfo *si,
ESS_SIGNING_CERT_V2 **psc);
-int ossl_cms_signerinfo_get_signing_cert(CMS_SignerInfo *si,
+int ossl_cms_signerinfo_get_signing_cert(const CMS_SignerInfo *si,
ESS_SIGNING_CERT **psc);
# endif /* OPENSSL_NO_CMS */
/* internal ESS related stuff */
-ESS_SIGNING_CERT *ossl_ess_signing_cert_get(PKCS7_SIGNER_INFO *si);
+ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si);
int ossl_ess_signing_cert_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc);
ESS_SIGNING_CERT *ossl_ess_signing_cert_new_init(X509 *signcert,
STACK_OF(X509) *certs,
int issuer_needed);
-ESS_SIGNING_CERT_V2 *ossl_ess_signing_cert_v2_get(PKCS7_SIGNER_INFO *si);
+ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si);
int ossl_ess_signing_cert_v2_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT_V2 *sc);
ESS_SIGNING_CERT_V2 *ossl_ess_signing_cert_v2_new_init(const EVP_MD *hash_alg,
STACK_OF(X509) *certs,
int issuer_needed);
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-int ossl_ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids,
- const X509 *cert);
-int ossl_ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
-int ossl_ess_find_cid(const STACK_OF(X509) *certs,
- ESS_CERT_ID *cid, ESS_CERT_ID_V2 *cid_v2);
+int ossl_ess_check_signing_certs(const ESS_SIGNING_CERT *ss,
+ const ESS_SIGNING_CERT_V2 *ssv2,
+ const STACK_OF(X509) *chain,
+ int require_signing_cert);
/*-
* IssuerSerial ::= SEQUENCE {
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2021 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
int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
const char *attrname, int type,
const void *bytes, int len);
-void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid,
+void *CMS_signed_get0_data_by_OBJ(const CMS_SignerInfo *si,
+ const ASN1_OBJECT *oid,
int lastpos, int type);
int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114
# define CMS_R_ERROR_SETTING_KEY 115
# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116
-# define CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE 182
# define CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR 183
# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117
# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176
/*
* ESS reason codes.
*/
+# define ESS_R_EMPTY_ESS_CERT_ID_LIST 107
+# define ESS_R_ESS_CERT_DIGEST_ERROR 103
+# define ESS_R_ESS_CERT_ID_NOT_FOUND 104
+# define ESS_R_ESS_CERT_ID_WRONG_ORDER 105
+# define ESS_R_ESS_DIGEST_ALG_UNKNOWN 106
# define ESS_R_ESS_SIGNING_CERTIFICATE_ERROR 102
# define ESS_R_ESS_SIGNING_CERT_ADD_ERROR 100
# define ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR 101
+# define ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE 108
#endif
void *data);
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
void *value);
-ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
-ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid);
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
STACK_OF(X509_ATTRIBUTE) *sk);
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
);
my @smime_cms_cades_ko_tests = (
- [ "signed content DER format, RSA key, but verified as CAdES-BES compatible",
+ [ "sign content DER format, RSA key, not CAdES-BES compatible",
[ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
"-certfile", catfile($smdir, "smroot.pem"),
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
+ "fail to verify token because requiring CAdES-BES compatibility",
[ @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
\&final_compare
};
subtest "CAdES ko tests\n" => sub {
- plan tests => (scalar @smime_cms_cades_ko_tests);
+ plan tests => 2 * scalar @smime_cms_cades_ko_tests;
foreach (@smime_cms_cades_ko_tests) {
SKIP: {
my $skip_reason = check_availability($$_[0]);
skip $skip_reason, 1 if $skip_reason;
- ok(run(app(["openssl", "cms", @{$$_[1]}]))
- && !run(app(["openssl", "cms", @{$$_[2]}])),
- $$_[0]);
+ ok(run(app(["openssl", "cms", @{$$_[1]}])), $$_[0]);
+ ok(!run(app(["openssl", "cms", @{$$_[3]}])), $$_[2]);
}
}
};