VirtualBox

Ignore:
Timestamp:
Oct 12, 2020 11:59:53 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
140868
Message:

SUPHardNt,IPRT: If there are nested signatures (i.e. more than one signature), don't get grumpy if there are time or cert path issues with some of them, as long as one or more checks out perfectly. (Mind, all the signature data must check out, it's just the cert path or signing time we're relaxing here.) ticketref:19743 bugref:3103

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r85121 r86549  
    216216#ifndef IPRT_WITHOUT_LDR_VERIFY
    217217/**
    218  * Parsed signature data.
    219  */
    220 typedef struct RTLDRPESIGNATURE
     218 * Parsed data for one signature.
     219 */
     220typedef struct RTLDRPESIGNATUREONE
    221221{
    222222    /** The outer content info wrapper. */
    223     RTCRPKCS7CONTENTINFO        ContentInfo;
     223    PRTCRPKCS7CONTENTINFO       pContentInfo;
    224224    /** Pointer to the decoded SignedData inside the ContentInfo member. */
    225225    PRTCRPKCS7SIGNEDDATA        pSignedData;
     
    228228    /** The digest type employed by the signature. */
    229229    RTDIGESTTYPE                enmDigest;
    230 
     230    /** Set if we've already validate the image hash. */
     231    bool                        fValidatedImageHash;
     232    /** The signature number. */
     233    uint16_t                    iSignature;
     234    /** Hash result. */
     235    RTLDRPEHASHRESUNION         HashRes;
     236} RTLDRPESIGNATUREONE;
     237/** Pointer to the parsed data of one signature. */
     238typedef RTLDRPESIGNATUREONE *PRTLDRPESIGNATUREONE;
     239
     240/**
     241 * Parsed signature data.
     242 */
     243typedef struct RTLDRPESIGNATURE
     244{
    231245    /** Pointer to the raw signatures.  This is allocated in the continuation of
    232246     * this structure to keep things simple.  The size is given by  the security
    233247     * export directory. */
    234248    WIN_CERTIFICATE const      *pRawData;
    235 
     249    /** The outer content info wrapper (primary signature). */
     250    RTCRPKCS7CONTENTINFO        PrimaryContentInfo;
     251    /** The info for the primary signature. */
     252    RTLDRPESIGNATUREONE         Primary;
     253    /** Number of nested signatures (zero if none). */
     254    uint16_t                    cNested;
     255    /** Pointer to an array of nested signatures (NULL if none). */
     256    PRTLDRPESIGNATUREONE        paNested;
    236257    /** Hash scratch data. */
    237258    RTLDRPEHASHCTXUNION         HashCtx;
    238     /** Hash result. */
    239     RTLDRPEHASHRESUNION         HashRes;
    240259} RTLDRPESIGNATURE;
    241260/** Pointed to SigneData parsing stat and output. */
     
    25232542{
    25242543    RT_NOREF_PV(pModPe);
    2525     RTCrPkcs7ContentInfo_Delete(&pSignature->ContentInfo);
     2544    RTCrPkcs7ContentInfo_Delete(&pSignature->PrimaryContentInfo);
     2545    if (pSignature->paNested > 0)
     2546    {
     2547        RTMemTmpFree(pSignature->paNested);
     2548        pSignature->paNested = NULL;
     2549    }
    25262550    RTMemTmpFree(pSignature);
     2551}
     2552
     2553
     2554/**
     2555 * Handles nested signatures.
     2556 *
     2557 * @returns IPRT status code.
     2558 * @param   pSignature          The signature status structure.  Returns with
     2559 *                              cNested = 0 and paNested = NULL if no nested
     2560 *                              signatures.
     2561 * @param   pErrInfo            Where to return extended error info (optional).
     2562 */
     2563static int rtldrPE_VerifySignatureDecodeNested(PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo)
     2564{
     2565    Assert(pSignature->cNested == 0);
     2566    Assert(pSignature->paNested == NULL);
     2567
     2568    /*
     2569     * Count nested signatures.
     2570     */
     2571    uint32_t cNested = 0;
     2572    for (uint32_t iSignerInfo = 0; iSignerInfo < pSignature->Primary.pSignedData->SignerInfos.cItems; iSignerInfo++)
     2573    {
     2574        PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignature->Primary.pSignedData->SignerInfos.papItems[iSignerInfo];
     2575        for (uint32_t iAttrib = 0; iAttrib < pSignerInfo->UnauthenticatedAttributes.cItems; iAttrib++)
     2576        {
     2577            PCRTCRPKCS7ATTRIBUTE pAttrib = pSignerInfo->UnauthenticatedAttributes.papItems[iAttrib];
     2578            if (pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE)
     2579            {
     2580                Assert(pAttrib->uValues.pContentInfos);
     2581                cNested += pAttrib->uValues.pContentInfos->cItems;
     2582            }
     2583        }
     2584    }
     2585    if (!cNested)
     2586        return VINF_SUCCESS;
     2587
     2588    /*
     2589     * Allocate and populate the info structures.
     2590     */
     2591    pSignature->paNested = (PRTLDRPESIGNATUREONE)RTMemTmpAllocZ(sizeof(pSignature->paNested[0]) * cNested);
     2592    if (!pSignature->paNested)
     2593        return RTErrInfoSetF(pErrInfo, VERR_NO_TMP_MEMORY, "Failed to allocate space for %u nested signatures", cNested);
     2594    pSignature->cNested = cNested;
     2595
     2596    cNested = 0;
     2597    for (uint32_t iSignerInfo = 0; iSignerInfo < pSignature->Primary.pSignedData->SignerInfos.cItems; iSignerInfo++)
     2598    {
     2599        PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignature->Primary.pSignedData->SignerInfos.papItems[iSignerInfo];
     2600        for (uint32_t iAttrib = 0; iAttrib < pSignerInfo->UnauthenticatedAttributes.cItems; iAttrib++)
     2601        {
     2602            PCRTCRPKCS7ATTRIBUTE pAttrib = pSignerInfo->UnauthenticatedAttributes.papItems[iAttrib];
     2603            if (pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE)
     2604            {
     2605                for (uint32_t iItem = 0; iItem < pAttrib->uValues.pContentInfos->cItems; iItem++, cNested++)
     2606                {
     2607                    PRTLDRPESIGNATUREONE  pInfo        = &pSignature->paNested[cNested];
     2608                    PRTCRPKCS7CONTENTINFO pContentInfo = pAttrib->uValues.pContentInfos->papItems[iItem];
     2609                    pInfo->pContentInfo = pContentInfo;
     2610                    pInfo->iSignature   = cNested;
     2611
     2612                    if (RTCrPkcs7ContentInfo_IsSignedData(pInfo->pContentInfo))
     2613                    { /* likely */ }
     2614                    else
     2615                        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/
     2616                                             "Nested#%u: PKCS#7 is not 'signedData': %s", cNested, pInfo->pContentInfo->ContentType.szObjId);
     2617                    PRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData;
     2618                    pInfo->pSignedData = pSignedData;
     2619
     2620                    /*
     2621                     * Check the authenticode bits.
     2622                     */
     2623                    if (!strcmp(pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))
     2624                    { /* likely */ }
     2625                    else
     2626                        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID,
     2627                                             "Nested#%u: Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)",
     2628                                             cNested, pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);
     2629                    pInfo->pIndData = pSignedData->ContentInfo.u.pIndirectDataContent;
     2630                    Assert(pInfo->pIndData);
     2631
     2632                    /*
     2633                     * Check that things add up.
     2634                     */
     2635                    int rc = RTCrPkcs7SignedData_CheckSanity(pSignedData,
     2636                                                             RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE
     2637                                                             | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH
     2638                                                             | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT,
     2639                                                             pErrInfo, "SD");
     2640                    if (RT_SUCCESS(rc))
     2641                        rc = RTCrSpcIndirectDataContent_CheckSanityEx(pInfo->pIndData,
     2642                                                                      pSignedData,
     2643                                                                      RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH,
     2644                                                                      pErrInfo);
     2645                    if (RT_SUCCESS(rc))
     2646                    {
     2647                        PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pInfo->pIndData->DigestInfo.DigestAlgorithm;
     2648                        pInfo->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm);
     2649                        AssertReturn(pInfo->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */
     2650                    }
     2651                    else
     2652                        return rc;
     2653                }
     2654            }
     2655        }
     2656    }
     2657
     2658    return VINF_SUCCESS;
    25272659}
    25282660
     
    25522684                            "WinCert");
    25532685
    2554     int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pSignature->ContentInfo, "CI");
     2686    PRTLDRPESIGNATUREONE pInfo = &pSignature->Primary;
     2687    pInfo->pContentInfo = &pSignature->PrimaryContentInfo;
     2688    int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, pInfo->pContentInfo, "CI");
    25552689    if (RT_SUCCESS(rc))
    25562690    {
    2557         if (RTCrPkcs7ContentInfo_IsSignedData(&pSignature->ContentInfo))
    2558         {
    2559             pSignature->pSignedData = pSignature->ContentInfo.u.pSignedData;
     2691        if (RTCrPkcs7ContentInfo_IsSignedData(pInfo->pContentInfo))
     2692        {
     2693            pInfo->pSignedData = pInfo->pContentInfo->u.pSignedData;
    25602694
    25612695            /*
    25622696             * Decode the authenticode bits.
    25632697             */
    2564             if (!strcmp(pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))
    2565             {
    2566                 pSignature->pIndData = pSignature->pSignedData->ContentInfo.u.pIndirectDataContent;
    2567                 Assert(pSignature->pIndData);
     2698            if (!strcmp(pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))
     2699            {
     2700                pInfo->pIndData = pInfo->pSignedData->ContentInfo.u.pIndirectDataContent;
     2701                Assert(pInfo->pIndData);
    25682702
    25692703                /*
    25702704                 * Check that things add up.
    25712705                 */
     2706                rc = RTCrPkcs7SignedData_CheckSanity(pInfo->pSignedData,
     2707                                                     RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE
     2708                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH
     2709                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT,
     2710                                                     pErrInfo, "SD");
    25722711                if (RT_SUCCESS(rc))
    2573                     rc = RTCrPkcs7SignedData_CheckSanity(pSignature->pSignedData,
    2574                                                          RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE
    2575                                                          | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH
    2576                                                          | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT,
    2577                                                          pErrInfo, "SD");
    2578                 if (RT_SUCCESS(rc))
    2579                     rc = RTCrSpcIndirectDataContent_CheckSanityEx(pSignature->pIndData,
    2580                                                                   pSignature->pSignedData,
     2712                    rc = RTCrSpcIndirectDataContent_CheckSanityEx(pInfo->pIndData,
     2713                                                                  pInfo->pSignedData,
    25812714                                                                  RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH,
    25822715                                                                  pErrInfo);
    25832716                if (RT_SUCCESS(rc))
    25842717                {
    2585                     PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pSignature->pIndData->DigestInfo.DigestAlgorithm;
    2586                     pSignature->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm);
    2587                     AssertReturn(pSignature->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */
     2718                    PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pInfo->pIndData->DigestInfo.DigestAlgorithm;
     2719                    pInfo->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm);
     2720                    AssertReturn(pInfo->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */
     2721
     2722                    /*
     2723                     * Deal with nested signatures.
     2724                     */
     2725                    rc = rtldrPE_VerifySignatureDecodeNested(pSignature, pErrInfo);
    25882726                }
    25892727            }
     
    25912729                rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID,
    25922730                                   "Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)",
    2593                                    pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);
     2731                                   pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);
    25942732        }
    25952733        else
    25962734            rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/
    2597                                "PKCS#7 is not 'signedData': %s", pSignature->ContentInfo.ContentType.szObjId);
     2735                               "PKCS#7 is not 'signedData': %s", pInfo->pContentInfo->ContentType.szObjId);
    25982736    }
    25992737    return rc;
     
    26012739
    26022740
     2741
    26032742static int rtldrPE_VerifyAllPageHashes(PRTLDRMODPE pModPe, PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib, RTDIGESTTYPE enmDigest,
    2604                                        void *pvScratch, size_t cbScratch, PRTERRINFO pErrInfo)
     2743                                       void *pvScratch, size_t cbScratch, uint32_t iSignature, PRTERRINFO pErrInfo)
    26052744{
    26062745    AssertReturn(cbScratch >= _4K, VERR_INTERNAL_ERROR_3);
     
    26182757    if (cPages * (cbHash + 4) != pAttrib->u.pPageHashes->RawData.Asn1Core.cb)
    26192758        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_SIZE_OVERFLOW,
    2620                              "Page hashes size issue: cb=%#x cbHash=%#x",
    2621                              pAttrib->u.pPageHashes->RawData.Asn1Core.cb, cbHash);
     2759                             "Signature #%u - Page hashes size issue in: cb=%#x cbHash=%#x",
     2760                             iSignature, pAttrib->u.pPageHashes->RawData.Asn1Core.cb, cbHash);
    26222761
    26232762    /*
     
    26402779        if (RT_UNLIKELY(offPageInFile >= SpecialPlaces.cbToHash))
    26412780            return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG,
    2642                                  "Page hash entry #%u is beyond the signature table start: %#x, %#x",
    2643                                  iPage, offPageInFile, SpecialPlaces.cbToHash);
     2781                                 "Signature #%u - Page hash entry #%u is beyond the signature table start: %#x, %#x",
     2782                                 iSignature, iPage, offPageInFile, SpecialPlaces.cbToHash);
    26442783        if (RT_UNLIKELY(offPageInFile < offPrev))
    26452784            return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_NOT_STRICTLY_SORTED,
    2646                                  "Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n",
    2647                                  iPage, offPageInFile, offPrev);
     2785                                 "Signature #%u - Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n",
     2786                                 iSignature, iPage, offPageInFile, offPrev);
    26482787
    26492788#ifdef COMPLICATED_AND_WRONG
     
    26662805                else
    26672806                    return RTErrInfoSetF(pErrInfo, VERR_PAGE_HASH_TAB_HASHES_NON_SECTION_DATA,
    2668                                          "Page hash entry #%u isn't in any section: %#x", iPage, offPageInFile);
     2807                                         "Signature #%u - Page hash entry #%u isn't in any section: %#x",
     2808                                         iSignature, iPage, offPageInFile);
    26692809            }
    26702810        }
     
    27102850            if (RT_FAILURE(rc))
    27112851                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_READ_ERROR_HASH,
    2712                                      "Page hash read error at %#x: %Rrc (cbScratchRead=%#zx)",
    2713                                      offScratchRead, rc, cbScratchRead);
     2852                                     "Signature #%u - Page hash read error at %#x: %Rrc (cbScratchRead=%#zx)",
     2853                                     iSignature, offScratchRead, rc, cbScratchRead);
    27142854        }
    27152855
     
    27782918        if (memcmp(pbHashTab, &HashRes, cbHash) != 0)
    27792919            return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_MISMATCH,
    2780                                  "Page hash failed for page #%u, @%#x, %#x bytes: %.*Rhxs != %.*Rhxs",
    2781                                  iPage, offPageInFile, cbPageInFile, (size_t)cbHash, pbHashTab, (size_t)cbHash, &HashRes);
     2920                                 "Signature #%u - Page hash failed for page #%u, @%#x, %#x bytes: %.*Rhxs != %.*Rhxs",
     2921                                 iSignature, iPage, offPageInFile, cbPageInFile, (size_t)cbHash, pbHashTab,
     2922                                 (size_t)cbHash, &HashRes);
    27822923        pbHashTab += cbHash;
    27832924        offPrev = offPageInFile;
     
    27892930    if (!ASMMemIsZero(pbHashTab + 4, cbHash))
    27902931        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG,
    2791                              "Maltform final page hash table entry: #%u %#010x %.*Rhxs",
    2792                              cPages - 1, RT_MAKE_U32_FROM_U8(pbHashTab[0], pbHashTab[1], pbHashTab[2], pbHashTab[3]),
     2932                             "Signature #%u - Malformed final page hash table entry: #%u %#010x %.*Rhxs",
     2933                             iSignature, cPages - 1, RT_MAKE_U32_FROM_U8(pbHashTab[0], pbHashTab[1], pbHashTab[2], pbHashTab[3]),
    27932934                             (size_t)cbHash, pbHashTab + 4);
    27942935    return VINF_SUCCESS;
     2936}
     2937
     2938
     2939static int rtldrPE_VerifySignatureValidateOnePageHashes(PRTLDRMODPE pModPe, PRTLDRPESIGNATUREONE pInfo,
     2940                                                        void *pvScratch, uint32_t cbScratch, PRTERRINFO pErrInfo)
     2941{
     2942    /*
     2943     * Compare the page hashes if present.
     2944     *
     2945     * Seems the difference between V1 and V2 page hash attributes is
     2946     * that v1 uses SHA-1 while v2 uses SHA-256. The data structures
     2947     * seems to be identical otherwise.  Initially we assumed the digest
     2948     * algorithm was supposed to be RTCRSPCINDIRECTDATACONTENT::DigestInfo,
     2949     * i.e. the same as for the whole image hash.  The initial approach
     2950     * worked just fine, but this makes more sense.
     2951     *
     2952     * (See also comments in osslsigncode.c (google it).)
     2953     */
     2954    PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib;
     2955    /* V2 - SHA-256: */
     2956    pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pInfo->pIndData,
     2957                                                             RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2);
     2958    if (pAttrib)
     2959        return rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA256, pvScratch, cbScratch,
     2960                                           pInfo->iSignature + 1, pErrInfo);
     2961
     2962    /* V1 - SHA-1: */
     2963    pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pInfo->pIndData,
     2964                                                             RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1);
     2965    if (pAttrib)
     2966        return rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA1, pvScratch, cbScratch,
     2967                                           pInfo->iSignature + 1, pErrInfo);
     2968
     2969    /* No page hashes: */
     2970    return VINF_SUCCESS;
     2971}
     2972
     2973
     2974static int rtldrPE_VerifySignatureValidateOneImageHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature,
     2975                                                       PRTLDRPESIGNATUREONE pInfo, void *pvScratch, uint32_t cbScratch,
     2976                                                       PRTERRINFO pErrInfo)
     2977{
     2978    /*
     2979     * Assert sanity.
     2980     */
     2981    AssertReturn(pInfo->enmDigest > RTDIGESTTYPE_INVALID && pInfo->enmDigest < RTDIGESTTYPE_END, VERR_INTERNAL_ERROR_4);
     2982    AssertPtrReturn(pInfo->pIndData, VERR_INTERNAL_ERROR_5);
     2983    AssertReturn(RTASN1CORE_IS_PRESENT(&pInfo->pIndData->DigestInfo.Digest.Asn1Core), VERR_INTERNAL_ERROR_5);
     2984    AssertPtrReturn(pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, VERR_INTERNAL_ERROR_5);
     2985
     2986    /*
     2987     * Skip it if we've already verified it.
     2988     */
     2989    if (pInfo->fValidatedImageHash)
     2990        return VINF_SUCCESS;
     2991
     2992    /*
     2993     * Calculate it.
     2994     */
     2995    uint32_t const cbHash = rtLdrPE_HashGetHashSize(pInfo->enmDigest);
     2996    AssertReturn(pInfo->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash, VERR_INTERNAL_ERROR_5);
     2997
     2998    int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, pInfo->enmDigest,
     2999                                     &pSignature->HashCtx, &pInfo->HashRes, pErrInfo);
     3000    if (RT_SUCCESS(rc))
     3001    {
     3002        pInfo->fValidatedImageHash = true;
     3003        if (memcmp(&pInfo->HashRes, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash) == 0)
     3004        {
     3005            /*
     3006             * Verify other signatures with the same digest type.
     3007             */
     3008            RTLDRPEHASHRESUNION const * const pHashRes = &pInfo->HashRes;
     3009            for (uint32_t i = 0; i < pSignature->cNested; i++)
     3010            {
     3011                pInfo = &pSignature->paNested[i]; /* Note! pInfo changes! */
     3012                if (   !pInfo->fValidatedImageHash
     3013                    && pInfo->enmDigest == pInfo->enmDigest
     3014                    /* paranoia from the top of this function: */
     3015                    && pInfo->pIndData
     3016                    && RTASN1CORE_IS_PRESENT(&pInfo->pIndData->DigestInfo.Digest.Asn1Core)
     3017                    && pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv
     3018                    && pInfo->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash)
     3019                {
     3020                    pInfo->fValidatedImageHash = true;
     3021                    if (memcmp(pHashRes, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash) != 0)
     3022                    {
     3023                        rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH,
     3024                                           "Full image signature #%u mismatch: %.*Rhxs, expected %.*Rhxs", pInfo->iSignature + 1,
     3025                                           cbHash, pHashRes,
     3026                                           cbHash, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv);
     3027                        break;
     3028                    }
     3029                }
     3030            }
     3031        }
     3032        else
     3033            rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH,
     3034                               "Full image signature #%u mismatch: %.*Rhxs, expected %.*Rhxs", pInfo->iSignature + 1,
     3035                               cbHash, &pInfo->HashRes,
     3036                               cbHash, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv);
     3037    }
     3038    return rc;
    27953039}
    27963040
     
    28063050static int rtldrPE_VerifySignatureValidateHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo)
    28073051{
    2808     AssertReturn(pSignature->enmDigest > RTDIGESTTYPE_INVALID && pSignature->enmDigest < RTDIGESTTYPE_END, VERR_INTERNAL_ERROR_4);
    2809     AssertPtrReturn(pSignature->pIndData, VERR_INTERNAL_ERROR_5);
    2810     AssertReturn(RTASN1CORE_IS_PRESENT(&pSignature->pIndData->DigestInfo.Digest.Asn1Core), VERR_INTERNAL_ERROR_5);
    2811     AssertPtrReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, VERR_INTERNAL_ERROR_5);
    2812 
    2813     uint32_t const cbHash = rtLdrPE_HashGetHashSize(pSignature->enmDigest);
    2814     AssertReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash, VERR_INTERNAL_ERROR_5);
    2815 
    28163052    /*
    28173053     * Allocate a temporary memory buffer.
     
    28203056     *       heap fragmentation.
    28213057     */
    2822 #ifdef IN_RING0
     3058# ifdef IN_RING0
    28233059    uint32_t    cbScratch = _256K - _4K;
    2824 #else
     3060# else
    28253061    uint32_t    cbScratch = _1M;
    2826 #endif
     3062# endif
    28273063    void       *pvScratch = RTMemTmpAlloc(cbScratch);
    28283064    if (!pvScratch)
     
    28353071
    28363072    /*
    2837      * Calculate and compare the full image hash.
    2838      */
    2839     int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, pSignature->enmDigest,
    2840                                      &pSignature->HashCtx, &pSignature->HashRes, pErrInfo);
     3073     * Verify signatures.
     3074     */
     3075    /* Image hashes: */
     3076    int rc = rtldrPE_VerifySignatureValidateOneImageHash(pModPe, pSignature, &pSignature->Primary,
     3077                                                         pvScratch, cbScratch, pErrInfo);
     3078    for (unsigned i = 0; i < pSignature->cNested && RT_SUCCESS(rc); i++)
     3079        rc = rtldrPE_VerifySignatureValidateOneImageHash(pModPe, pSignature, &pSignature->paNested[i],
     3080                                                         pvScratch, cbScratch, pErrInfo);
     3081
     3082    /* Page hashes: */
    28413083    if (RT_SUCCESS(rc))
    28423084    {
    2843         if (!memcmp(&pSignature->HashRes, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash))
    2844         {
    2845             /*
    2846              * Compare the page hashes if present.
    2847              *
    2848              * Seems the difference between V1 and V2 page hash attributes is
    2849              * that v1 uses SHA-1 while v2 uses SHA-256. The data structures
    2850              * seems to be identical otherwise.  Initially we assumed the digest
    2851              * algorithm was supposed to be RTCRSPCINDIRECTDATACONTENT::DigestInfo,
    2852              * i.e. the same as for the whole image hash.  The initial approach
    2853              * worked just fine, but this makes more sense.
    2854              *
    2855              * (See also comments in osslsigncode.c (google it).)
    2856              */
    2857             PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib;
    2858             pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pSignature->pIndData,
    2859                                                                      RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2);
    2860             if (pAttrib)
    2861                 rc = rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA256, pvScratch, cbScratch, pErrInfo);
    2862             else
    2863             {
    2864                 pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pSignature->pIndData,
    2865                                                                          RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1);
    2866                 if (pAttrib)
    2867                     rc = rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA1, pvScratch, cbScratch, pErrInfo);
    2868             }
    2869         }
    2870         else
    2871             rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH,
    2872                                "Full image signature mismatch: %.*Rhxs, expected %.*Rhxs",
    2873                                cbHash, &pSignature->HashRes,
    2874                                cbHash, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv);
    2875     }
    2876 
     3085        rc = rtldrPE_VerifySignatureValidateOnePageHashes(pModPe, &pSignature->Primary, pvScratch, cbScratch, pErrInfo);
     3086        for (unsigned i = 0; i < pSignature->cNested && RT_SUCCESS(rc); i++)
     3087            rc = rtldrPE_VerifySignatureValidateOnePageHashes(pModPe, &pSignature->paNested[i], pvScratch, cbScratch, pErrInfo);
     3088    }
     3089
     3090    /*
     3091     * Ditch the scratch buffer.
     3092     */
    28773093    RTMemTmpFree(pvScratch);
    28783094    return rc;
     
    29013117            if (RT_SUCCESS(rc))
    29023118            {
    2903                 rc = pfnCallback(&pModPe->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA,
    2904                                  &pSignature->ContentInfo, sizeof(pSignature->ContentInfo),
    2905                                  NULL /*pvExternalData*/, 0 /*cbExternalData*/,
    2906                                  pErrInfo, pvUser);
     3119                /*
     3120                 * Work the callback.
     3121                 */
     3122                /* The primary signature: */
     3123                RTLDRSIGNATUREINFO Info;
     3124                Info.iSignature     = 0;
     3125                Info.cSignatures    = (uint16_t)(1 + pSignature->cNested);
     3126                Info.enmType        = RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA;
     3127                Info.pvSignature    = pSignature->Primary.pContentInfo;
     3128                Info.cbSignature    = sizeof(*pSignature->Primary.pContentInfo);
     3129                Info.pvExternalData = NULL;
     3130                Info.cbExternalData = 0;
     3131                rc = pfnCallback(&pModPe->Core, &Info, pErrInfo, pvUser);
     3132
     3133                /* The nested signatures: */
     3134                for (uint32_t iNested = 0; iNested < pSignature->cNested && rc == VINF_SUCCESS; iNested++)
     3135                {
     3136                    Info.iSignature     = (uint16_t)(1 + iNested);
     3137                    Info.cSignatures    = (uint16_t)(1 + pSignature->cNested);
     3138                    Info.enmType        = RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA;
     3139                    Info.pvSignature    = pSignature->paNested[iNested].pContentInfo;
     3140                    Info.cbSignature    = sizeof(*pSignature->paNested[iNested].pContentInfo);
     3141                    Info.pvExternalData = NULL;
     3142                    Info.cbExternalData = 0;
     3143                    rc = pfnCallback(&pModPe->Core, &Info, pErrInfo, pvUser);
     3144                }
    29073145            }
    29083146            rtldrPE_VerifySignatureDestroy(pModPe, pSignature);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette