コード例 #1
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
/**
 * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
 * Standard code signing.  Use this for Microsoft SPC.}
 */
RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
                                                   void *pvUser, PRTERRINFO pErrInfo)
{
    int rc = VINF_SUCCESS;
    if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
    {
        /*
         * If KeyUsage is present it must include digital signature.
         */
        rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
        if (RT_SUCCESS(rc))
        {
            /*
             * The extended usage 'code signing' must be present.
             */
            if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
            if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
                                     pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
        }
    }

    /*
     * Timestamping too?
     */
    if (   (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
        && RT_SUCCESS(rc))
        rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);

    return rc;
}
コード例 #2
0
static int rtCrX509TbsCertificate_CheckSanityExtra(PCRTCRX509TBSCERTIFICATE pThis, uint32_t fFlags,
                                                   PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (   RTAsn1Integer_IsPresent(&pThis->T0.Version)
        && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V1) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V2) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V3) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_UNSUPPORTED_VERSION,
                             "%s: Unknown Version number: %llu",
                             pszErrorTag, pThis->T0.Version.uValue.u);

    if (   pThis->SerialNumber.Asn1Core.cb < 1
        || pThis->SerialNumber.Asn1Core.cb > 1024)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_SERIAL_NUMBER_OUT_OF_BOUNDS,
                             "%s: Bad SerialNumber length: %u", pszErrorTag, pThis->SerialNumber.Asn1Core.cb);

    if (  (   RTAsn1BitString_IsPresent(&pThis->T1.IssuerUniqueId)
           || RTAsn1BitString_IsPresent(&pThis->T2.SubjectUniqueId))
        && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V2) < 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_UNIQUE_IDS_REQ_V2,
                             "%s: IssuerUniqueId and SubjectUniqueId requires version 2", pszErrorTag);

    if (   RTCrX509Extensions_IsPresent(&pThis->T3.Extensions)
        && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V3) < 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_EXTS_REQ_V3, "%s: Extensions requires version 3", pszErrorTag);

    return VINF_SUCCESS;
}
コード例 #3
0
/** @callback_method_impl{FNVBOXEXTPACKREGISTER}  */
extern "C" DECLEXPORT(int) VBoxExtPackRegister(PCVBOXEXTPACKHLP pHlp, PCVBOXEXTPACKREG *ppReg, PRTERRINFO pErrInfo)
{
    /*
     * Check the VirtualBox version.
     */
    if (!VBOXEXTPACK_IS_VER_COMPAT(pHlp->u32Version, VBOXEXTPACKHLP_VERSION))
        return RTErrInfoSetF(pErrInfo, VERR_VERSION_MISMATCH,
                             "Helper version mismatch - expected %#x got %#x",
                             VBOXEXTPACKHLP_VERSION, pHlp->u32Version);
    if (   VBOX_FULL_VERSION_GET_MAJOR(pHlp->uVBoxFullVersion) != VBOX_VERSION_MAJOR
            || VBOX_FULL_VERSION_GET_MINOR(pHlp->uVBoxFullVersion) != VBOX_VERSION_MINOR)
        return RTErrInfoSetF(pErrInfo, VERR_VERSION_MISMATCH,
                             "VirtualBox version mismatch - expected %u.%u got %u.%u",
                             VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR,
                             VBOX_FULL_VERSION_GET_MAJOR(pHlp->uVBoxFullVersion),
                             VBOX_FULL_VERSION_GET_MINOR(pHlp->uVBoxFullVersion));

    /*
     * We're good, save input and return the registration structure.
     */
    g_pHlp = pHlp;
    *ppReg = &g_vboxSkeletonExtPackReg;

    return VINF_SUCCESS;
}
コード例 #4
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
static int rtCrPkcs7VerifyCertUsageTimstamping(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
{
    if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
    if (!(pCert->TbsCertificate.T3.fExtKeyUsage & (RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING)))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x (time stamping)",
                             pCert->TbsCertificate.T3.fExtKeyUsage,
                             RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING);
    return VINF_SUCCESS;
}
コード例 #5
0
RTDECL(int) RTAsn1Integer_CheckSanity(PCRTASN1INTEGER pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    RT_NOREF_PV(fFlags);
    if (RT_UNLIKELY(!RTAsn1Integer_IsPresent(pThis)))
        return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (INTEGER).", pszErrorTag);
    return VINF_SUCCESS;
}
コード例 #6
0
ファイル: asn1-ut-core.cpp プロジェクト: bayasist/vbox
RTDECL(int) RTAsn1Core_CheckSanity(PCRTASN1CORE pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    /* We can only check that it's present. */
    if (!RTAsn1Core_IsPresent(pThis))
        return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (RTASN1CORE).", pszErrorTag);
    return VINF_SUCCESS;
}
コード例 #7
0
static int rtCrX509Validity_CheckSanityExtra(PCRTCRX509VALIDITY pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (RTAsn1Time_Compare(&pThis->NotBefore, &pThis->NotAfter) > 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_VALIDITY_SWAPPED, "%s: NotBefore is after NotAfter", pszErrorTag);
    /** @todo check tag constraints? */
    return VINF_SUCCESS;
}
コード例 #8
0
ファイル: asn1-ut-dyntype.cpp プロジェクト: mcenirm/vbox
RTDECL(int) RTAsn1DynType_CheckSanity(PCRTASN1DYNTYPE pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (RT_UNLIKELY(!RTAsn1DynType_IsPresent(pThis)))
        return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (DYNTYPE).", pszErrorTag);

    int rc;
    switch (pThis->enmType)
    {
        case RTASN1TYPE_CORE:           rc = RTAsn1Core_CheckSanity(&pThis->u.Core, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_NULL:           rc = RTAsn1Null_CheckSanity(&pThis->u.Asn1Null, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_INTEGER:        rc = RTAsn1Integer_CheckSanity(&pThis->u.Integer, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_BOOLEAN:        rc = RTAsn1Boolean_CheckSanity(&pThis->u.Boolean, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_STRING:         rc = RTAsn1String_CheckSanity(&pThis->u.String, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_OCTET_STRING:   rc = RTAsn1OctetString_CheckSanity(&pThis->u.OctetString, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_BIT_STRING:     rc = RTAsn1BitString_CheckSanity(&pThis->u.BitString, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_TIME:           rc = RTAsn1Time_CheckSanity(&pThis->u.Time, fFlags, pErrInfo, pszErrorTag); break;
#if 0
        case RTASN1TYPE_SEQUENCE_CORE:  rc = VINF_SUCCESS; //rc = RTAsn1SequenceCore_CheckSanity(&pThis->u.SeqCore, fFlags, pErrInfo, pszErrorTag); break;
        case RTASN1TYPE_SET_CORE:       rc = VINF_SUCCESS; //rc = RTAsn1SetCore_CheckSanity(&pThis->u.SetCore, fFlags, pErrInfo, pszErrorTag); break;
#endif
        case RTASN1TYPE_OBJID:          rc = RTAsn1ObjId_CheckSanity(&pThis->u.ObjId, fFlags, pErrInfo, pszErrorTag); break;
        default:
            AssertFailedReturn(VERR_ASN1_INTERNAL_ERROR_2);
    }

    return rc;
}
コード例 #9
0
ファイル: ldrNative.cpp プロジェクト: mcenirm/vbox
RTDECL(int) RTLdrLoadEx(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
{
    LogFlow(("RTLdrLoadEx: pszFilename=%p:{%s} phLdrMod=%p fFlags=%#x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));

    /*
     * Validate and massage the input.
     */
    RTErrInfoClear(pErrInfo);
    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
    AssertReturn(!(fFlags & ~RTLDRLOAD_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);

    /*
     * Allocate and initialize module structure.
     */
    int rc = VERR_NO_MEMORY;
    PRTLDRMODNATIVE pMod = (PRTLDRMODNATIVE)RTMemAlloc(sizeof(*pMod));
    if (pMod)
    {
        pMod->Core.u32Magic     = RTLDRMOD_MAGIC;
        pMod->Core.eState       = LDR_STATE_LOADED;
        pMod->Core.pOps         = &g_rtldrNativeOps;
        pMod->Core.pReader      = NULL;
        pMod->Core.enmFormat    = RTLDRFMT_NATIVE;
        pMod->Core.enmType      = RTLDRTYPE_SHARED_LIBRARY_RELOCATABLE; /* approx */
#ifdef RT_BIG_ENDIAN
        pMod->Core.enmEndian    = RTLDRENDIAN_BIG;
#else
        pMod->Core.enmEndian    = RTLDRENDIAN_LITTLE;
#endif
#ifdef RT_ARCH_AMD64
        pMod->Core.enmArch      = RTLDRARCH_AMD64;
#elif defined(RT_ARCH_X86)
        pMod->Core.enmArch      = RTLDRARCH_X86_32;
#else
        pMod->Core.enmArch      = RTLDRARCH_HOST;
#endif
        pMod->hNative           = ~(uintptr_t)0;
        pMod->fFlags            = fFlags;

        /*
         * Attempt to open the module.
         */
        rc = rtldrNativeLoad(pszFilename, &pMod->hNative, fFlags, pErrInfo);
        if (RT_SUCCESS(rc))
        {
            *phLdrMod = &pMod->Core;
            LogFlow(("RTLdrLoad: returns %Rrc *phLdrMod=%RTldrm\n", rc, *phLdrMod));
            return rc;
        }

        RTMemFree(pMod);
    }
    else
        RTErrInfoSetF(pErrInfo, rc, "Failed to allocate %zu bytes for the module handle", sizeof(*pMod));
    *phLdrMod = NIL_RTLDRMOD;
    LogFlow(("RTLdrLoad: returns %Rrc\n", rc));
    return rc;
}
コード例 #10
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
static int rtCrPkcs7VerifyCertUsageDigitalSignature(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
{
    if (   (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
        && !(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fKeyUsage=%#x, missing %#x",
                             pCert->TbsCertificate.T3.fKeyUsage, RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE);
    return VINF_SUCCESS;
}
コード例 #11
0
ファイル: x509-verify.cpp プロジェクト: mcenirm/vbox
RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
                                                PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
                                                PRTERRINFO pErrInfo)
{
    /*
     * Validate the input a little.
     */
    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    AssertReturn(RTCrX509Certificate_IsPresent(pThis), VERR_INVALID_PARAMETER);

    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);

    if (pParameters)
    {
        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
        if (pParameters->enmType == RTASN1TYPE_NULL)
            pParameters = NULL;
    }

    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);

    /*
     * Check if the algorithm matches.
     */
    const char *pszCipherOid = RTCrPkixGetCiperOidFromSignatureAlgorithm(&pThis->SignatureAlgorithm.Algorithm);
    if (!pszCipherOid)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO,
                             "Certificate signature algorithm not known: %s",
                             pThis->SignatureAlgorithm.Algorithm.szObjId);

    if (RTAsn1ObjId_CompareWithString(pAlgorithm, pszCipherOid) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH,
                             "Certificate signature cipher algorithm mismatch: cert uses %s (%s) while key uses %s",
                             pszCipherOid, pThis->SignatureAlgorithm.Algorithm.szObjId, pAlgorithm->szObjId);

    /*
     * Here we should recode the to-be-signed part as DER, but we'll ASSUME
     * that it's already in DER encoding.  This is safe.
     */
    return RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey, &pThis->SignatureValue,
                                         RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                         RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                         pErrInfo);
}
コード例 #12
0
static int rtCrX509Name_CheckSanityExtra(PCRTCRX509NAME pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    RT_NOREF_PV(fFlags);

    if (pThis->cItems == 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_NAME_EMPTY_SET, "%s: Has no components.", pszErrorTag);

    for (uint32_t i = 0; i < pThis->cItems; i++)
    {
        PCRTCRX509RELATIVEDISTINGUISHEDNAME const pRdn = pThis->papItems[i];
        if (pRdn->cItems == 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_X509_NAME_EMPTY_SUB_SET,
                                 "%s: Items[%u] has no sub components.", pszErrorTag, i);

        for (uint32_t j = 0; j < pRdn->cItems; j++)
        {
            PCRTCRX509ATTRIBUTETYPEANDVALUE const pAttr = pRdn->papItems[j];

            if (pAttr->Value.enmType != RTASN1TYPE_STRING)
                return RTErrInfoSetF(pErrInfo, VERR_CR_X509_NAME_NOT_STRING,
                                     "%s: Items[%u].paItems[%u].enmType is %d instead of string (%d).",
                                     pszErrorTag, i, j, pAttr->Value.enmType, RTASN1TYPE_STRING);
            if (pAttr->Value.u.String.Asn1Core.cb == 0)
                return RTErrInfoSetF(pErrInfo, VERR_CR_X509_NAME_EMPTY_STRING,
                                     "%s: Items[%u].paItems[%u] is an empty string", pszErrorTag, i, j);
            switch (pAttr->Value.u.String.Asn1Core.uTag)
            {
                case ASN1_TAG_PRINTABLE_STRING:
                case ASN1_TAG_UTF8_STRING:
                    break;
                case ASN1_TAG_T61_STRING:
                case ASN1_TAG_UNIVERSAL_STRING:
                case ASN1_TAG_BMP_STRING:
                    break;
                case ASN1_TAG_IA5_STRING: /* Used by "Microsoft Root Certificate Authority" in the "com" part of the Issuer. */
                    break;
                default:
                    return RTErrInfoSetF(pErrInfo, VERR_CR_X509_INVALID_NAME_STRING_TAG,
                                         "%s: Items[%u].paItems[%u] invalid string type: %u",  pszErrorTag, i, j,
                                         pAttr->Value.u.String.Asn1Core.uTag);
            }
        }
    }

    return VINF_SUCCESS;
}
コード例 #13
0
static int rtCrX509SubjectPublicKeyInfo_CheckSanityExtra(PCRTCRX509SUBJECTPUBLICKEYINFO pThis, uint32_t fFlags,
                                                         PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (pThis->SubjectPublicKey.cBits <= 32)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_PUBLIC_KEY_TOO_SMALL,
                             "%s: SubjectPublicKey is too small, only %u bits", pszErrorTag, pThis->SubjectPublicKey.cBits);
    return VINF_SUCCESS;
}
コード例 #14
0
static int rtCrX509Certificate_CheckSanityExtra(PCRTCRX509CERTIFICATE pThis, uint32_t fFlags,
                                               PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (RTCrX509AlgorithmIdentifier_Compare(&pThis->SignatureAlgorithm, &pThis->TbsCertificate.Signature) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_CERT_TBS_SIGN_ALGO_MISMATCH,
                             "%s: SignatureAlgorithm (%s) does not match TbsCertificate.Signature (%s).", pszErrorTag,
                             pThis->SignatureAlgorithm.Algorithm.szObjId,
                             pThis->TbsCertificate.Signature.Algorithm.szObjId);
    return VINF_SUCCESS;
}
コード例 #15
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
/**
 * Verifies a counter signature.
 *
 * @returns IPRT status code.
 * @param   pCounterSignerInfo  The counter signature.
 * @param   pPrimarySignerInfo  The primary signature (can be a counter
 *                              signature too if nested).
 * @param   pSignedData         The SignedData.
 * @param   fFlags              Verficiation flags.
 * @param   hAdditionalCerts    Store containing optional certificates,
 *                              optional.
 * @param   hTrustedCerts       Store containing trusted certificates, required.
 * @param   pValidationTime     The time we're supposed to validate the
 *                              certificates chains at.
 * @param   pfnVerifyCert       Signing certificate verification callback.
 * @param   fVccFlags           Signing certificate verification callback flags.
 * @param   pvUser              Callback parameter.
 * @param   pErrInfo            Where to store additional error details,
 *                              optional.
 */
static int rtCrPkcs7VerifyCounterSignerInfo(PCRTCRPKCS7SIGNERINFO pCounterSignerInfo, PCRTCRPKCS7SIGNERINFO pPrimarySignerInfo,
                                            PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
                                            RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts, PCRTTIMESPEC pValidationTime,
                                            PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, uint32_t fVccFlags,
                                            void *pvUser, PRTERRINFO pErrInfo)
{
    /*
     * Calculate the digest we need to verify.
     */
    RTCRDIGEST hDigest;
    int rc = RTCrDigestCreateByObjId(&hDigest, &pCounterSignerInfo->DigestAlgorithm.Algorithm);
    if (RT_SUCCESS(rc))
    {
        rc = RTCrDigestUpdate(hDigest,
                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.uData.pv,
                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.cb);
        if (RT_SUCCESS(rc))
            rc = RTCrDigestFinal(hDigest, NULL, 0);
        if (RT_SUCCESS(rc))
        {
            /*
             * Pass it on to the common SignerInfo verifier function.
             */
            rc = rtCrPkcs7VerifySignerInfo(pCounterSignerInfo, pSignedData, hDigest,
                                           fFlags | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE,
                                           hAdditionalCerts, hTrustedCerts, pValidationTime,
                                           pfnVerifyCert, fVccFlags, pvUser, pErrInfo);

        }
        else
            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
                               "Hashing for counter signature failed unexpectedly: %Rrc", rc);
        RTCrDigestRelease(hDigest);
    }
    else
        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
                           pCounterSignerInfo->DigestAlgorithm.Algorithm.szObjId, rc);

    return rc;
}
コード例 #16
0
SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
{
    /*
     * Check that the module can be trusted.
     */
    int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
    if (RT_SUCCESS(rc))
    {
        rc = supLoadModule(pszFilename, pszModule, NULL, pErrInfo, ppvImageBase);
        if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
            RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
    }
    return rc;
}
コード例 #17
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
/**
 * Find the handle to the digest given by the specified SignerInfo.
 *
 * @returns IPRT status code
 * @param   phDigest            Where to return a referenced digest handle on
 *                              success.
 * @param   pSignedData         The signed data structure.
 * @param   pSignerInfo         The signer info.
 * @param   pahDigests          Array of content digests that runs parallel to
 *                              pSignedData->DigestAlgorithms.
 * @param   pErrInfo            Where to store additional error details,
 *                              optional.
 */
static int rtCrPkcs7VerifyFindDigest(PRTCRDIGEST phDigest, PCRTCRPKCS7SIGNEDDATA pSignedData,
                                     PCRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRDIGEST pahDigests, PRTERRINFO pErrInfo)
{
    uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
    while (iDigest-- > 0)
        if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
                                                &pSignerInfo->DigestAlgorithm) == 0)
        {
            RTCRDIGEST hDigest = pahDigests[iDigest];
            uint32_t cRefs = RTCrDigestRetain(hDigest);
            AssertReturn(cRefs != UINT32_MAX, VERR_CR_PKCS7_INTERNAL_ERROR);
            *phDigest = hDigest;
            return VINF_SUCCESS;
        }
    *phDigest = NIL_RTCRDIGEST; /* Make gcc happy. */
    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
                         "SignerInfo.DigestAlgorithm %s not found.",
                         pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
}
コード例 #18
0
RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo)
{
    AssertReturn(enmStoreId > RTCRSTOREID_INVALID && enmStoreId < RTCRSTOREID_END, VERR_INVALID_PARAMETER);

    /*
     * Create an empty in-memory store.
     */
    RTCRSTORE hStore;
    int rc = RTCrStoreCreateInMem(&hStore, 128);
    if (RT_SUCCESS(rc))
    {
        *phStore = hStore;

        /*
         * Resolve the APIs we need to do this job.
         */
        RTLDRMOD hLdrMod;
        int rc2 = RTLdrLoadSystem("crypt32.dll", false /*NoUnload*/, &hLdrMod);
        if (RT_SUCCESS(rc2))
        {
            PFNCERTOPENSTORE                pfnOpenStore  = NULL;
            rc2 = RTLdrGetSymbol(hLdrMod, "CertOpenStore", (void **)&pfnOpenStore);

            PFNCERTCLOSESTORE               pfnCloseStore = NULL;
            if (RT_SUCCESS(rc2))
                rc2 = RTLdrGetSymbol(hLdrMod, "CertCloseStore", (void **)&pfnCloseStore);

            PFNCERTENUMCERTIFICATESINSTORE  pfnEnumCerts  = NULL;
            if (RT_SUCCESS(rc2))
                rc2 = RTLdrGetSymbol(hLdrMod, "CertEnumCertificatesInStore", (void **)&pfnEnumCerts);
            if (RT_SUCCESS(rc2))
            {
                /*
                 * Do the work.
                 */
                switch (enmStoreId)
                {
                case RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES:
                case RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES:
                {
                    DWORD fStore = enmStoreId == RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES
                                   ? CERT_SYSTEM_STORE_CURRENT_USER : CERT_SYSTEM_STORE_LOCAL_MACHINE;
                    static PCRTUTF16 const s_apwszStores[] =  { L"AuthRoot", L"CA", L"MY", L"Root" };
                    for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszStores); i++)
                        rc = rtCrStoreAddCertsFromNative(hStore, fStore, s_apwszStores[i], pfnOpenStore, pfnCloseStore,
                                                         pfnEnumCerts, rc, pErrInfo);
                    break;
                }

                default:
                    AssertFailed(); /* implement me */
                }
            }
            else
                rc = RTErrInfoSetF(pErrInfo, -rc2, "Error resolving crypt32.dll APIs");
            RTLdrClose(hLdrMod);
        }
        else
            rc = RTErrInfoSetF(pErrInfo, -rc2, "Error loading crypt32.dll");
    }
    else
        RTErrInfoSet(pErrInfo, rc, "RTCrStoreCreateInMem failed");
    return rc;
}
コード例 #19
0
ファイル: SUPLib-win.cpp プロジェクト: jeppeter/vbox
int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted, SUPINITOP *penmWhat, PRTERRINFO pErrInfo)
{
    /*
     * Make sure the image verifier is fully initialized.
     */
    int rc = suplibOsHardenedVerifyInit();
    if (RT_FAILURE(rc))
        return RTErrInfoSetF(pErrInfo, rc, "suplibOsHardenedVerifyInit failed: %Rrc", rc);

    /*
     * Done if of pre-inited.
     */
    if (fPreInited)
    {
#if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_HARDENED_R3)
# ifdef IN_SUP_R3_STATIC
        return VERR_NOT_SUPPORTED;
# else
        return VINF_SUCCESS;
# endif
#else
        return VINF_SUCCESS;
#endif
    }

    /*
     * Try open the device.
     */
#ifndef IN_SUP_HARDENED_R3
    uint32_t cTry = 0;
#endif
    HANDLE hDevice;
    for (;;)
    {
        IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;

        static const WCHAR  s_wszName[] = L"\\Device\\VBoxDrvU";
        UNICODE_STRING      NtName;
        NtName.Buffer        = (PWSTR)s_wszName;
        NtName.Length        = sizeof(s_wszName) - sizeof(WCHAR) * (fUnrestricted ? 2 : 1);
        NtName.MaximumLength = NtName.Length;

        OBJECT_ATTRIBUTES   ObjAttr;
        InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);

        hDevice = RTNT_INVALID_HANDLE_VALUE;

        NTSTATUS rcNt = NtCreateFile(&hDevice,
                                     GENERIC_READ | GENERIC_WRITE, /* No SYNCHRONIZE. */
                                     &ObjAttr,
                                     &Ios,
                                     NULL /* Allocation Size*/,
                                     FILE_ATTRIBUTE_NORMAL,
                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                                     FILE_OPEN,
                                     FILE_NON_DIRECTORY_FILE, /* No FILE_SYNCHRONOUS_IO_NONALERT! */
                                     NULL /*EaBuffer*/,
                                     0 /*EaLength*/);
        if (NT_SUCCESS(rcNt))
            rcNt = Ios.Status;
        if (NT_SUCCESS(rcNt))
        {
            /*
             * We're good.
             */
            pThis->hDevice       = hDevice;
            pThis->fUnrestricted = fUnrestricted;
            return VINF_SUCCESS;
        }

#ifndef IN_SUP_HARDENED_R3
        /*
         * Failed to open, try starting the service and reopen the device
         * exactly once.
         */
        if (cTry == 0 && !NT_SUCCESS(rcNt))
        {
            cTry++;
            suplibOsStartService();
            continue;
        }
#endif

        /*
         * Translate the error code.
         */
        switch (rcNt)
        {
            /** @todo someone must test what is actually returned. */
            case STATUS_DEVICE_DOES_NOT_EXIST:
            case STATUS_DEVICE_NOT_CONNECTED:
            //case ERROR_BAD_DEVICE:
            case STATUS_DEVICE_REMOVED:
            //case ERROR_DEVICE_NOT_AVAILABLE:
                rc = VERR_VM_DRIVER_LOAD_ERROR;
                break;
            case STATUS_OBJECT_PATH_NOT_FOUND:
            case STATUS_NO_SUCH_DEVICE:
            case STATUS_NO_SUCH_FILE:
            case STATUS_OBJECT_NAME_NOT_FOUND:
                rc = VERR_VM_DRIVER_NOT_INSTALLED;
                break;
            case STATUS_ACCESS_DENIED:
            case STATUS_SHARING_VIOLATION:
                rc = VERR_VM_DRIVER_NOT_ACCESSIBLE;
                break;
            case STATUS_UNSUCCESSFUL:
                rc = VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0;
                break;
            case STATUS_TRUST_FAILURE:
                rc = VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1;
                break;
            case STATUS_TOO_LATE:
                rc = VERR_SUPDRV_HARDENING_EVIL_HANDLE;
                break;
            default:
                if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
                    rc = SUP_NT_STATUS_TO_VBOX(rcNt);
                else
                    rc = VERR_VM_DRIVER_OPEN_ERROR;
                break;
        }

#ifdef IN_SUP_HARDENED_R3
        /*
         * Get more details from VBoxDrvErrorInfo if present.
         */
        if (pErrInfo && pErrInfo->cbMsg > 32)
        {
            /* Prefix. */
            size_t      cchPrefix;
            const char *pszDefine = RTErrGetDefine(rc);
            if (strncmp(pszDefine, RT_STR_TUPLE("Unknown")))
                cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%s): ", rcNt, pszDefine);
            else
                cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%d): ", rcNt, rc);

            /* Get error info. */
            supR3HardenedWinReadErrorInfoDevice(pErrInfo->pszMsg + cchPrefix, pErrInfo->cbMsg - cchPrefix, "");
            if (pErrInfo->pszMsg[cchPrefix] != '\0')
            {
                pErrInfo->fFlags |= RTERRINFO_FLAGS_SET;
                pErrInfo->rc      = rc;
                *penmWhat = kSupInitOp_Integrity;
            }
            else
                pErrInfo->pszMsg[0] = '\0';
        }
