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