pkcs7-verify.cpp revision 8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5
b711a01730152421a900e5f4e237cfb848c9c4fdvboxsync/* $Id$ */
b711a01730152421a900e5f4e237cfb848c9c4fdvboxsync/** @file
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * IPRT - Crypto - PKCS \#7, Verification
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync */
2f14f4556ae74ad40719bc9690534693abb71868vboxsync
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync/*
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync * Copyright (C) 2006-2014 Oracle Corporation
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync *
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * available from http://www.virtualbox.org. This file is free software;
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * you can redistribute it and/or modify it under the terms of the GNU
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * General Public License (GPL) as published by the Free Software
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * The contents of this file may alternatively be used under the terms
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * of the Common Development and Distribution License Version 1.0
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * CDDL are applicable instead of those of the GPL.
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync *
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * You may elect to license modified versions of this file under the
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * terms and conditions of either the GPL or the CDDL or both.
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync */
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync/*******************************************************************************
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync* Header Files *
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync*******************************************************************************/
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include "internal/iprt.h"
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/crypto/pkcs7.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/err.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/string.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/crypto/digest.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/crypto/pkix.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/crypto/store.h>
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync#include <iprt/crypto/x509.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync#ifdef IPRT_WITH_OPENSSL
78a072e1b56619e3230735ae073668311232ec94vboxsync# include "internal/iprt-openssl.h"
78a072e1b56619e3230735ae073668311232ec94vboxsync# include <openssl/pkcs7.h>
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync# include <openssl/x509.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync# include <openssl/err.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#endif
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
94c538a65fbdfa1ea06f4fe0a65599c1ab0fed58vboxsync
94c538a65fbdfa1ea06f4fe0a65599c1ab0fed58vboxsync#ifdef IPRT_WITH_OPENSSL
d0318084c32279bf313f47358242cd61ada858d6vboxsyncstatic int rtCrPkcs7VerifySignedDataUsingOpenSsl(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
94c538a65fbdfa1ea06f4fe0a65599c1ab0fed58vboxsync RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
d5d45608052fd506e4114bf112df6efae7fcd8a7vboxsync void const *pvContent, uint32_t cbContent, PRTERRINFO pErrInfo)
d5d45608052fd506e4114bf112df6efae7fcd8a7vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Verify using OpenSSL.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync int rcOssl;
78a072e1b56619e3230735ae073668311232ec94vboxsync unsigned char const *pbRawContent = RTASN1CORE_GET_RAW_ASN1_PTR(&pContentInfo->SeqCore.Asn1Core);
78a072e1b56619e3230735ae073668311232ec94vboxsync PKCS7 *pOsslPkcs7 = NULL;
78a072e1b56619e3230735ae073668311232ec94vboxsync if (d2i_PKCS7(&pOsslPkcs7, &pbRawContent, RTASN1CORE_GET_RAW_ASN1_SIZE(&pContentInfo->SeqCore.Asn1Core)) == pOsslPkcs7)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync STACK_OF(X509) *pAddCerts = NULL;
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hAdditionalCerts != NIL_RTCRSTORE)
78a072e1b56619e3230735ae073668311232ec94vboxsync rcOssl = RTCrStoreConvertToOpenSslCertStack(hAdditionalCerts, 0, (void **)&pAddCerts);
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync pAddCerts = sk_X509_new_null();
78a072e1b56619e3230735ae073668311232ec94vboxsync rcOssl = RT_LIKELY(pAddCerts != NULL) ? VINF_SUCCESS : VERR_NO_MEMORY;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rcOssl))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync for (uint32_t i = 0; i < pContentInfo->u.pSignedData->Certificates.cItems; i++)
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync rtCrOpenSslAddX509CertToStack(pAddCerts, &pContentInfo->u.pSignedData->Certificates.paItems[i]);
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync X509_STORE *pTrustedCerts = NULL;
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync if (hTrustedCerts != NIL_RTCRSTORE)
2d86fd6bcfe35a4bb83bb8a4fe68090693cdce95vboxsync rcOssl = RTCrStoreConvertToOpenSslCertStore(hTrustedCerts, 0, (void **)&pTrustedCerts);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rcOssl))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync rtCrOpenSslInit();
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync BIO *pBioContent = BIO_new_mem_buf((void *)pvContent, cbContent);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (pBioContent)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t fOsslFlags = PKCS7_NOCHAIN;
78a072e1b56619e3230735ae073668311232ec94vboxsync fOsslFlags |= PKCS7_NOVERIFY; // temporary hack.
78a072e1b56619e3230735ae073668311232ec94vboxsync if (PKCS7_verify(pOsslPkcs7, pAddCerts, pTrustedCerts, pBioContent, NULL /*out*/, fOsslFlags))
78a072e1b56619e3230735ae073668311232ec94vboxsync rcOssl = VINF_SUCCESS;
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_VERIFY_FAILED, "PKCS7_verify failed: ");
78a072e1b56619e3230735ae073668311232ec94vboxsync if (pErrInfo)
78a072e1b56619e3230735ae073668311232ec94vboxsync ERR_print_errors_cb(rtCrOpenSslErrInfoCallback, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync BIO_free(pBioContent);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync if (pTrustedCerts)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync X509_STORE_free(pTrustedCerts);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync }
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync else
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed");
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync if (pAddCerts)
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync sk_X509_pop_free(pAddCerts, X509_free);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync }
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync else
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed");
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync PKCS7_free(pOsslPkcs7);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync }
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync else
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_D2I_FAILED, "d2i_PKCS7 failed");
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return rcOssl;
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync}
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync#endif /* IPRT_WITH_OPENSSL */
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsyncstatic int rtCrPkcs7VerifyCertUsageTimstamping(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync{
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync if (!(pCert->TbsCertificate.T3.fExtKeyUsage & (RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING)))
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x (time stamping)",
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync pCert->TbsCertificate.T3.fExtKeyUsage,
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return VINF_SUCCESS;
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync}
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsyncstatic int rtCrPkcs7VerifyCertUsageDigitalSignature(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync{
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync if ( (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync && !(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fKeyUsage=%#x, missing %#x",
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync pCert->TbsCertificate.T3.fKeyUsage, RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return VINF_SUCCESS;
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync}
223a6730e81629b0bf552ccc31f119a998cc8e27vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync/**
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * Default implementation that checks for the DigitalSignature KeyUsage bit.}
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync */
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsyncRTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync void *pvUser, PRTERRINFO pErrInfo)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync{
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync int rc = VINF_SUCCESS;
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync if ( (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync && RT_SUCCESS(rc))
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync return rc;
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync}
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync/**
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * Standard code signing. Use this for Microsoft SPC.}
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync */
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsyncRTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync void *pvUser, PRTERRINFO pErrInfo)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync{
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync int rc = VINF_SUCCESS;
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync {
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync /*
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * If KeyUsage is present it must include digital signature.
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync */
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync if (RT_SUCCESS(rc))
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync {
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync /*
6804e4c1c12ab612ad6257a4922309c476c204e5vboxsync * The extended usage 'code signing' must be present.
223a6730e81629b0bf552ccc31f119a998cc8e27vboxsync */
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
78a072e1b56619e3230735ae073668311232ec94vboxsync pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Timestamping too?
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if ( (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
78a072e1b56619e3230735ae073668311232ec94vboxsync && RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync return rc;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Deals with authenticated attributes.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * When authenticated attributes are present (checked by caller) we must:
78a072e1b56619e3230735ae073668311232ec94vboxsync * - fish out the content type and check it against the content inof,
78a072e1b56619e3230735ae073668311232ec94vboxsync * - fish out the message digest among and check it against *phDigest,
78a072e1b56619e3230735ae073668311232ec94vboxsync * - compute the message digest of the authenticated attributes and
78a072e1b56619e3230735ae073668311232ec94vboxsync * replace *phDigest with this for the signature verification.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns IPRT status code.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignerInfo The signer info being verified.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignedData The signed data.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param phDigest On input this is the digest of the content. On
78a072e1b56619e3230735ae073668311232ec94vboxsync * output it will (on success) be a reference to
78a072e1b56619e3230735ae073668311232ec94vboxsync * the message digest of the authenticated
78a072e1b56619e3230735ae073668311232ec94vboxsync * attributes. The input reference is consumed.
78a072e1b56619e3230735ae073668311232ec94vboxsync * The caller shall release the output reference.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param fFlags Flags.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pErrInfo Extended error info, optional.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncstatic int rtCrPkcs7VerifySignerInfoAuthAttribs(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
78a072e1b56619e3230735ae073668311232ec94vboxsync PRTCRDIGEST phDigest, uint32_t fFlags, PRTERRINFO pErrInfo)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
1637773d6c473e4ab75812805ef00226f3a397c0vboxsync /*
1637773d6c473e4ab75812805ef00226f3a397c0vboxsync * Scan the attributes and validate the two required attributes
1637773d6c473e4ab75812805ef00226f3a397c0vboxsync * (RFC-2315, chapter 9.2, fourth bullet). Checking that we've got exactly
1637773d6c473e4ab75812805ef00226f3a397c0vboxsync * one of each of them is checked by the santiy checker function, so we'll
78a072e1b56619e3230735ae073668311232ec94vboxsync * just assert that it did it's job here.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t cContentTypes = 0;
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t cMessageDigests = 0;
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t i = pSignerInfo->AuthenticatedAttributes.cItems;
78a072e1b56619e3230735ae073668311232ec94vboxsync while (i-- > 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[i];
78a072e1b56619e3230735ae073668311232ec94vboxsync
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync AssertReturn(!cContentTypes, VERR_CR_PKCS7_INTERNAL_ERROR);
78a072e1b56619e3230735ae073668311232ec94vboxsync AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_CR_PKCS7_INTERNAL_ERROR);
78a072e1b56619e3230735ae073668311232ec94vboxsync AssertReturn(pAttrib->uValues.pObjIds->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync if ( !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE) /* See note about microsoft below. */
78a072e1b56619e3230735ae073668311232ec94vboxsync && RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
78a072e1b56619e3230735ae073668311232ec94vboxsync "Expected content-type %s, found %s",
78a072e1b56619e3230735ae073668311232ec94vboxsync &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
78a072e1b56619e3230735ae073668311232ec94vboxsync cContentTypes++;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync {
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync AssertReturn(!cMessageDigests, VERR_CR_PKCS7_INTERNAL_ERROR);
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_CR_PKCS7_INTERNAL_ERROR);
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync AssertReturn(pAttrib->uValues.pOctetStrings->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync if (!RTCrDigestMatch(*phDigest,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb))
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync {
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync size_t cbHash = RTCrDigestGetHashSize(*phDigest);
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync if (cbHash != pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb)
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync "Authenticated message-digest attribute mismatch: cbHash=%#zx cbValue=%#x",
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb);
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync "Authenticated message-digest attribute mismatch (cbHash=%#zx):\n"
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync "signed: %.*Rhxs\n"
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync "our: %.*Rhxs\n",
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync cbHash,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync cbHash, RTCrDigestGetHash(*phDigest));
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync }
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync cMessageDigests++;
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync }
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync }
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync /*
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync * Full error reporting here as we don't currently extensively santiy check
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync * counter signatures.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Note! Microsoft includes content info in their timestamp counter signatures,
78a072e1b56619e3230735ae073668311232ec94vboxsync * at least for vista, despite the RFC-3852 stating counter signatures
78a072e1b56619e3230735ae073668311232ec94vboxsync * "MUST NOT contain a content-type".
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync */
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync if (RT_UNLIKELY( cContentTypes != 1
78a072e1b56619e3230735ae073668311232ec94vboxsync && !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE)))
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
78a072e1b56619e3230735ae073668311232ec94vboxsync "Missing authenticated content-type attribute.");
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_UNLIKELY(cMessageDigests != 1))
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
78a072e1b56619e3230735ae073668311232ec94vboxsync "Missing authenticated message-digest attribute.");
78a072e1b56619e3230735ae073668311232ec94vboxsync
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Calculate the digest of the the authenticated attributes for use in the
78a072e1b56619e3230735ae073668311232ec94vboxsync * signature validation.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if ( pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NULL
78a072e1b56619e3230735ae073668311232ec94vboxsync && pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NOT_PRESENT)
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL, "Digest algorithm has unsupported parameters");
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCRDIGEST hDigest;
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync int rc = RTCrDigestCreateByObjId(&hDigest, &pSignerInfo->DigestAlgorithm.Algorithm);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCrDigestRelease(*phDigest);
78a072e1b56619e3230735ae073668311232ec94vboxsync *phDigest = hDigest;
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* ASSUMES that the attributes are encoded according to DER. */
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync uint8_t const *pbData = (uint8_t const *)RTASN1CORE_GET_RAW_ASN1_PTR(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t cbData = RTASN1CORE_GET_RAW_ASN1_SIZE(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
78a072e1b56619e3230735ae073668311232ec94vboxsync uint8_t bSetOfTag = ASN1_TAG_SET | ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED;
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrDigestUpdate(hDigest, &bSetOfTag, sizeof(bSetOfTag)); /* Replace the implict tag with a SET-OF tag. */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrDigestUpdate(hDigest, pbData + sizeof(bSetOfTag), cbData - sizeof(bSetOfTag)); /* Skip the implicit tag. */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrDigestFinal(hDigest, NULL, 0);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync return rc;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Find the handle to the digest given by the specified SignerInfo.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns IPRT status code
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param phDigest Where to return a referenced digest handle on
78a072e1b56619e3230735ae073668311232ec94vboxsync * success.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignedData The signed data structure.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignerInfo The signer info.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pahDigests Array of content digests that runs parallel to
78a072e1b56619e3230735ae073668311232ec94vboxsync * pSignedData->DigestAlgorithms.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pErrInfo Where to store additional error details,
78a072e1b56619e3230735ae073668311232ec94vboxsync * optional.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncstatic int rtCrPkcs7VerifyFindDigest(PRTCRDIGEST phDigest, PCRTCRPKCS7SIGNEDDATA pSignedData,
78a072e1b56619e3230735ae073668311232ec94vboxsync PCRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRDIGEST pahDigests, PRTERRINFO pErrInfo)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
78a072e1b56619e3230735ae073668311232ec94vboxsync while (iDigest-- > 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->DigestAlgorithm) == 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCRDIGEST hDigest = pahDigests[iDigest];
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t cRefs = RTCrDigestRetain(hDigest);
78a072e1b56619e3230735ae073668311232ec94vboxsync AssertReturn(cRefs != UINT32_MAX, VERR_CR_PKCS7_INTERNAL_ERROR);
78a072e1b56619e3230735ae073668311232ec94vboxsync *phDigest = hDigest;
78a072e1b56619e3230735ae073668311232ec94vboxsync return VINF_SUCCESS;
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
78a072e1b56619e3230735ae073668311232ec94vboxsync "SignerInfo.DigestAlgorithm %s not found.",
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Verifies one signature on a PKCS \#7 SignedData.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns IPRT status code.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignerInfo The signature.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pSignedData The SignedData.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param hDigests The digest corresponding to
78a072e1b56619e3230735ae073668311232ec94vboxsync * pSignerInfo->DigestAlgorithm.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param fFlags Verficiation flags.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param hAdditionalCerts Store containing optional certificates,
78a072e1b56619e3230735ae073668311232ec94vboxsync * optional.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param hTrustedCerts Store containing trusted certificates, required.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pValidationTime The time we're supposed to validate the
78a072e1b56619e3230735ae073668311232ec94vboxsync * certificates chains at.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pfnVerifyCert Signing certificate verification callback.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param fVccFlags Signing certificate verification callback flags.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pvUser Callback parameter.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pErrInfo Where to store additional error details,
78a072e1b56619e3230735ae073668311232ec94vboxsync * optional.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncstatic int rtCrPkcs7VerifySignerInfo(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCRDIGEST hDigest, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
78a072e1b56619e3230735ae073668311232ec94vboxsync PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert,
78a072e1b56619e3230735ae073668311232ec94vboxsync uint32_t fVccFlags, void *pvUser, PRTERRINFO pErrInfo)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Locate the certificate used for signing.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync PCRTCRCERTCTX pSignerCertCtx = NULL;
78a072e1b56619e3230735ae073668311232ec94vboxsync PCRTCRX509CERTIFICATE pSignerCert = NULL;
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCRSTORE hSignerCertSrc = hTrustedCerts;
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hSignerCertSrc != NIL_RTCRSTORE)
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!pSignerCertCtx)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync hSignerCertSrc = hAdditionalCerts;
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync if (hSignerCertSrc != NIL_RTCRSTORE)
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync if (pSignerCertCtx)
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync pSignerCert = pSignerCertCtx->pCert;
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync {
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync hSignerCertSrc = NULL;
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerCert = RTCrX509Certificates_FindByIssuerAndSerialNumber(&pSignedData->Certificates,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->IssuerAndSerialNumber.Name,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (!pSignerCert)
78a072e1b56619e3230735ae073668311232ec94vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND,
78a072e1b56619e3230735ae073668311232ec94vboxsync "Certificate not found: serial=%.*Rhxs",
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb,
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.uData.pv);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * If not a trusted certificate, we'll have to build certificate paths
78a072e1b56619e3230735ae073668311232ec94vboxsync * and verify them. If no valid paths are found, this step will fail.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync int rc = VINF_SUCCESS;
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync if ( hSignerCertSrc == NIL_RTCRSTORE
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync || hSignerCertSrc != hTrustedCerts)
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync {
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync RTCRX509CERTPATHS hCertPaths;
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrX509CertPathsCreate(&hCertPaths, pSignerCert);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, pValidationTime);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hTrustedCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (hAdditionalCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (pSignedData->Certificates.cItems > 0 && RT_SUCCESS(rc))
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync rc = RTCrX509CertPathsSetUntrustedArray(hCertPaths,
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignedData->Certificates.paItems,
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignedData->Certificates.cItems);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync rc = RTCrX509CertPathsBuild(hCertPaths, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Check that the certificate purpose and whatnot matches what
78a072e1b56619e3230735ae073668311232ec94vboxsync * is being signed.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = pfnVerifyCert(pSignerCert, hCertPaths, fVccFlags, pvUser, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync RTErrInfoSetF(pErrInfo, rc, "Error configuring path builder: %Rrc", rc);
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCrX509CertPathsRelease(hCertPaths);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Check that the certificate purpose matches what is signed.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, fVccFlags, pvUser, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Reference the digest so we can safely replace with one on the
78a072e1b56619e3230735ae073668311232ec94vboxsync * authenticated attributes below.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if ( RT_SUCCESS(rc)
78a072e1b56619e3230735ae073668311232ec94vboxsync && RTCrDigestRetain(hDigest) != UINT32_MAX)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * If there are authenticated attributes, we've got more work before we
78a072e1b56619e3230735ae073668311232ec94vboxsync * can verify the signature.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if ( RT_SUCCESS(rc)
78a072e1b56619e3230735ae073668311232ec94vboxsync && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Verify the signature.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCRPKIXSIGNATURE hSignature;
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrPkixSignatureCreateByObjId(&hSignature,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
78a072e1b56619e3230735ae073668311232ec94vboxsync false /*fSigning*/,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
78a072e1b56619e3230735ae073668311232ec94vboxsync &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_SUCCESS(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync {
78a072e1b56619e3230735ae073668311232ec94vboxsync /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
78a072e1b56619e3230735ae073668311232ec94vboxsync * (this is not vital). */
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (RT_FAILURE(rc))
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
78a072e1b56619e3230735ae073668311232ec94vboxsync "Signature verficiation failed: %Rrc", rc);
78a072e1b56619e3230735ae073668311232ec94vboxsync RTCrPkixSignatureRelease(hSignature);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
78a072e1b56619e3230735ae073668311232ec94vboxsync pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync RTCrDigestRelease(hDigest);
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync }
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync else if (RT_SUCCESS(rc))
b9efdf4f2f5a547f76dc2e254656d83cab80ce73vboxsync rc = VERR_CR_PKCS7_INTERNAL_ERROR;
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync RTCrCertCtxRelease(pSignerCertCtx);
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync return rc;
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync}
36dd9dabf3f64468206cb74145b51245cf7fde54vboxsync
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync/**
67927207a2d6bb545eb655ef14cdb090b1957120vboxsync * Verifies a counter signature.
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync *
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync * @returns IPRT status code.
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync * @param pCounterSignerInfo The counter signature.
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync * @param pPrimarySignerInfo The primary signature (can be a counter
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync * signature too if nested).
e3197fda68ad1e45cc3004f5b58a326a5270aa8fvboxsync * @param pSignedData The SignedData.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param fFlags Verficiation flags.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param hAdditionalCerts Store containing optional certificates,
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * optional.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param hTrustedCerts Store containing trusted certificates, required.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param pValidationTime The time we're supposed to validate the
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * certificates chains at.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param pfnVerifyCert Signing certificate verification callback.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param fVccFlags Signing certificate verification callback flags.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param pvUser Callback parameter.
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * @param pErrInfo Where to store additional error details,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync * optional.
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync */
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsyncstatic int rtCrPkcs7VerifyCounterSignerInfo(PCRTCRPKCS7SIGNERINFO pCounterSignerInfo, PCRTCRPKCS7SIGNERINFO pPrimarySignerInfo,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts, PCRTTIMESPEC pValidationTime,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, uint32_t fVccFlags,
60a6d709c252770b3830c85deac9c493625e3f52vboxsync void *pvUser, PRTERRINFO pErrInfo)
60a6d709c252770b3830c85deac9c493625e3f52vboxsync{
60a6d709c252770b3830c85deac9c493625e3f52vboxsync /*
60a6d709c252770b3830c85deac9c493625e3f52vboxsync * Calculate the digest we need to verify.
60a6d709c252770b3830c85deac9c493625e3f52vboxsync */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync RTCRDIGEST hDigest;
60a6d709c252770b3830c85deac9c493625e3f52vboxsync int rc = RTCrDigestCreateByObjId(&hDigest, &pCounterSignerInfo->DigestAlgorithm.Algorithm);
60a6d709c252770b3830c85deac9c493625e3f52vboxsync if (RT_SUCCESS(rc))
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync {
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync rc = RTCrDigestUpdate(hDigest,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync pPrimarySignerInfo->EncryptedDigest.Asn1Core.uData.pv,
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync pPrimarySignerInfo->EncryptedDigest.Asn1Core.cb);
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync if (RT_SUCCESS(rc))
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync rc = RTCrDigestFinal(hDigest, NULL, 0);
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync if (RT_SUCCESS(rc))
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync {
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync /*
3f6d4775faa373634b2f3fc2a90fc517733f6fd6vboxsync * Pass it on to the common SignerInfo verifier function.
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync */
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync rc = rtCrPkcs7VerifySignerInfo(pCounterSignerInfo, pSignedData, hDigest,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync fFlags | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync hAdditionalCerts, hTrustedCerts, pValidationTime,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync pfnVerifyCert, fVccFlags, pvUser, pErrInfo);
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync }
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync else
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync "Hashing for counter signature failed unexpectedly: %Rrc", rc);
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync RTCrDigestRelease(hDigest);
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync }
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync else
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync pCounterSignerInfo->DigestAlgorithm.Algorithm.szObjId, rc);
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync return rc;
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync}
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsyncRTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync PRTERRINFO pErrInfo)
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync{
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync /*
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync * Check the input.
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (pfnVerifyCert)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync AssertPtrReturn(pfnVerifyCert, VERR_INVALID_POINTER);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync else
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pfnVerifyCert = RTCrPkcs7VerifyCertCallbackDefault;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (!RTCrPkcs7ContentInfo_IsSignedData(pContentInfo))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NOT_SIGNED_DATA, "Not PKCS #7 SignedData.");
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync PCRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync int rc = RTCrPkcs7SignedData_CheckSanity(pSignedData, 0, pErrInfo, "");
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_FAILURE(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return rc;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync AssertReturn(!(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE), VERR_INVALID_FLAGS);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /*
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync * Hash the content info.
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /* Exactly what the content is, for some stupid reason unnecessarily
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync complicated. Figure it out here as we'll need it for the OpenSSL code
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync path as well. */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync void const *pvContent = pSignedData->ContentInfo.Content.Asn1Core.uData.pv;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync uint32_t cbContent = pSignedData->ContentInfo.Content.Asn1Core.cb;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (pSignedData->ContentInfo.Content.pEncapsulated)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pvContent = pSignedData->ContentInfo.Content.pEncapsulated->uData.pv;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync cbContent = pSignedData->ContentInfo.Content.pEncapsulated->cb;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /* Check that there aren't too many or too few hash algorithms for our
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync implementation and purposes. */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync RTCRDIGEST ahDigests[2];
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync uint32_t const cDigests = pSignedData->DigestAlgorithms.cItems;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (!cDigests) /** @todo we might have to support this... */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS, "No digest algorithms");
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (cDigests > RT_ELEMENTS(ahDigests))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_TOO_MANY_DIGEST_ALGORITHMS,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync "Too many digest algorithm: cAlgorithms=%u", cDigests);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /* Create the message digest calculators. */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync uint32_t i;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync for (i = 0; i < cDigests; i++)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTCrDigestCreateByObjId(&ahDigests[i], &pSignedData->DigestAlgorithms.paItems[i].Algorithm);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_FAILURE(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pSignedData->DigestAlgorithms.paItems[i].Algorithm.szObjId, rc);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync break;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_SUCCESS(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /* Hash the content. */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync for (i = 0; i < cDigests && RT_SUCCESS(rc); i++)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTCrDigestUpdate(ahDigests[i], pvContent, cbContent);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_SUCCESS(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTCrDigestFinal(ahDigests[i], NULL, 0);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_SUCCESS(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /*
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync * Validate the signed infos.
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = VERR_CR_PKCS7_NO_SIGNER_INFOS;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync for (i = 0; i < pSignedData->SignerInfos.cItems; i++)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync PCRTCRPKCS7SIGNERINFO pSignerInfo = &pSignedData->SignerInfos.paItems[i];
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync RTCRDIGEST hThisDigest;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = rtCrPkcs7VerifyFindDigest(&hThisDigest, pSignedData, pSignerInfo, ahDigests, pErrInfo);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_FAILURE(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync break;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /*
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync * See if we can find a trusted signing time.
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync */
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync bool fDone = false;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync PCRTCRPKCS7SIGNERINFO pSigningTimeSigner = NULL;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync PCRTASN1TIME pSignedTime;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync while ( !fDone
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync && (pSignedTime = RTCrPkcs7SignerInfo_GetSigningTime(pSignerInfo, &pSigningTimeSigner)) != NULL)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync RTTIMESPEC ThisValidationTime;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (pSigningTimeSigner == pSignerInfo)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync continue;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA | RTCRPKCS7VCC_F_TIMESTAMP,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pvUser, pErrInfo);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync else
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = VINF_SUCCESS;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = rtCrPkcs7VerifyCounterSignerInfo(pSigningTimeSigner, pSignerInfo, pSignedData, fFlags,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pfnVerifyCert, RTCRPKCS7VCC_F_TIMESTAMP, pvUser, pErrInfo);
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync if (RT_SUCCESS(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync hTrustedCerts, &ThisValidationTime,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync fDone = RT_SUCCESS(rc)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync else
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_3, "RTTimeImplode failed");
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync fDone = true;
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /*
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync * No valid signing time found, use the one specified instead.
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (!fDone)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts, hTrustedCerts,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync pValidationTime, pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync RTCrDigestRelease(hThisDigest);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync if (RT_FAILURE(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync break;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync else
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync "Hashing content failed unexpectedly (i=%u): %Rrc", i, rc);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync /* Clean up digests. */
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync i = cDigests;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync while (i-- > 0)
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync {
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync int rc2 = RTCrDigestRelease(ahDigests[i]);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync AssertRC(rc2);
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync }
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync#ifdef IPRT_WITH_OPENSSL
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync /*
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * Verify using OpenSSL and combine the results (should be identical).
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync */
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync int rcOssl = rtCrPkcs7VerifySignedDataUsingOpenSsl(pContentInfo, fFlags, hAdditionalCerts, hTrustedCerts,
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync pvContent, cbContent, RT_SUCCESS(rc) ? pErrInfo : NULL);
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync if (RT_SUCCESS(rcOssl) && RT_SUCCESS(rc))
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync return rc;
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync// AssertMsg(RT_FAILURE_NP(rcOssl) && RT_FAILURE_NP(rc), ("%Rrc, %Rrc\n", rcOssl, rc));
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync if (RT_FAILURE(rc))
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return rc;
144b558460813c947bcc0845c183df352b251f35vboxsync return rcOssl;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync#else
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync return rc;
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync#endif
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync}
22ecc39cb2e9aeb958d702b60fd677e8df0cdc70vboxsync
144b558460813c947bcc0845c183df352b251f35vboxsync