#endif
        return rc;
    }
}
コード例 #20
0
ファイル: x509-verify.cpp プロジェクト: miguelinux/vbox
RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
                                                PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
                                                PRTERRINFO pErrInfo)
{
    /*
     * Validate the input a little.
     */
    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    AssertReturn(RTCrX509Certificate_IsPresent(pThis), VERR_INVALID_PARAMETER);

    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);

    if (pParameters)
    {
        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
        if (pParameters->enmType == RTASN1TYPE_NULL)
            pParameters = NULL;
    }

    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);

    /*
     * Check if the algorithm matches.
     */
    const char *pszCipherOid = RTCrPkixGetCiperOidFromSignatureAlgorithm(&pThis->SignatureAlgorithm.Algorithm);
    if (!pszCipherOid)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO,
                             "Certificate signature algorithm not known: %s",
                             pThis->SignatureAlgorithm.Algorithm.szObjId);

    if (RTAsn1ObjId_CompareWithString(pAlgorithm, pszCipherOid) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH,
                             "Certificate signature cipher algorithm mismatch: cert uses %s (%s) while key uses %s",
                             pszCipherOid, pThis->SignatureAlgorithm.Algorithm.szObjId, pAlgorithm->szObjId);

    /*
     * Here we should recode the to-be-signed part as DER, but we'll ASSUME
     * that it's already in DER encoding and only does this if there the
     * encoded bits are missing.
     */
    if (   pThis->TbsCertificate.SeqCore.Asn1Core.uData.pu8
        && pThis->TbsCertificate.SeqCore.Asn1Core.cb > 0)
        return RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey, &pThis->SignatureValue,
                                             RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                             RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                             pErrInfo);

    uint32_t cbEncoded;
    int rc = RTAsn1EncodePrepare((PRTASN1CORE)&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER, &cbEncoded, pErrInfo);
    if (RT_SUCCESS(rc))
    {
        void *pvTbsBits = RTMemTmpAlloc(cbEncoded);
        if (pvTbsBits)
        {
            rc = RTAsn1EncodeToBuffer(&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
                                      pvTbsBits, cbEncoded, pErrInfo);
            if (RT_SUCCESS(rc))
                rc = RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey,
                                                   &pThis->SignatureValue, pvTbsBits, cbEncoded, pErrInfo);
            else
                AssertRC(rc);
            RTMemTmpFree(pvTbsBits);
        }
        else
            rc = VERR_NO_TMP_MEMORY;
    }
    return rc;
}
コード例 #21
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
/**
 * Deals with authenticated attributes.
 *
 * When authenticated attributes are present (checked by caller) we must:
 *  - fish out the content type and check it against the content inof,
 *  - fish out the message digest among and check it against *phDigest,
 *  - compute the message digest of the authenticated attributes and
 *    replace *phDigest with this for the signature verification.
 *
 * @returns IPRT status code.
 * @param   pSignerInfo         The signer info being verified.
 * @param   pSignedData         The signed data.
 * @param   phDigest            On input this is the digest of the content. On
 *                              output it will (on success) be a reference to
 *                              the message digest of the authenticated
 *                              attributes.  The input reference is consumed.
 *                              The caller shall release the output reference.
 * @param   fFlags              Flags.
 * @param   pErrInfo            Extended error info, optional.
 */
