mirror of
https://github.com/openssl/openssl.git
synced 2025-03-19 19:50:42 +08:00
crypto/cms: add CAdES-BES signed attributes validation
for signing certificate V2 and signing certificate extensions. CAdES: lowercase name for now internal methods. crypto/cms: generated file changes. Add some CHANGES entries. [extended tests] Reviewed-by: Shane Lontis <shane.lontis@oracle.com> Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/8098)
This commit is contained in:
parent
f7f53d7d61
commit
9e3c510bde
@ -23,6 +23,15 @@ OpenSSL 3.0
|
||||
|
||||
### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
|
||||
|
||||
* Add CAdES-BES signature verification support, mostly derived
|
||||
from ESSCertIDv2 TS (RFC 5816) contribution by Marek Klein.
|
||||
|
||||
*Filipe Raimundo da Silva*
|
||||
|
||||
* Add CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API.
|
||||
|
||||
*Antonio Iacono*
|
||||
|
||||
* Deprecated EC_POINT_make_affine() and EC_POINTs_make_affine(). These
|
||||
functions are not widely used and now OpenSSL automatically perform this
|
||||
conversion when needed.
|
||||
|
13
apps/cms.c
13
apps/cms.c
@ -670,12 +670,18 @@ int cms_main(int argc, char **argv)
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
if (flags & CMS_CADES) {
|
||||
if (flags & CMS_NOATTR) {
|
||||
if ((flags & CMS_CADES) != 0) {
|
||||
if ((flags & CMS_NOATTR) != 0) {
|
||||
BIO_puts(bio_err, "Incompatible options: "
|
||||
"CAdES required 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"
|
||||
" certs and signed attributes validations\n");
|
||||
goto opthelp;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation & SMIME_SIGNERS) {
|
||||
@ -1115,7 +1121,8 @@ int cms_main(int argc, char **argv)
|
||||
goto end;
|
||||
} else if (operation == SMIME_VERIFY) {
|
||||
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
|
||||
BIO_printf(bio_err, "Verification successful\n");
|
||||
BIO_printf(bio_err, "%s Verification successful\n",
|
||||
(flags & CMS_CADES) ? "CAdES" : "CMS");
|
||||
} else {
|
||||
BIO_printf(bio_err, "Verification failure\n");
|
||||
if (verify_retcode)
|
||||
|
@ -52,6 +52,10 @@ 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),
|
||||
"invalid encrypted key length"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
DEFINE_STACK_OF(GENERAL_NAMES)
|
||||
DEFINE_STACK_OF(CMS_SignerInfo)
|
||||
DEFINE_STACK_OF(ESS_CERT_ID)
|
||||
DEFINE_STACK_OF(ESS_CERT_ID_V2)
|
||||
DEFINE_STACK_OF(X509)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
|
||||
|
||||
@ -29,33 +32,100 @@ IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
|
||||
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
|
||||
{
|
||||
ASN1_STRING *str;
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
if (prr)
|
||||
CMS_ReceiptRequest *rr;
|
||||
ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_receiptRequest);
|
||||
|
||||
if (prr != NULL)
|
||||
*prr = NULL;
|
||||
str = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj
|
||||
(NID_id_smime_aa_receiptRequest), -3,
|
||||
V_ASN1_SEQUENCE);
|
||||
if (!str)
|
||||
str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
|
||||
if (!rr)
|
||||
if (rr == NULL)
|
||||
return -1;
|
||||
if (prr)
|
||||
if (prr != NULL)
|
||||
*prr = rr;
|
||||
else
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
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 ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain)
|
||||
{
|
||||
ESS_SIGNING_CERT *ss = NULL;
|
||||
ESS_SIGNING_CERT_V2 *ssv2 = NULL;
|
||||
X509 *cert;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
if (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 (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 (ess_find_cert(cert_ids, cert) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else if (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 (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 (ess_find_cert_v2(cert_ids_v2, cert) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS,
|
||||
CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE);
|
||||
return 0;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
if (!ret)
|
||||
CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS,
|
||||
CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR);
|
||||
|
||||
ESS_SIGNING_CERT_free(ss);
|
||||
ESS_SIGNING_CERT_V2_free(ssv2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
|
||||
int allorfirst,
|
||||
STACK_OF(GENERAL_NAMES)
|
||||
*receiptList, STACK_OF(GENERAL_NAMES)
|
||||
*receiptsTo)
|
||||
{
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
CMS_ReceiptRequest *rr;
|
||||
|
||||
rr = CMS_ReceiptRequest_new();
|
||||
if (rr == NULL)
|
||||
@ -145,6 +215,7 @@ static int cms_msgSigDigest(CMS_SignerInfo *si,
|
||||
unsigned char *dig, unsigned int *diglen)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
|
||||
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
@ -160,6 +231,7 @@ int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
|
||||
{
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int diglen;
|
||||
|
||||
if (!cms_msgSigDigest(src, dig, &diglen)) {
|
||||
CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
|
||||
return 0;
|
||||
|
@ -421,6 +421,9 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *
|
||||
/* SignerInfo routines */
|
||||
int CMS_si_check_attributes(const CMS_SignerInfo *si);
|
||||
|
||||
/* ESS routines */
|
||||
int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain);
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_CertificateChoices)
|
||||
DECLARE_ASN1_ITEM(CMS_DigestedData)
|
||||
DECLARE_ASN1_ITEM(CMS_EncryptedData)
|
||||
|
@ -233,7 +233,8 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|
||||
static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
|
||||
X509_STORE *store,
|
||||
STACK_OF(X509) *certs,
|
||||
STACK_OF(X509_CRL) *crls)
|
||||
STACK_OF(X509_CRL) *crls,
|
||||
STACK_OF(X509) **chain)
|
||||
{
|
||||
X509_STORE_CTX *ctx = X509_STORE_CTX_new();
|
||||
X509 *signer;
|
||||
@ -262,6 +263,10 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
|
||||
goto err;
|
||||
}
|
||||
r = 1;
|
||||
|
||||
/* also send back the trust chain when required */
|
||||
if (chain != NULL)
|
||||
*chain = X509_STORE_CTX_get1_chain(ctx);
|
||||
err:
|
||||
X509_STORE_CTX_free(ctx);
|
||||
return r;
|
||||
@ -275,9 +280,11 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
STACK_OF(X509) *cms_certs = NULL;
|
||||
STACK_OF(X509_CRL) *crls = NULL;
|
||||
STACK_OF(X509) **si_chains = NULL;
|
||||
X509 *signer;
|
||||
int i, scount = 0, ret = 0;
|
||||
BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
|
||||
int cadesVerify = (flags & CMS_CADES) != 0;
|
||||
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
@ -312,27 +319,44 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
}
|
||||
|
||||
/* Attempt to verify all signers certs */
|
||||
/* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
|
||||
|
||||
if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
|
||||
if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
|
||||
if (cadesVerify) {
|
||||
/* Certificate trust chain is required to check CAdES signature */
|
||||
si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
|
||||
if (si_chains == NULL) {
|
||||
CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
cms_certs = CMS_get1_certs(cms);
|
||||
if (!(flags & CMS_NOCRL))
|
||||
crls = CMS_get1_crls(cms);
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
for (i = 0; i < scount; i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
|
||||
|
||||
if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
|
||||
si_chains ? &si_chains[i] : NULL))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to verify all SignerInfo signed attribute signatures */
|
||||
|
||||
if (!(flags & CMS_NO_ATTR_VERIFY)) {
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
|
||||
for (i = 0; i < scount; i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (CMS_signed_get_attr_count(si) < 0)
|
||||
continue;
|
||||
if (CMS_SignerInfo_verify(si) <= 0)
|
||||
goto err;
|
||||
if (cadesVerify) {
|
||||
STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
|
||||
|
||||
if (ess_check_signing_certs(si, si_chain) <= 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,6 +444,11 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
BIO_free_all(tmpout);
|
||||
|
||||
err2:
|
||||
if (si_chains != NULL) {
|
||||
for (i = 0; i < scount; ++i)
|
||||
sk_X509_pop_free(si_chains[i], X509_free);
|
||||
OPENSSL_free(si_chains);
|
||||
}
|
||||
sk_X509_pop_free(cms_certs, X509_free);
|
||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||
|
||||
|
@ -320,6 +320,7 @@ CMS_F_CMS_SET_DETACHED:147:CMS_set_detached
|
||||
CMS_F_CMS_SIGN:148:CMS_sign
|
||||
CMS_F_CMS_SIGNED_DATA_INIT:149:cms_signed_data_init
|
||||
CMS_F_CMS_SIGNERINFO_CONTENT_SIGN:150:cms_SignerInfo_content_sign
|
||||
CMS_F_CMS_SIGNERINFO_GET_CHAIN:184:cms_signerinfo_get_chain
|
||||
CMS_F_CMS_SIGNERINFO_SIGN:151:CMS_SignerInfo_sign
|
||||
CMS_F_CMS_SIGNERINFO_VERIFY:152:CMS_SignerInfo_verify
|
||||
CMS_F_CMS_SIGNERINFO_VERIFY_CERT:153:cms_signerinfo_verify_cert
|
||||
@ -329,6 +330,7 @@ CMS_F_CMS_SI_CHECK_ATTRIBUTES:183:CMS_si_check_attributes
|
||||
CMS_F_CMS_STREAM:155:CMS_stream
|
||||
CMS_F_CMS_UNCOMPRESS:156:CMS_uncompress
|
||||
CMS_F_CMS_VERIFY:157:CMS_verify
|
||||
CMS_F_ESS_CHECK_SIGNING_CERTS:185:ess_check_signing_certs
|
||||
CMS_F_KEK_UNWRAP_KEY:180:kek_unwrap_key
|
||||
COMP_F_BIO_ZLIB_FLUSH:99:bio_zlib_flush
|
||||
COMP_F_BIO_ZLIB_NEW:100:bio_zlib_new
|
||||
@ -2188,6 +2190,8 @@ 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
|
||||
CMS_R_INVALID_KEY_LENGTH:118:invalid key length
|
||||
|
@ -1,3 +1,8 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]= \
|
||||
ess_lib.c ess_asn1.c ess_err.c
|
||||
|
||||
IF[{- !$disabled{'cms'} and !$disabled{'ts'} -}]
|
||||
SOURCE[../../libcrypto]= ess_lib.c
|
||||
ENDIF
|
||||
|
||||
SOURCE[../../libcrypto]= ess_asn1.c ess_err.c
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2019-2020 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
|
||||
@ -9,9 +9,11 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/ess.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "crypto/ess.h"
|
||||
#include "crypto/cms.h"
|
||||
|
||||
/* ASN1 stuff for ESS Structure */
|
||||
|
||||
@ -55,3 +57,61 @@ ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = {
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ESS_SIGNING_CERT_V2)
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
|
||||
|
||||
/* No cms support means no CMS_SignerInfo* definitions */
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
/*
|
||||
* Returns < 0 if attribute is not found, 1 if found, or
|
||||
* -1 on attribute parsing failure.
|
||||
*/
|
||||
int cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si,
|
||||
ESS_SIGNING_CERT_V2 **psc)
|
||||
{
|
||||
ASN1_STRING *str;
|
||||
ESS_SIGNING_CERT_V2 *sc;
|
||||
ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificateV2);
|
||||
|
||||
if (psc != NULL)
|
||||
*psc = NULL;
|
||||
str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT_V2));
|
||||
if (sc == NULL)
|
||||
return -1;
|
||||
if (psc != NULL)
|
||||
*psc = sc;
|
||||
else
|
||||
ESS_SIGNING_CERT_V2_free(sc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns < 0 if attribute is not found, 1 if found, or
|
||||
* -1 on attribute parsing failure.
|
||||
*/
|
||||
int cms_signerinfo_get_signing_cert(CMS_SignerInfo *si,
|
||||
ESS_SIGNING_CERT **psc)
|
||||
{
|
||||
ASN1_STRING *str;
|
||||
ESS_SIGNING_CERT *sc;
|
||||
ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificate);
|
||||
|
||||
if (psc != NULL)
|
||||
*psc = NULL;
|
||||
str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT));
|
||||
if (sc == NULL)
|
||||
return -1;
|
||||
if (psc != NULL)
|
||||
*psc = sc;
|
||||
else
|
||||
ESS_SIGNING_CERT_free(sc);
|
||||
return 1;
|
||||
}
|
||||
#endif /* !OPENSSL_NO_CMS */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 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,8 +15,8 @@
|
||||
|
||||
DEFINE_STACK_OF(ESS_CERT_ID)
|
||||
DEFINE_STACK_OF(ESS_CERT_ID_V2)
|
||||
DEFINE_STACK_OF(X509)
|
||||
DEFINE_STACK_OF(GENERAL_NAME)
|
||||
DEFINE_STACK_OF(X509)
|
||||
|
||||
static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
|
||||
static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
|
||||
@ -61,9 +61,12 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
|
||||
unsigned char cert_sha1[SHA_DIGEST_LENGTH];
|
||||
|
||||
/* Call for side-effect of computing hash and caching extensions */
|
||||
X509_check_purpose(cert, -1, 0);
|
||||
if (!X509v3_cache_extensions(cert, NULL, NULL))
|
||||
return NULL;
|
||||
|
||||
if ((cid = ESS_CERT_ID_new()) == NULL)
|
||||
goto err;
|
||||
/* TODO(3.0): fetch sha1 algorithm from providers */
|
||||
if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
|
||||
goto err;
|
||||
if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH))
|
||||
@ -85,8 +88,8 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
|
||||
goto err;
|
||||
name = NULL; /* Ownership is lost. */
|
||||
ASN1_INTEGER_free(cid->issuer_serial->serial);
|
||||
if (!(cid->issuer_serial->serial =
|
||||
ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
|
||||
if ((cid->issuer_serial->serial =
|
||||
ASN1_INTEGER_dup(X509_get_serialNumber(cert))) == NULL)
|
||||
goto err;
|
||||
|
||||
return cid;
|
||||
@ -159,6 +162,7 @@ static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
|
||||
cid->hash_alg = NULL;
|
||||
}
|
||||
|
||||
/* TODO(3.0): fetch sha1 algorithm from providers */
|
||||
if (!X509_digest(cert, hash_alg, hash, &hash_len))
|
||||
goto err;
|
||||
|
||||
@ -196,8 +200,9 @@ ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(PKCS7_SIGNER_INFO *si)
|
||||
{
|
||||
ASN1_TYPE *attr;
|
||||
const unsigned char *p;
|
||||
|
||||
attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
|
||||
if (!attr)
|
||||
if (attr == NULL)
|
||||
return NULL;
|
||||
p = attr->value.sequence->data;
|
||||
return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
|
||||
@ -273,3 +278,86 @@ int ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si,
|
||||
OPENSSL_free(pp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert)
|
||||
{
|
||||
GENERAL_NAME *issuer;
|
||||
|
||||
if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1)
|
||||
return -1;
|
||||
|
||||
issuer = sk_GENERAL_NAME_value(is->issuer, 0);
|
||||
if (issuer->type != GEN_DIRNAME
|
||||
|| X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0)
|
||||
return -1;
|
||||
|
||||
return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert));
|
||||
}
|
||||
|
||||
/* Returns < 0 if certificate is not found, certificate index otherwise. */
|
||||
int 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, NULL, NULL))
|
||||
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 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 && 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;
|
||||
}
|
||||
|
@ -26,8 +26,7 @@ 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_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
|
||||
static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert);
|
||||
|
||||
static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx,
|
||||
PKCS7 *token, TS_TST_INFO *tst_info);
|
||||
static int ts_check_status_info(TS_RESP *response);
|
||||
@ -44,7 +43,6 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info);
|
||||
static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer);
|
||||
static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names,
|
||||
GENERAL_NAME *name);
|
||||
static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert);
|
||||
|
||||
/*
|
||||
* This must be large enough to hold all values in ts_status_text (with
|
||||
@ -218,7 +216,7 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
|
||||
if (ss != NULL) {
|
||||
cert_ids = ss->cert_ids;
|
||||
cert = sk_X509_value(chain, 0);
|
||||
if (ts_find_cert(cert_ids, cert) != 0)
|
||||
if (ess_find_cert(cert_ids, cert) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@ -228,14 +226,14 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
|
||||
if (sk_ESS_CERT_ID_num(cert_ids) > 1) {
|
||||
for (i = 1; i < sk_X509_num(chain); ++i) {
|
||||
cert = sk_X509_value(chain, i);
|
||||
if (ts_find_cert(cert_ids, cert) < 0)
|
||||
if (ess_find_cert(cert_ids, cert) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else if (ssv2 != NULL) {
|
||||
cert_ids_v2 = ssv2->cert_ids;
|
||||
cert = sk_X509_value(chain, 0);
|
||||
if (ts_find_cert_v2(cert_ids_v2, cert) != 0)
|
||||
if (ess_find_cert_v2(cert_ids_v2, cert) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@ -245,7 +243,7 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
|
||||
if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) {
|
||||
for (i = 1; i < sk_X509_num(chain); ++i) {
|
||||
cert = sk_X509_value(chain, i);
|
||||
if (ts_find_cert_v2(cert_ids_v2, cert) < 0)
|
||||
if (ess_find_cert_v2(cert_ids_v2, cert) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@ -263,87 +261,6 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns < 0 if certificate is not found, certificate index otherwise. */
|
||||
static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
|
||||
{
|
||||
int i;
|
||||
unsigned char cert_sha1[SHA_DIGEST_LENGTH];
|
||||
|
||||
if (!cert_ids || !cert)
|
||||
return -1;
|
||||
|
||||
/* Recompute SHA1 hash of certificate if necessary (side effect). */
|
||||
X509_check_purpose(cert, -1, 0);
|
||||
|
||||
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) {
|
||||
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) {
|
||||
ESS_ISSUER_SERIAL *is = cid->issuer_serial;
|
||||
if (!is || !ts_issuer_serial_cmp(is, cert))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns < 0 if certificate is not found, certificate index otherwise. */
|
||||
static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, 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) {
|
||||
ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i);
|
||||
const EVP_MD *md;
|
||||
|
||||
if (cid->hash_alg != NULL)
|
||||
md = EVP_get_digestbyobj(cid->hash_alg->algorithm);
|
||||
else
|
||||
md = EVP_sha256();
|
||||
|
||||
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) {
|
||||
ESS_ISSUER_SERIAL *is = cid->issuer_serial;
|
||||
|
||||
if (is == NULL || !ts_issuer_serial_cmp(is, cert))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert)
|
||||
{
|
||||
GENERAL_NAME *issuer;
|
||||
|
||||
if (!is || !cert || sk_GENERAL_NAME_num(is->issuer) != 1)
|
||||
return -1;
|
||||
|
||||
issuer = sk_GENERAL_NAME_value(is->issuer, 0);
|
||||
if (issuer->type != GEN_DIRNAME
|
||||
|| X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)))
|
||||
return -1;
|
||||
|
||||
if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Verifies whether 'response' contains a valid response with regards
|
||||
* to the settings of the context:
|
||||
|
@ -569,7 +569,8 @@ 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 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.
|
||||
|
||||
@ -577,9 +578,10 @@ An ESS signing-certificate-v2 attribute allows for the use of any digest algorit
|
||||
|
||||
The digital signature value computed on the user data and, when present, on the signed attributes.
|
||||
|
||||
Note that currently the B<-cades> option applies only to the B<-sign> operation and is ignored during
|
||||
the B<-verify> operation, i.e. the signing certification is not checked during the verification process.
|
||||
This feature might be added in a future version.
|
||||
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.
|
||||
|
||||
=back
|
||||
|
||||
|
@ -66,10 +66,14 @@ from the content. If the content is not of type B<text/plain> then an error is
|
||||
returned.
|
||||
|
||||
If B<CMS_NO_SIGNER_CERT_VERIFY> is set the signing certificates are not
|
||||
verified.
|
||||
verified, unless CMS_CADES flag is also set.
|
||||
|
||||
If B<CMS_NO_ATTR_VERIFY> is set the signed attributes signature is not
|
||||
verified.
|
||||
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.
|
||||
|
||||
If B<CMS_NO_CONTENT_VERIFY> is set then the content digest is not checked.
|
||||
|
||||
@ -122,7 +126,7 @@ L<ERR_get_error(3)>, L<CMS_sign(3)>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Copyright 2008-2020 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2019-2020 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
|
||||
@ -7,7 +7,15 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
/* internal CMS-ESS related stuff */
|
||||
|
||||
int cms_add1_signing_cert(CMS_SignerInfo *si, ESS_SIGNING_CERT *sc);
|
||||
int cms_add1_signing_cert_v2(CMS_SignerInfo *si, ESS_SIGNING_CERT_V2 *sc);
|
||||
|
||||
int cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si,
|
||||
ESS_SIGNING_CERT_V2 **psc);
|
||||
int cms_signerinfo_get_signing_cert(CMS_SignerInfo *si,
|
||||
ESS_SIGNING_CERT **psc);
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2019-2020 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
|
||||
@ -24,6 +24,10 @@ ESS_SIGNING_CERT_V2 *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 ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids, const X509 *cert);
|
||||
int ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
|
||||
|
||||
/*-
|
||||
* IssuerSerial ::= SEQUENCE {
|
||||
* issuer GeneralNames,
|
||||
|
@ -109,6 +109,7 @@ int ERR_load_CMS_strings(void);
|
||||
# define CMS_F_CMS_SIGN 0
|
||||
# define CMS_F_CMS_SIGNED_DATA_INIT 0
|
||||
# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 0
|
||||
# define CMS_F_CMS_SIGNERINFO_GET_CHAIN 0
|
||||
# define CMS_F_CMS_SIGNERINFO_SIGN 0
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY 0
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 0
|
||||
@ -118,6 +119,7 @@ int ERR_load_CMS_strings(void);
|
||||
# define CMS_F_CMS_STREAM 0
|
||||
# define CMS_F_CMS_UNCOMPRESS 0
|
||||
# define CMS_F_CMS_VERIFY 0
|
||||
# define CMS_F_ESS_CHECK_SIGNING_CERTS 0
|
||||
# define CMS_F_KEK_UNWRAP_KEY 0
|
||||
# endif
|
||||
|
||||
@ -147,6 +149,8 @@ int ERR_load_CMS_strings(void);
|
||||
# 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
|
||||
# define CMS_R_INVALID_KEY_LENGTH 118
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2020 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
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#ifndef OPENSSL_ESSERR_H
|
||||
# define OPENSSL_ESSERR_H
|
||||
# pragma once
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
@ -30,7 +30,7 @@ my $smcont = srctop_file("test", "smcont.txt");
|
||||
my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
|
||||
= disabled qw/des dh dsa ec ec2m rc2 zlib/;
|
||||
|
||||
plan tests => 7;
|
||||
plan tests => 10;
|
||||
|
||||
my @smime_pkcs7_tests = (
|
||||
|
||||
@ -251,26 +251,6 @@ my @smime_cms_tests = (
|
||||
"-CAfile", catfile($smdir, "smroot.pem") ]
|
||||
],
|
||||
|
||||
[ "signed content DER format, RSA key, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-in", $smcont, "-outform", "DER",
|
||||
"-nodetach",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-md", "sha256", "-in", $smcont,
|
||||
"-outform", "DER", "-nodetach",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
|
||||
[ "{cmd1}", "-encrypt", "-in", $smcont,
|
||||
"-stream", "-out", "{output}.cms", "-keyid",
|
||||
@ -360,6 +340,87 @@ my @smime_cms_tests = (
|
||||
|
||||
);
|
||||
|
||||
my @smime_cms_cades_tests = (
|
||||
|
||||
[ "signed content DER format, RSA key, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-in", $smcont, "-outform", "DER",
|
||||
"-nodetach",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
|
||||
"DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
|
||||
"DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
|
||||
"-in", $smcont, "-outform", "DER",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"),
|
||||
"-outform", "DER", "-out", "{output}.cms" ],
|
||||
[ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
|
||||
[ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
|
||||
[ "{cmd1}", "-sign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
|
||||
"-in", $smcont, "-outform", "DER",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"),
|
||||
"-outform", "DER", "-out", "{output}.cms" ],
|
||||
[ "{cmd1}", "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
|
||||
"-inform", "DER", "-in", "{output}.cms",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa2.pem"),
|
||||
"-outform", "DER", "-out", "{output}2.cms" ],
|
||||
|
||||
[ "{cmd2}", "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
],
|
||||
);
|
||||
|
||||
my @smime_cms_cades_ko_tests = (
|
||||
[ "signed content DER format, RSA key, but verified as CAdES-BES compatible",
|
||||
[ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
|
||||
[ "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
]
|
||||
);
|
||||
|
||||
# cades options test - check that some combinations are rejected
|
||||
my @smime_cms_cades_invalid_option_tests = (
|
||||
[
|
||||
[ "-cades", "-noattr" ],
|
||||
],[
|
||||
[ "-verify", "-cades", "-noattr" ],
|
||||
],[
|
||||
[ "-verify", "-cades", "-noverify" ],
|
||||
],
|
||||
);
|
||||
|
||||
my @smime_cms_comp_tests = (
|
||||
|
||||
[ "compressed content test streaming PEM format",
|
||||
@ -491,7 +552,7 @@ my @smime_cms_param_tests = (
|
||||
"-in", "{output}.cms", "-out", "{output}.txt" ],
|
||||
\&final_compare
|
||||
]
|
||||
);
|
||||
);
|
||||
|
||||
my @contenttype_cms_test = (
|
||||
[ "signed content test - check that content type is added to additional signerinfo, RSA keys",
|
||||
@ -542,7 +603,7 @@ sub runner_loop {
|
||||
$x;
|
||||
} @$_;
|
||||
|
||||
diag "CMD: openssl", join(" ", @cmd);
|
||||
diag "CMD: openssl ", join(" ", @cmd);
|
||||
$ok &&= run(app(["openssl", @cmd]));
|
||||
$opts{input} = $opts{output};
|
||||
}
|
||||
@ -654,6 +715,36 @@ subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
|
||||
}
|
||||
};
|
||||
|
||||
subtest "CAdES <=> CAdES consistency tests\n" => sub {
|
||||
plan tests => (scalar @smime_cms_cades_tests);
|
||||
|
||||
runner_loop(prefix => 'cms-cades', cmd1 => 'cms', cmd2 => 'cms',
|
||||
tests => [ @smime_cms_cades_tests ]);
|
||||
};
|
||||
|
||||
subtest "CAdES; cms incompatible arguments tests\n" => sub {
|
||||
plan tests => (scalar @smime_cms_cades_invalid_option_tests);
|
||||
|
||||
foreach (@smime_cms_cades_invalid_option_tests) {
|
||||
ok(!run(app(["openssl", "cms", @{$$_[0]} ] )));
|
||||
}
|
||||
};
|
||||
|
||||
subtest "CAdES ko tests\n" => sub {
|
||||
plan tests => (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]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sub check_availability {
|
||||
my $tnam = shift;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user