mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
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:
parent
bef876f97e
commit
63b64f19c1
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user