static int rtCrPkcs7VerifySignerInfoAuthAttribs(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
                                                PRTCRDIGEST phDigest, uint32_t fFlags, PRTERRINFO pErrInfo)
{
    /*
     * Scan the attributes and validate the two required attributes
     * (RFC-2315, chapter 9.2, fourth bullet).  Checking that we've got exactly
     * one of each of them is checked by the santiy checker function, so we'll
     * just assert that it did it's job here.
     */
    uint32_t    cContentTypes   = 0;
    uint32_t    cMessageDigests = 0;
    uint32_t    i               = pSignerInfo->AuthenticatedAttributes.cItems;
    while (i-- > 0)
    {
        PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[i];

        if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
        {
            AssertReturn(!cContentTypes, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->uValues.pObjIds->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);

            if (   !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE) /* See note about microsoft below. */
                && RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
                   return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
                                        "Expected content-type %s, found %s",
                                        &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
            cContentTypes++;
        }
        else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
        {
            AssertReturn(!cMessageDigests, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->uValues.pOctetStrings->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);

            if (!RTCrDigestMatch(*phDigest,
                                 pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
                                 pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb))
            {
                size_t cbHash = RTCrDigestGetHashSize(*phDigest);
                if (cbHash != pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb)
                    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
                                         "Authenticated message-digest attribute mismatch: cbHash=%#zx cbValue=%#x",
                                         cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb);
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
                                     "Authenticated message-digest attribute mismatch (cbHash=%#zx):\n"
                                     "signed: %.*Rhxs\n"
                                     "our:    %.*Rhxs\n",
                                     cbHash,
                                     cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
                                     cbHash, RTCrDigestGetHash(*phDigest));
            }
            cMessageDigests++;
        }
    }

    /*
     * Full error reporting here as we don't currently extensively santiy check
     * counter signatures.
     * Note! Microsoft includes content info in their timestamp counter signatures,
     *       at least for vista, despite the RFC-3852 stating counter signatures
     *       "MUST NOT contain a content-type".
     */
    if (RT_UNLIKELY(   cContentTypes != 1
                    && !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE)))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                            "Missing authenticated content-type attribute.");
    if (RT_UNLIKELY(cMessageDigests != 1))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                            "Missing authenticated message-digest attribute.");

    /*
     * Calculate the digest of the the authenticated attributes for use in the
     * signature validation.
     */
    if (   pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NULL
        && pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NOT_PRESENT)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL, "Digest algorithm has unsupported parameters");

    RTCRDIGEST hDigest;
    int rc = RTCrDigestCreateByObjId(&hDigest, &pSignerInfo->DigestAlgorithm.Algorithm);
    if (RT_SUCCESS(rc))
    {
        RTCrDigestRelease(*phDigest);
        *phDigest = hDigest;

        /* ASSUMES that the attributes are encoded according to DER. */
        uint8_t const  *pbData = (uint8_t const *)RTASN1CORE_GET_RAW_ASN1_PTR(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
        uint32_t        cbData = RTASN1CORE_GET_RAW_ASN1_SIZE(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
        uint8_t         bSetOfTag = ASN1_TAG_SET | ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED;
        rc = RTCrDigestUpdate(hDigest, &bSetOfTag, sizeof(bSetOfTag)); /* Replace the implict tag with a SET-OF tag. */
        if (RT_SUCCESS(rc))
            rc = RTCrDigestUpdate(hDigest, pbData + sizeof(bSetOfTag), cbData - sizeof(bSetOfTag)); /* Skip the implicit tag. */
        if (RT_SUCCESS(rc))
            rc = RTCrDigestFinal(hDigest, NULL, 0);
    }
    return rc;
}
コード例 #22
0
static int rtCrPkcs7SignedData_CheckSanityExtra(PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
                                                PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    bool const fAuthenticode = RT_BOOL(fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE);

    //RTAsn1Dump(&pSignedData->SeqCore.Asn1Core, 0, 0, RTAsn1DumpStrmPrintfV, g_pStdOut);

    if (   RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V1) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V3) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V4) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V5) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_VERSION, "SignedData version is %llu, expected %u",
                             pSignedData->Version.uValue.u, RTCRPKCS7SIGNEDDATA_V1);

    /*
     * DigestAlgorithms.
     */
    if (pSignedData->DigestAlgorithms.cItems == 0) /** @todo this might be too strict */
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS, "SignedData.DigestAlgorithms is empty");
    if (pSignedData->DigestAlgorithms.cItems != 1 && fAuthenticode)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
                             "SignedData.DigestAlgorithms has more than one algorithm (%u)",
                             pSignedData->DigestAlgorithms.cItems);

    if (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH)
        for (uint32_t i = 0; i < pSignedData->DigestAlgorithms.cItems; i++)
        {
            if (RTCrX509AlgorithmIdentifier_QueryDigestType(&pSignedData->DigestAlgorithms.paItems[i]) == RTDIGESTTYPE_INVALID)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM,
                                     "SignedData.DigestAlgorithms[%i] is not known: %s",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Algorithm.szObjId);
            if (pSignedData->DigestAlgorithms.paItems[i].Parameters.enmType != RTASN1TYPE_NULL)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL,
                                     "SignedData.DigestAlgorithms[%i] has parameters: tag=%u",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Parameters.u.Core.uTag);
        }

    /*
     * Certificates.
     */
    if (   (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT)
        && pSignedData->Certificates.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_CERTIFICATES,
                            "SignedData.Certifcates is empty, expected at least one certificate");

    /*
     * Crls.
     */
    if (fAuthenticode && RTAsn1Core_IsPresent(&pSignedData->Crls))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_EXPECTED_NO_CRLS,
                            "SignedData.Crls is not empty as expected for authenticode.");
    /** @todo check Crls when they become important. */

    /*
     * SignerInfos.
     */
    if (pSignedData->SignerInfos.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_SIGNER_INFOS, "SignedData.SignerInfos is empty?");
    if (fAuthenticode && pSignedData->SignerInfos.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO,
                             "SignedData.SignerInfos should have one entry for authenticode: %u",
                             pSignedData->SignerInfos.cItems);

    for (uint32_t i = 0; i < pSignedData->SignerInfos.cItems; i++)
    {
        PCRTCRPKCS7SIGNERINFO pSignerInfo = &pSignedData->SignerInfos.paItems[i];

        if (RTAsn1Integer_UnsignedCompareWithU32(&pSignerInfo->Version, RTCRPKCS7SIGNERINFO_V1) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_VERSION,
                                 "SignedData.SignerInfos[%u] version is %llu, expected %u",
                                 pSignerInfo->Version.uValue.u, RTCRPKCS7SIGNERINFO_V1);

        /* IssuerAndSerialNumber. */
        int rc = RTCrX509Name_CheckSanity(&pSignerInfo->IssuerAndSerialNumber.Name, 0, pErrInfo,
                                          "SignedData.SignerInfos[#].IssuerAndSerialNumber.Name");
        if (RT_FAILURE(rc))
            return rc;

        if (pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb == 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber.SerialNumber is missing (zero length)", i);

        PCRTCRX509CERTIFICATE pCert;
        pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
                                                                    &pSignerInfo->IssuerAndSerialNumber.Name,
                                                                    &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
        if (!pCert && (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT))
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber not found in T0.Certificates", i);

        /* DigestAlgorithm */
        uint32_t j = 0;
        while (   j < pSignedData->DigestAlgorithms.cItems
               && RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[j],
                                                      &pSignerInfo->DigestAlgorithm) != 0)
            j++;
        if (j >= pSignedData->DigestAlgorithms.cItems)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
                                 "SignedData.SignerInfos[%u].DigestAlgorithm (%s) not found in SignedData.DigestAlgorithms",
                                 i, pSignerInfo->DigestAlgorithm.Algorithm.szObjId);

        /* Digest encryption algorithm. */
