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;
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;
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;
}
/* Attempt to verify all signers certs */
-
- if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
+ /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
+
+ 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;
+ }
}
}
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);