TS and CMS CAdES-BES: Refactor check_signing_certs() funcs into common ESS func

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)
This commit is contained in:
Dr. David von Oheimb 2021-03-12 19:45:40 +01:00 committed by Dr. David von Oheimb
parent bef876f97e
commit 63b64f19c1
24 changed files with 160 additions and 230 deletions

View File

@ -59,7 +59,7 @@ OpenSSL 3.0
*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

View File

@ -126,7 +126,7 @@ const OPTIONS cms_options[] = {
{"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"},
@ -728,12 +728,12 @@ int cms_main(int argc, char **argv)
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;
}

View File

@ -125,7 +125,8 @@ int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
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);

View File

@ -59,8 +59,6 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
{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),

View File

@ -46,67 +46,14 @@ int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
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);

View File

@ -473,7 +473,8 @@ void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms);
/* 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);

View File

@ -381,7 +381,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
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;
}
}

View File

@ -299,7 +299,6 @@ CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\
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
@ -629,9 +628,16 @@ ENGINE_R_UNIMPLEMENTED_CIPHER:146:unimplemented cipher
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
@ -706,9 +712,9 @@ EVP_R_NO_KEY_SET:154:no key set
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

View File

@ -65,7 +65,7 @@ IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
* 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;
@ -92,7 +92,7 @@ int ossl_cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si,
* 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;

View File

@ -1,6 +1,6 @@
/*
* 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
@ -15,12 +15,24 @@
#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}
};

View File

@ -192,7 +192,7 @@ static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
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;
@ -204,7 +204,7 @@ ESS_SIGNING_CERT *ossl_ess_signing_cert_get(PKCS7_SIGNER_INFO *si)
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;
@ -289,112 +289,92 @@ static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert)
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;
}

View File

@ -18,7 +18,7 @@
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)
{
@ -1209,17 +1209,17 @@ PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
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;

View File

@ -17,8 +17,8 @@
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);
@ -202,37 +202,13 @@ end:
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;

View File

@ -161,9 +161,12 @@ Resign a message: take an existing message and one or more new signers.
=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>
@ -564,7 +567,8 @@ with caution. For a fuller description see L<CMS_decrypt(3)>).
=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
@ -582,19 +586,19 @@ Message-digest of the eContent OCTET STRING within encapContentInfo being signed
=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

View File

@ -469,12 +469,13 @@ the TSA name field of the response. Default is no. (Optional)
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>

View File

@ -72,8 +72,8 @@ If B<CMS_NO_ATTR_VERIFY> is set the signed attributes signature is not
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.

View File

@ -18,9 +18,9 @@
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 */

View File

@ -13,14 +13,14 @@
/* 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,
@ -28,12 +28,10 @@ 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 {

View File

@ -1,6 +1,6 @@
/*
* 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

View File

@ -310,7 +310,8 @@ int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
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);

View File

@ -49,7 +49,6 @@
# 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

View File

@ -21,8 +21,14 @@
/*
* 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

View File

@ -304,8 +304,8 @@ int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type,
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,

View File

@ -451,10 +451,11 @@ my @smime_cms_cades_tests = (
);
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
@ -798,16 +799,15 @@ subtest "CAdES; cms incompatible arguments tests\n" => sub {
};
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]);
}
}
};