#if 0  /** @todo Unimportant: Seen timestamp signatures specifying pkcs1-Sha256WithRsaEncryption in SignerInfo and just RSA in the certificate.  Figure out how to compare the two. */
        if (   pCert
            && RTCrX509AlgorithmIdentifier_Compare(&pSignerInfo->DigestEncryptionAlgorithm,
                                                   &pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH,
                                 "SignedData.SignerInfos[%u].DigestEncryptionAlgorithm (%s) mismatch with certificate (%s)",
                                 i, pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId,
                                 pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId);
#endif

        /* Authenticated attributes we know. */
        if (RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
        {
            bool fFoundContentInfo   = false;
            bool fFoundMessageDigest = false;
            for (j = 0; j < pSignerInfo->AuthenticatedAttributes.cItems; j++)
            {
                PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[j];
                if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
                {
                    if (fFoundContentInfo)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                            "Multiple authenticated content-type attributes.");
                    fFoundContentInfo = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pObjIds->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for content-type attrib, found: %u",
                                             pAttrib->uValues.pObjIds->cItems);
                }
                else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
                {
                    if (fFoundMessageDigest)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                            "Multiple authenticated message-digest attributes.");
                    fFoundMessageDigest = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pOctetStrings->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for message-digest attrib, found: %u",
                                             pAttrib->uValues.pOctetStrings->cItems);
                }
                else
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_UNKNOWN, VERR_INTERNAL_ERROR_3);
            }

            if (!fFoundContentInfo)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                    "Missing authenticated content-type attribute.");
            if (!fFoundMessageDigest)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                    "Missing authenticated message-digest attribute.");
        }
    }

    return VINF_SUCCESS;
}
コード例 #23
0
ファイル: pkix-verify.cpp プロジェクト: jeppeter/vbox
RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
                                          PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
                                          PRTERRINFO pErrInfo)
{
    /*
     * Valid input.
     */
    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);

    if (pParameters)
    {
        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
        if (pParameters->enmType == RTASN1TYPE_NULL)
            pParameters = NULL;
    }

    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);

    AssertPtrReturn(pSignatureValue, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pSignatureValue), VERR_INVALID_POINTER);

    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
    AssertReturn(cbData > 0, VERR_INVALID_PARAMETER);

    /*
     * Parameters are not currently supported (openssl code path).
     */
    if (pParameters)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL,
                            "Cipher algorithm parameters are not yet supported.");

    /*
     * Validate using IPRT.
     */
    RTCRPKIXSIGNATURE hSignature;
    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters);
    if (RT_FAILURE(rcIprt))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
                             "Unknown public key algorithm [IPRT]: %s", pAlgorithm->szObjId);

    RTCRDIGEST hDigest;
    rcIprt = RTCrDigestCreateByObjId(&hDigest, pAlgorithm);
    if (RT_SUCCESS(rcIprt))
    {
        /* Calculate the digest. */
        rcIprt = RTCrDigestUpdate(hDigest, pvData, cbData);
        if (RT_SUCCESS(rcIprt))
        {
            rcIprt = RTCrPkixSignatureVerifyBitString(hSignature, hDigest, pSignatureValue);
            if (RT_FAILURE(rcIprt))
                RTErrInfoSet(pErrInfo, rcIprt, "RTCrPkixSignatureVerifyBitString failed");
        }
        else
            RTErrInfoSet(pErrInfo, rcIprt, "RTCrDigestUpdate failed");
        RTCrDigestRelease(hDigest);
    }
    else
        RTErrInfoSetF(pErrInfo, rcIprt, "Unknown digest algorithm [IPRT]: %s", pAlgorithm->szObjId);
    RTCrPkixSignatureRelease(hSignature);

