Changeset 86549 in vbox for trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
- Timestamp:
- Oct 12, 2020 11:59:53 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 140868
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
r85121 r86549 216 216 #ifndef IPRT_WITHOUT_LDR_VERIFY 217 217 /** 218 * Parsed signature data.219 */ 220 typedef struct RTLDRPESIGNATURE 218 * Parsed data for one signature. 219 */ 220 typedef struct RTLDRPESIGNATUREONE 221 221 { 222 222 /** The outer content info wrapper. */ 223 RTCRPKCS7CONTENTINFOContentInfo;223 PRTCRPKCS7CONTENTINFO pContentInfo; 224 224 /** Pointer to the decoded SignedData inside the ContentInfo member. */ 225 225 PRTCRPKCS7SIGNEDDATA pSignedData; … … 228 228 /** The digest type employed by the signature. */ 229 229 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. */ 238 typedef RTLDRPESIGNATUREONE *PRTLDRPESIGNATUREONE; 239 240 /** 241 * Parsed signature data. 242 */ 243 typedef struct RTLDRPESIGNATURE 244 { 231 245 /** Pointer to the raw signatures. This is allocated in the continuation of 232 246 * this structure to keep things simple. The size is given by the security 233 247 * export directory. */ 234 248 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; 236 257 /** Hash scratch data. */ 237 258 RTLDRPEHASHCTXUNION HashCtx; 238 /** Hash result. */239 RTLDRPEHASHRESUNION HashRes;240 259 } RTLDRPESIGNATURE; 241 260 /** Pointed to SigneData parsing stat and output. */ … … 2523 2542 { 2524 2543 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 } 2526 2550 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 */ 2563 static 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; 2527 2659 } 2528 2660 … … 2552 2684 "WinCert"); 2553 2685 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"); 2555 2689 if (RT_SUCCESS(rc)) 2556 2690 { 2557 if (RTCrPkcs7ContentInfo_IsSignedData( &pSignature->ContentInfo))2558 { 2559 p Signature->pSignedData = pSignature->ContentInfo.u.pSignedData;2691 if (RTCrPkcs7ContentInfo_IsSignedData(pInfo->pContentInfo)) 2692 { 2693 pInfo->pSignedData = pInfo->pContentInfo->u.pSignedData; 2560 2694 2561 2695 /* 2562 2696 * Decode the authenticode bits. 2563 2697 */ 2564 if (!strcmp(p Signature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))2565 { 2566 p Signature->pIndData = pSignature->pSignedData->ContentInfo.u.pIndirectDataContent;2567 Assert(p Signature->pIndData);2698 if (!strcmp(pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID)) 2699 { 2700 pInfo->pIndData = pInfo->pSignedData->ContentInfo.u.pIndirectDataContent; 2701 Assert(pInfo->pIndData); 2568 2702 2569 2703 /* 2570 2704 * Check that things add up. 2571 2705 */ 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"); 2572 2711 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, 2581 2714 RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH, 2582 2715 pErrInfo); 2583 2716 if (RT_SUCCESS(rc)) 2584 2717 { 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); 2588 2726 } 2589 2727 } … … 2591 2729 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, 2592 2730 "Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)", 2593 p Signature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);2731 pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 2594 2732 } 2595 2733 else 2596 2734 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/ 2597 "PKCS#7 is not 'signedData': %s", p Signature->ContentInfo.ContentType.szObjId);2735 "PKCS#7 is not 'signedData': %s", pInfo->pContentInfo->ContentType.szObjId); 2598 2736 } 2599 2737 return rc; … … 2601 2739 2602 2740 2741 2603 2742 static 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) 2605 2744 { 2606 2745 AssertReturn(cbScratch >= _4K, VERR_INTERNAL_ERROR_3); … … 2618 2757 if (cPages * (cbHash + 4) != pAttrib->u.pPageHashes->RawData.Asn1Core.cb) 2619 2758 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); 2622 2761 2623 2762 /* … … 2640 2779 if (RT_UNLIKELY(offPageInFile >= SpecialPlaces.cbToHash)) 2641 2780 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG, 2642 " Page hash entry #%u is beyond the signature table start: %#x, %#x",2643 i Page, offPageInFile, SpecialPlaces.cbToHash);2781 "Signature #%u - Page hash entry #%u is beyond the signature table start: %#x, %#x", 2782 iSignature, iPage, offPageInFile, SpecialPlaces.cbToHash); 2644 2783 if (RT_UNLIKELY(offPageInFile < offPrev)) 2645 2784 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 i Page, offPageInFile, offPrev);2785 "Signature #%u - Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n", 2786 iSignature, iPage, offPageInFile, offPrev); 2648 2787 2649 2788 #ifdef COMPLICATED_AND_WRONG … … 2666 2805 else 2667 2806 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); 2669 2809 } 2670 2810 } … … 2710 2850 if (RT_FAILURE(rc)) 2711 2851 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); 2714 2854 } 2715 2855 … … 2778 2918 if (memcmp(pbHashTab, &HashRes, cbHash) != 0) 2779 2919 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); 2782 2923 pbHashTab += cbHash; 2783 2924 offPrev = offPageInFile; … … 2789 2930 if (!ASMMemIsZero(pbHashTab + 4, cbHash)) 2790 2931 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG, 2791 " Maltformfinal 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]), 2793 2934 (size_t)cbHash, pbHashTab + 4); 2794 2935 return VINF_SUCCESS; 2936 } 2937 2938 2939 static 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 2974 static 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; 2795 3039 } 2796 3040 … … 2806 3050 static int rtldrPE_VerifySignatureValidateHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo) 2807 3051 { 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 2816 3052 /* 2817 3053 * Allocate a temporary memory buffer. … … 2820 3056 * heap fragmentation. 2821 3057 */ 2822 # ifdef IN_RING03058 # ifdef IN_RING0 2823 3059 uint32_t cbScratch = _256K - _4K; 2824 # else3060 # else 2825 3061 uint32_t cbScratch = _1M; 2826 # endif3062 # endif 2827 3063 void *pvScratch = RTMemTmpAlloc(cbScratch); 2828 3064 if (!pvScratch) … … 2835 3071 2836 3072 /* 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: */ 2841 3083 if (RT_SUCCESS(rc)) 2842 3084 { 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 */ 2877 3093 RTMemTmpFree(pvScratch); 2878 3094 return rc; … … 2901 3117 if (RT_SUCCESS(rc)) 2902 3118 { 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 } 2907 3145 } 2908 3146 rtldrPE_VerifySignatureDestroy(pModPe, pSignature);
Note:
See TracChangeset
for help on using the changeset viewer.