mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 12:39:28 +00:00
166 lines
5.2 KiB
C
166 lines
5.2 KiB
C
/* Provenance: openssl/openssl PKCS7_verify (fixed).
|
|||
|
|
* repo: openssl/openssl
|
||
|
|
* commit: f4129fbe3cde786d363510069fe297234f99be8f
|
||
|
|
* parent: 609bcb24866d64f1fc49d38b852edbb39057d721
|
||
|
|
* commit_url: https://github.com/openssl/openssl/commit/f4129fbe3cde786d363510069fe297234f99be8f
|
||
|
|
* cve: CVE-2026-45447
|
||
|
|
* license: Apache-2.0
|
||
|
|
* function: PKCS7_verify
|
||
|
|
* relpath: crypto/pkcs7/pk7_smime.c
|
||
|
|
*/
|
||
|
|
|
||
|
|
int PKCS7_verify(PKCS7 *p7, const STACK_OF(X509) *certs, X509_STORE *store,
|
||
|
|
BIO *indata, BIO *out, int flags)
|
||
|
|
{
|
||
|
|
STACK_OF(X509) *signers;
|
||
|
|
STACK_OF(X509) *included_certs;
|
||
|
|
STACK_OF(X509) *untrusted = NULL;
|
||
|
|
X509 *signer;
|
||
|
|
STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
|
||
|
|
PKCS7_SIGNER_INFO *si;
|
||
|
|
X509_STORE_CTX *cert_ctx = NULL;
|
||
|
|
char *buf = NULL;
|
||
|
|
int i, j = 0, k, ret = 0;
|
||
|
|
BIO *p7bio = NULL;
|
||
|
|
BIO *tmpout = NULL;
|
||
|
|
BIO *next = NULL;
|
||
|
|
const PKCS7_CTX *p7_ctx;
|
||
|
|
|
||
|
|
if (p7 == NULL) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!PKCS7_type_is_signed(p7)) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Check for no data and no content: no data to verify signature */
|
||
|
|
if (PKCS7_get_detached(p7) && indata == NULL) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (flags & PKCS7_NO_DUAL_CONTENT) {
|
||
|
|
/*
|
||
|
|
* This was originally "#if 0" because we thought that only old broken
|
||
|
|
* Netscape did this. It turns out that Authenticode uses this kind
|
||
|
|
* of "extended" PKCS7 format, and things like UEFI secure boot and
|
||
|
|
* tools like osslsigncode need it. In Authenticode the verification
|
||
|
|
* process is different, but the existing PKCs7 verification works.
|
||
|
|
*/
|
||
|
|
if (!PKCS7_get_detached(p7) && indata != NULL) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
sinfos = PKCS7_get_signer_info(p7);
|
||
|
|
|
||
|
|
if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
signers = PKCS7_get0_signers(p7, certs, flags);
|
||
|
|
if (signers == NULL)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
/* Now verify the certificates */
|
||
|
|
p7_ctx = ossl_pkcs7_get0_ctx(p7);
|
||
|
|
cert_ctx = X509_STORE_CTX_new_ex(ossl_pkcs7_ctx_get0_libctx(p7_ctx),
|
||
|
|
ossl_pkcs7_ctx_get0_propq(p7_ctx));
|
||
|
|
if (cert_ctx == NULL)
|
||
|
|
goto err;
|
||
|
|
if ((flags & PKCS7_NOVERIFY) == 0) {
|
||
|
|
if (!ossl_x509_add_certs_new(&untrusted, certs, X509_ADD_FLAG_NO_DUP))
|
||
|
|
goto err;
|
||
|
|
included_certs = pkcs7_get0_certificates(p7);
|
||
|
|
if ((flags & PKCS7_NOCHAIN) == 0
|
||
|
|
&& !ossl_x509_add_certs_new(&untrusted, included_certs,
|
||
|
|
X509_ADD_FLAG_NO_DUP))
|
||
|
|
goto err;
|
||
|
|
|
||
|
|
for (k = 0; k < sk_X509_num(signers); k++) {
|
||
|
|
signer = sk_X509_value(signers, k);
|
||
|
|
if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
if ((flags & PKCS7_NOCHAIN) == 0
|
||
|
|
&& !X509_STORE_CTX_set_default(cert_ctx, "smime_sign"))
|
||
|
|
goto err;
|
||
|
|
if (!(flags & PKCS7_NOCRL))
|
||
|
|
X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl);
|
||
|
|
i = X509_verify_cert(cert_ctx);
|
||
|
|
if (i <= 0) {
|
||
|
|
j = X509_STORE_CTX_get_error(cert_ctx);
|
||
|
|
ERR_raise_data(ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR,
|
||
|
|
"Verify error: %s",
|
||
|
|
X509_verify_cert_error_string(j));
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
/* Check for revocation status here */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((p7bio = PKCS7_dataInit(p7, indata)) == NULL)
|
||
|
|
goto err;
|
||
|
|
|
||
|
|
if (flags & PKCS7_TEXT) {
|
||
|
|
if ((tmpout = BIO_new(BIO_s_mem())) == NULL) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
BIO_set_mem_eof_return(tmpout, 0);
|
||
|
|
} else
|
||
|
|
tmpout = out;
|
||
|
|
|
||
|
|
/* We now have to 'read' from p7bio to calculate digests etc. */
|
||
|
|
if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL)
|
||
|
|
goto err;
|
||
|
|
for (;;) {
|
||
|
|
i = BIO_read(p7bio, buf, BUFFERSIZE);
|
||
|
|
if (i <= 0)
|
||
|
|
break;
|
||
|
|
if (tmpout)
|
||
|
|
BIO_write(tmpout, buf, i);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (flags & PKCS7_TEXT) {
|
||
|
|
if (!SMIME_text(tmpout, out)) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Now Verify All Signatures */
|
||
|
|
if (!(flags & PKCS7_NOSIGS))
|
||
|
|
for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
|
||
|
|
si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
|
||
|
|
signer = sk_X509_value(signers, i);
|
||
|
|
j = PKCS7_signatureVerify(p7bio, p7, si, signer);
|
||
|
|
if (j <= 0) {
|
||
|
|
ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = 1;
|
||
|
|
|
||
|
|
err:
|
||
|
|
if (flags & PKCS7_TEXT)
|
||
|
|
BIO_free(tmpout);
|
||
|
|
X509_STORE_CTX_free(cert_ctx);
|
||
|
|
OPENSSL_free(buf);
|
||
|
|
while (p7bio != NULL && p7bio != indata) {
|
||
|
|
next = BIO_pop(p7bio);
|
||
|
|
BIO_free(p7bio);
|
||
|
|
p7bio = next;
|
||
|
|
}
|
||
|
|
sk_X509_free(signers);
|
||
|
|
sk_X509_free(untrusted);
|
||
|
|
return ret;
|
||
|
|
}
|