#ifdef IPRT_WITH_OPENSSL
    /*
     * Validate using OpenSSL EVP.
     */
    rtCrOpenSslInit();

    /* Translate the algorithm ID into a EVP message digest type pointer. */
    int iAlgoNid = OBJ_txt2nid(pAlgorithm->szObjId);
    if (iAlgoNid == NID_undef)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
                             "Unknown public key algorithm [OpenSSL]: %s", pAlgorithm->szObjId);
    const char *pszAlogSn = OBJ_nid2sn(iAlgoNid);
    const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlogSn);
    if (!pEvpMdType)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
                             "EVP_get_digestbyname failed on %s (%s)", pszAlogSn, pAlgorithm->szObjId);

    /* Initialize the EVP message digest context. */
    EVP_MD_CTX EvpMdCtx;
    EVP_MD_CTX_init(&EvpMdCtx);
    if (!EVP_VerifyInit_ex(&EvpMdCtx, pEvpMdType, NULL /*engine*/))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
                             "EVP_VerifyInit_ex failed (algorithm type is %s / %s)", pszAlogSn, pAlgorithm->szObjId);

    /* Create an EVP public key. */
    int rcOssl;
    EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
    if (pEvpPublicKey)
    {
        pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
        if (pEvpPublicKey->type != NID_undef)
        {
            const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
            if (d2i_PublicKey(pEvpPublicKey->type, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
            {
                /* Digest the data. */
                EVP_VerifyUpdate(&EvpMdCtx, pvData, cbData);

                /* Verify the signature. */
                if (EVP_VerifyFinal(&EvpMdCtx,
                                    RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue),
                                    RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue),
                                    pEvpPublicKey) > 0)
                    rcOssl = VINF_SUCCESS;
                else
                    rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed");
            }
            else
                rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
        }
        else
            rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
                                   "EVP_PKEY_type(%d) failed", pEvpMdType->required_pkey_type[0]);
        /* Cleanup and return.*/
        EVP_PKEY_free(pEvpPublicKey);
    }
    else
        rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", pEvpMdType->required_pkey_type[0]);
    EVP_MD_CTX_cleanup(&EvpMdCtx);

    /*
     * Check the result.
     */
    if (RT_SUCCESS(rcIprt) && RT_SUCCESS(rcOssl))
        return VINF_SUCCESS;
    if (RT_FAILURE_NP(rcIprt) && RT_FAILURE_NP(rcOssl))
        return rcIprt;
    AssertMsgFailed(("rcIprt=%Rrc rcOssl=%Rrc\n", rcIprt, rcOssl));
    if (RT_FAILURE_NP(rcOssl))
        return rcOssl;
#endif /* IPRT_WITH_OPENSSL */

    return rcIprt;
}
コード例 #24
0
int rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlags, PRTERRINFO pErrInfo)
{
    Assert(sizeof(*phHandle) >= sizeof(HMODULE));
    AssertReturn(!(fFlags & RTLDRLOAD_FLAGS_GLOBAL), VERR_INVALID_FLAGS);
    AssertLogRelMsgReturn(RTPathStartsWithRoot(pszFilename),  /* Relative names will still be applied to the search path. */
                          ("pszFilename='%s'\n", pszFilename),
                          VERR_INTERNAL_ERROR_2);

    /*
     * Convert to UTF-16 and make sure it got a .DLL suffix.
     */
    int rc;
    RTUTF16 *pwszNative = NULL;
    if (RTPathHasSuffix(pszFilename))
        rc = RTStrToUtf16(pszFilename, &pwszNative);
    else
    {
        size_t cwcAlloc;
        rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcAlloc);
        if (RT_SUCCESS(rc))
        {
            cwcAlloc += sizeof(".DLL");
            pwszNative = RTUtf16Alloc(cwcAlloc * sizeof(RTUTF16));
            if (pwszNative)
            {
                size_t cwcNative;
                rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwszNative, cwcAlloc, &cwcNative);
                if (RT_SUCCESS(rc))
                    rc = RTUtf16CopyAscii(&pwszNative[cwcNative], cwcAlloc - cwcNative, ".DLL");
            }
            else
                rc = VERR_NO_UTF16_MEMORY;
        }
    }
    if (RT_SUCCESS(rc))
    {
        /*
         * Attempt load.
         */
        HMODULE     hmod;
        static int  s_iSearchDllLoadDirSupported = 0;
        if (   !(fFlags & RTLDRLOAD_FLAGS_NT_SEARCH_DLL_LOAD_DIR)
            || s_iSearchDllLoadDirSupported < 0)
            hmod = LoadLibraryExW(pwszNative, NULL, 0);
        else
        {
            hmod = LoadLibraryExW(pwszNative, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32
                                  | LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
            if (s_iSearchDllLoadDirSupported == 0)
            {
                if (hmod != NULL || GetLastError() != ERROR_INVALID_PARAMETER)
                    s_iSearchDllLoadDirSupported = 1;
                else
                {
                    s_iSearchDllLoadDirSupported = -1;
                    hmod = LoadLibraryExW(pwszNative, NULL, 0);
                }
            }
        }
        if (hmod)
        {
            *phHandle = (uintptr_t)hmod;
            RTUtf16Free(pwszNative);
            return VINF_SUCCESS;
        }

        /*
         * Try figure why it failed to load.
         */
        DWORD dwErr = GetLastError();
        rc = RTErrConvertFromWin32(dwErr);
        rc = RTErrInfoSetF(pErrInfo, rc, "GetLastError=%u", dwErr);
    }
    else
        rc = RTErrInfoSetF(pErrInfo, rc, "Error converting UTF-8 to UTF-16 string.");
    RTUtf16Free(pwszNative);
    return rc;
}
コード例 #25
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
/**
 * Verifies one signature on a PKCS \#7 SignedData.
 *
 * @returns IPRT status code.
 * @param   pSignerInfo         The signature.
 * @param   pSignedData         The SignedData.
 * @param   hDigests            The digest corresponding to
 *                              pSignerInfo->DigestAlgorithm.
 * @param   fFlags              Verficiation flags.
 * @param   hAdditionalCerts    Store containing optional certificates,
 *                              optional.
 * @param   hTrustedCerts       Store containing trusted certificates, required.
 * @param   pValidationTime     The time we're supposed to validate the
 *                              certificates chains at.
 * @param   pfnVerifyCert       Signing certificate verification callback.
 * @param   fVccFlags           Signing certificate verification callback flags.
 * @param   pvUser              Callback parameter.
 * @param   pErrInfo            Where to store additional error details,
 *                              optional.
 */
static int rtCrPkcs7VerifySignerInfo(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
                                     RTCRDIGEST hDigest, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
                                     PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert,
                                     uint32_t fVccFlags, void *pvUser, PRTERRINFO pErrInfo)
{
    /*
     * Locate the certificate used for signing.
     */
    PCRTCRCERTCTX           pSignerCertCtx = NULL;
    PCRTCRX509CERTIFICATE   pSignerCert = NULL;
    RTCRSTORE               hSignerCertSrc = hTrustedCerts;
    if (hSignerCertSrc != NIL_RTCRSTORE)
        pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
                                                          &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
    if (!pSignerCertCtx)
    {
        hSignerCertSrc = hAdditionalCerts;
        if (hSignerCertSrc != NIL_RTCRSTORE)
            pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
                                                              &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
    }
    if (pSignerCertCtx)
        pSignerCert = pSignerCertCtx->pCert;
    else
    {
        hSignerCertSrc = NULL;
        pSignerCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
                                                                          &pSignerInfo->IssuerAndSerialNumber.Name,
                                                                          &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
        if (!pSignerCert)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND,
                                 "Certificate not found: serial=%.*Rhxs",
                                 pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb,
                                 pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.uData.pv);
    }

    /*
     * If not a trusted certificate, we'll have to build certificate paths
     * and verify them.  If no valid paths are found, this step will fail.
     */
    int rc = VINF_SUCCESS;
    if (   hSignerCertSrc == NIL_RTCRSTORE
        || hSignerCertSrc != hTrustedCerts)
    {
        RTCRX509CERTPATHS hCertPaths;
        rc = RTCrX509CertPathsCreate(&hCertPaths, pSignerCert);
        if (RT_SUCCESS(rc))
        {
            rc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, pValidationTime);
            if (hTrustedCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts);
            if (hAdditionalCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts);
            if (pSignedData->Certificates.cItems > 0 && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetUntrustedSet(hCertPaths, &pSignedData->Certificates);
            if (RT_SUCCESS(rc))
            {
                rc = RTCrX509CertPathsBuild(hCertPaths, pErrInfo);
                if (RT_SUCCESS(rc))
                    rc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, pErrInfo);

                /*
                 * Check that the certificate purpose and whatnot matches what
                 * is being signed.
                 */
                if (RT_SUCCESS(rc))
                    rc = pfnVerifyCert(pSignerCert, hCertPaths, fVccFlags, pvUser, pErrInfo);
            }
            else
                RTErrInfoSetF(pErrInfo, rc, "Error configuring path builder: %Rrc", rc);
            RTCrX509CertPathsRelease(hCertPaths);
        }
    }
    /*
     * Check that the certificate purpose matches what is signed.
     */
    else
        rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, fVccFlags, pvUser, pErrInfo);

    /*
     * Reference the digest so we can safely replace with one on the
     * authenticated attributes below.
     */
    if (   RT_SUCCESS(rc)
        && RTCrDigestRetain(hDigest) != UINT32_MAX)
    {
        /*
         * If there are authenticated attributes, we've got more work before we
         * can verify the signature.
         */
        if (   RT_SUCCESS(rc)
            && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
            rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);

        /*
         * Verify the signature.
         */
        if (RT_SUCCESS(rc))
        {
            RTCRPKIXSIGNATURE hSignature;
            rc = RTCrPkixSignatureCreateByObjId(&hSignature,
                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
                                                false /*fSigning*/,
                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
                                                &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
            if (RT_SUCCESS(rc))
            {
                /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
                 *        (this is not vital). */
                rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
                if (RT_FAILURE(rc))
                    rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
                                       "Signature verficiation failed: %Rrc", rc);
                RTCrPkixSignatureRelease(hSignature);
            }
            else
                rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
                                   pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
                                   pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
        }

        RTCrDigestRelease(hDigest);
    }
    else if (RT_SUCCESS(rc))
        rc = VERR_CR_PKCS7_INTERNAL_ERROR;
    RTCrCertCtxRelease(pSignerCertCtx);
    return rc;
}
コード例 #26
0
RTDECL(int) RTAsn1Time_CheckSanity(PCRTASN1TIME pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    if (RT_UNLIKELY(!RTAsn1Time_IsPresent(pThis)))
        return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (TIME).", pszErrorTag);
    return VINF_SUCCESS;
}
コード例 #27
0
ファイル: spc-sanity.cpp プロジェクト: miguelinux/vbox
RTDECL(int) RTCrSpcIndirectDataContent_CheckSanityEx(PCRTCRSPCINDIRECTDATACONTENT pIndData,
                                                     PCRTCRPKCS7SIGNEDDATA pSignedData,
                                                     uint32_t fFlags,
                                                     PRTERRINFO pErrInfo)
{
    /*
     * Match up the digest algorithms (page 8, v1.0).
     */
    if (pSignedData->SignerInfos.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_SIGNER_INFOS,
                             "SpcIndirectDataContent expects SignedData to have exactly one SignerInfos entries, found: %u",
                             pSignedData->SignerInfos.cItems);
    if (pSignedData->DigestAlgorithms.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
                             "SpcIndirectDataContent expects SignedData to have exactly one DigestAlgorithms entries, found: %u",
                             pSignedData->DigestAlgorithms.cItems);

    if (RTCrX509AlgorithmIdentifier_Compare(&pIndData->DigestInfo.DigestAlgorithm, /** @todo not entirely sure about this check... */
                                            &pSignedData->SignerInfos.paItems[0].DigestAlgorithm) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_SIGNED_IND_DATA_DIGEST_ALGO_MISMATCH,
                             "SpcIndirectDataContent DigestInfo and SignerInfos algorithms mismatch: %s vs %s",
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId,
                             pSignedData->SignerInfos.paItems[0].DigestAlgorithm.Algorithm.szObjId);

    if (RTCrX509AlgorithmIdentifier_Compare(&pIndData->DigestInfo.DigestAlgorithm,
                                            &pSignedData->DigestAlgorithms.paItems[0]) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_IND_DATA_DIGEST_ALGO_NOT_IN_DIGEST_ALGOS,
                             "SpcIndirectDataContent DigestInfo and SignedData.DigestAlgorithms[0] mismatch: %s vs %s",
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId,
                             pSignedData->DigestAlgorithms.paItems[0].Algorithm.szObjId);

    if (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH)
    {
        if (RTCrX509AlgorithmIdentifier_QueryDigestType(&pIndData->DigestInfo.DigestAlgorithm) == RTDIGESTTYPE_INVALID)
            return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_UNKNOWN_DIGEST_ALGO,
                                 "SpcIndirectDataContent DigestAlgortihm is not known: %s",
                                 pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId);
    }

    uint32_t cbDigest = RTCrX509AlgorithmIdentifier_QueryDigestSize(&pIndData->DigestInfo.DigestAlgorithm);
    if (   pIndData->DigestInfo.Digest.Asn1Core.cb != cbDigest
        && (cbDigest != UINT32_MAX || (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH)))
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_IND_DATA_DIGEST_SIZE_MISMATCH,
                             "SpcIndirectDataContent Digest size mismatch with algorithm: %u, expected %u (%s)",
                             pIndData->DigestInfo.Digest.Asn1Core.cb, cbDigest,
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId);

    /*
     * Data.
     */
    if (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_PE_IMAGE)
    {
        if (   pIndData->Data.enmType != RTCRSPCAAOVTYPE_PE_IMAGE_DATA
            || RTAsn1ObjId_CompareWithString(&pIndData->Data.Type, RTCRSPCPEIMAGEDATA_OID) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_EXPECTED_PE_IMAGE_DATA,
                                 "SpcIndirectDataContent.Data.Type is %s, expected %s (SpcPeImageData) [enmType=%d]",
                                 pIndData->Data.Type.szObjId, RTCRSPCPEIMAGEDATA_OID, pIndData->Data.enmType);
        if (   pIndData->Data.uValue.pPeImage
            || !RTCrSpcPeImageData_IsPresent(pIndData->Data.uValue.pPeImage) )
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_DATA_NOT_PRESENT,
                                "SpcIndirectDataContent.Data.uValue/PEImage is missing");

        if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_MONIKER
            && RTCrSpcSerializedObject_IsPresent(pIndData->Data.uValue.pPeImage->T0.File.u.pMoniker) )
        {
            PCRTCRSPCSERIALIZEDOBJECT pObj = pIndData->Data.uValue.pPeImage->T0.File.u.pMoniker;

            if (pObj->Uuid.Asn1Core.cb != sizeof(RTUUID))
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_BAD_MONIKER_UUID,
                                     "SpcIndirectDataContent...MonikerT1.Uuid incorrect size: %u, expected %u.",
                                     pObj->Uuid.Asn1Core.cb, sizeof(RTUUID));
            if (RTUuidCompareStr(pObj->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR) != 0)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_UNKNOWN_MONIKER_UUID,
                                     "SpcIndirectDataContent...MonikerT1.Uuid mismatch: %RTuuid, expected %s.",
                                     pObj->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR);

            if (pObj->enmType != RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_BAD_MONIKER_CHOICE,
                                     "SpcIndirectDataContent...pMoniker->enmType=%d, expected %d.",
                                     pObj->enmType, RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES);
            if (!pObj->u.pData)
                return RTErrInfoSet(pErrInfo, VERR_CR_SPC_MONIKER_BAD_DATA,
                                    "SpcIndirectDataContent...pMoniker->pData is NULL.");

            uint32_t cPageHashTabs = 0;
            for (uint32_t i = 0; i < pObj->u.pData->cItems; i++)
            {
                PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttr = &pObj->u.pData->paItems[i];
                if (   RTAsn1ObjId_CompareWithString(&pAttr->Type, RTCRSPC_PE_IMAGE_HASHES_V1_OID) == 0
                    || RTAsn1ObjId_CompareWithString(&pAttr->Type, RTCRSPC_PE_IMAGE_HASHES_V2_OID) == 0 )
                {
                    cPageHashTabs++;
                    AssertPtr(pAttr->u.pPageHashes->pData);
                }
                else
                    return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_PEIMAGE_UNKNOWN_ATTRIBUTE,
                                         "SpcIndirectDataContent...MonikerT1 unknown attribute %u: %s.",
                                         i, pAttr->Type.szObjId);
            }
            if (cPageHashTabs > 0)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_PEIMAGE_MULTIPLE_HASH_TABS,
                                     "SpcIndirectDataContent...MonikerT1 multiple page hash attributes (%u).", cPageHashTabs);

        }
        else if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_FILE
                 && RTCrSpcString_IsPresent(&pIndData->Data.uValue.pPeImage->T0.File.u.pT2->File) )
        {
            /* Could check for "<<<Obsolete>>>" here, but it's really irrelevant. */
        }
        else if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_URL
                 && RTAsn1String_IsPresent(pIndData->Data.uValue.pPeImage->T0.File.u.pUrl) )
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_URL_UNEXPECTED,
                                "SpcIndirectDataContent.Data.uValue.pPeImage->File is an URL, expected object Moniker or File.");
        else
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_NO_CONTENT,
                                "SpcIndirectDataContent.Data.uValue.pPeImage->File has no content");
    }

    return VINF_SUCCESS;
}
コード例 #28
0
ファイル: pkcs7-verify.cpp プロジェクト: jeppeter/vbox
RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
                                      RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
                                      PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
                                      PRTERRINFO pErrInfo)
{
    /*
     * Check the input.
     */
    if (pfnVerifyCert)
        AssertPtrReturn(pfnVerifyCert, VERR_INVALID_POINTER);
    else
        pfnVerifyCert = RTCrPkcs7VerifyCertCallbackDefault;

    if (!RTCrPkcs7ContentInfo_IsSignedData(pContentInfo))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NOT_SIGNED_DATA, "Not PKCS #7 SignedData.");
    PCRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData;
    int rc = RTCrPkcs7SignedData_CheckSanity(pSignedData, 0, pErrInfo, "");
    if (RT_FAILURE(rc))
        return rc;

    /*
     * Hash the content info.
     */
    /* Exactly what the content is, for some stupid reason unnecessarily
       complicated.  Figure it out here as we'll need it for the OpenSSL code
       path as well. */
    void const *pvContent = pSignedData->ContentInfo.Content.Asn1Core.uData.pv;
    uint32_t    cbContent = pSignedData->ContentInfo.Content.Asn1Core.cb;
    if (pSignedData->ContentInfo.Content.pEncapsulated)
    {
        pvContent = pSignedData->ContentInfo.Content.pEncapsulated->uData.pv;
        cbContent = pSignedData->ContentInfo.Content.pEncapsulated->cb;
    }

    /* Check that there aren't too many or too few hash algorithms for our
       implementation and purposes. */
    RTCRDIGEST     ahDigests[2];
    uint32_t const cDigests = pSignedData->DigestAlgorithms.cItems;
    if (!cDigests) /** @todo we might have to support this... */
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS, "No digest algorithms");

    if (cDigests > RT_ELEMENTS(ahDigests))
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_TOO_MANY_DIGEST_ALGORITHMS,
                             "Too many digest algorithm: cAlgorithms=%u", cDigests);

    /* Create the message digest calculators. */
    rc = VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS;
    uint32_t i;
    for (i = 0; i < cDigests; i++)
    {
        rc = RTCrDigestCreateByObjId(&ahDigests[i], &pSignedData->DigestAlgorithms.paItems[i].Algorithm);
        if (RT_FAILURE(rc))
        {
            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
                               pSignedData->DigestAlgorithms.paItems[i].Algorithm.szObjId, rc);
            break;
        }
    }
    if (RT_SUCCESS(rc))
    {
        /* Hash the content. */
        for (i = 0; i < cDigests && RT_SUCCESS(rc); i++)
        {
            rc = RTCrDigestUpdate(ahDigests[i], pvContent, cbContent);
            if (RT_SUCCESS(rc))
                rc = RTCrDigestFinal(ahDigests[i], NULL, 0);
        }
        if (RT_SUCCESS(rc))
        {
            /*
             * Validate the signed infos.
             */
            uint32_t fPrimaryVccFlags = !(fFlags & RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING)
                                      ? RTCRPKCS7VCC_F_SIGNED_DATA : RTCRPKCS7VCC_F_TIMESTAMP;
            rc = VERR_CR_PKCS7_NO_SIGNER_INFOS;
            for (i = 0; i < pSignedData->SignerInfos.cItems; i++)
            {
                PCRTCRPKCS7SIGNERINFO   pSignerInfo = &pSignedData->SignerInfos.paItems[i];
                RTCRDIGEST              hThisDigest = NIL_RTCRDIGEST; /* (gcc maybe incredible stupid.) */
                rc = rtCrPkcs7VerifyFindDigest(&hThisDigest, pSignedData, pSignerInfo, ahDigests, pErrInfo);
                if (RT_FAILURE(rc))
                    break;

                /*
                 * See if we can find a trusted signing time.
                 * (Note that while it would make sense splitting up this function,
                 * we need to carry a lot of arguments around, so better not.)
                 */
                bool                    fDone              = false;
                PCRTCRPKCS7SIGNERINFO   pSigningTimeSigner = NULL;
                PCRTASN1TIME            pSignedTime;
                while (   !fDone
                       && (pSignedTime = RTCrPkcs7SignerInfo_GetSigningTime(pSignerInfo, &pSigningTimeSigner)) != NULL)
                {
                    RTTIMESPEC ThisValidationTime;
                    if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
                    {
                        if (pSigningTimeSigner == pSignerInfo)
                        {
                            if (fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY)
                                continue;
                            rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags,
                                                           hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
                                                           pfnVerifyCert, fPrimaryVccFlags | RTCRPKCS7VCC_F_TIMESTAMP,
                                                           pvUser, pErrInfo);
                        }
                        else
                        {
                            rc = VINF_SUCCESS;
                            if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED))
                                rc = rtCrPkcs7VerifyCounterSignerInfo(pSigningTimeSigner, pSignerInfo, pSignedData, fFlags,
                                                                      hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
                                                                      pfnVerifyCert, RTCRPKCS7VCC_F_TIMESTAMP, pvUser, pErrInfo);
                            if (RT_SUCCESS(rc))
                                rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
                                                               hTrustedCerts, &ThisValidationTime,
                                                               pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
                        }
                        fDone = RT_SUCCESS(rc)
                             || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT);
                    }
                    else
                    {
                        rc = RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_3, "RTTimeImplode failed");
                        fDone = true;
                    }
                }

                /*
                 * If not luck, check for microsoft timestamp counter signatures.
                 */
                if (!fDone && !(fFlags & RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP))
                {
                    PCRTCRPKCS7CONTENTINFO pSignedTimestamp = NULL;
                    pSignedTime = RTCrPkcs7SignerInfo_GetMsTimestamp(pSignerInfo, &pSignedTimestamp);
                    if (pSignedTime)
                    {
                        RTTIMESPEC ThisValidationTime;
                        if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
                        {
                            rc = VINF_SUCCESS;
                            if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED))
                                rc = RTCrPkcs7VerifySignedData(pSignedTimestamp,
                                                               fFlags | RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP
                                                               | RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING,
                                                               hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
                                                               pfnVerifyCert, pvUser, pErrInfo);

                            if (RT_SUCCESS(rc))
                                rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
                                                               hTrustedCerts, &ThisValidationTime,
                                                               pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
                            fDone = RT_SUCCESS(rc)
                                 || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT);
                        }
                        else
                        {
                            rc = RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_3, "RTTimeImplode failed");
                            fDone = true;
                        }

                    }
                }

                /*
                 * No valid signing time found, use the one specified instead.
                 */
                if (!fDone)
                    rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts, hTrustedCerts,
                                                   pValidationTime, pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
                RTCrDigestRelease(hThisDigest);
                if (RT_FAILURE(rc))
                    break;
            }
        }
        else
            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
                               "Hashing content failed unexpectedly (i=%u): %Rrc", i, rc);

        /* Clean up digests. */
        i = cDigests;
    }
    while (i-- > 0)
    {
        int rc2 = RTCrDigestRelease(ahDigests[i]);
        AssertRC(rc2);
    }


#ifdef IPRT_WITH_OPENSSL
    /*
     * Verify using OpenSSL and combine the results (should be identical).
     */
    /** @todo figure out how to verify MS timstamp signatures using OpenSSL. */
    if (fFlags & RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING)
        return rc;
    int rcOssl = rtCrPkcs7VerifySignedDataUsingOpenSsl(pContentInfo, fFlags, hAdditionalCerts, hTrustedCerts,
                                                       pvContent, cbContent, RT_SUCCESS(rc) ? pErrInfo : NULL);
    if (RT_SUCCESS(rcOssl) && RT_SUCCESS(rc))
        return rc;
//    AssertMsg(RT_FAILURE_NP(rcOssl) && RT_FAILURE_NP(rc), ("%Rrc, %Rrc\n", rcOssl, rc));
    if (RT_FAILURE(rc))
        return rc;
    return rcOssl;
#else
    return rc;
#endif
}