Changeset 64848 in vbox
- Timestamp:
- Dec 13, 2016 1:57:59 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/tools/RTSignTool.cpp
r64731 r64848 41 41 #include <iprt/stream.h> 42 42 #include <iprt/string.h> 43 #include <iprt/crypto/digest.h> 43 44 #include <iprt/crypto/x509.h> 44 45 #include <iprt/crypto/pkcs7.h> 45 46 #include <iprt/crypto/store.h> 47 #include <iprt/crypto/spc.h> 46 48 #ifdef VBOX 47 49 # include <VBox/sup.h> /* Certificates */ … … 58 60 RTSIGNTOOLHELP_FULL 59 61 } RTSIGNTOOLHELP; 62 63 64 typedef struct SHOWEXEPKCS7 65 { 66 uint8_t const *pbBuf; 67 size_t cbBuf; 68 const char *pszFilename; 69 unsigned cVerbosity; 70 RTLDRMOD hLdrMod; 71 /** The outer content info wrapper. */ 72 RTCRPKCS7CONTENTINFO ContentInfo; 73 /** Pointer to the decoded SignedData inside the ContentInfo member. */ 74 PRTCRPKCS7SIGNEDDATA pSignedData; 75 /** Pointer to the indirect data content. */ 76 PRTCRSPCINDIRECTDATACONTENT pIndData; 77 78 char szPrefix[256]; 79 char szTmp[4096]; 80 } SHOWEXEPKCS7; 81 typedef SHOWEXEPKCS7 *PSHOWEXEPKCS7; 60 82 61 83 … … 66 88 static RTEXITCODE HelpHelp(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel); 67 89 static RTEXITCODE HandleVersion(int cArgs, char **papszArgs); 90 #ifndef IPRT_IN_BUILD_TOOL 91 static int HandleShowExeWorkerPkcs7Display(PSHOWEXEPKCS7 pThis, PRTCRPKCS7SIGNEDDATA pSignedData, size_t offPrefix); 92 #endif 68 93 69 94 … … 265 290 } VERIFYEXESTATE; 266 291 267 # ifdef VBOX292 # ifdef VBOX 268 293 /** Certificate store load set. 269 294 * Declared outside HandleVerifyExe because of braindead gcc visibility crap. */ … … 274 299 unsigned cTAs; 275 300 }; 276 # endif301 # endif 277 302 278 303 /** … … 619 644 620 645 #endif /* !IPRT_IN_BUILD_TOOL */ 646 //// 647 #ifndef IPRT_IN_BUILD_TOOL 648 649 /* 650 * The 'show-exe' command. 651 */ 652 static RTEXITCODE HelpShowExe(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel) 653 { 654 RT_NOREF_PV(enmLevel); 655 RTStrmPrintf(pStrm, 656 "show-exe [--verbose|-v] [--quiet|-q] <exe1> [exe2 [..]]\n"); 657 return RTEXITCODE_SUCCESS; 658 } 659 660 661 static int HandleShowExeWorkerPkcs7Decode(PSHOWEXEPKCS7 pThis) 662 { 663 RTERRINFOSTATIC ErrInfo; 664 RTASN1CURSORPRIMARY PrimaryCursor; 665 RTAsn1CursorInitPrimary(&PrimaryCursor, pThis->pbBuf, pThis->cbBuf, RTErrInfoInitStatic(&ErrInfo), 666 &g_RTAsn1DefaultAllocator, 0, "WinCert"); 667 668 int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pThis->ContentInfo, "CI"); 669 if (RT_SUCCESS(rc)) 670 { 671 if (RTCrPkcs7ContentInfo_IsSignedData(&pThis->ContentInfo)) 672 { 673 pThis->pSignedData = pThis->ContentInfo.u.pSignedData; 674 675 /* 676 * Decode the authenticode bits. 677 */ 678 if (!strcmp(pThis->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID)) 679 { 680 pThis->pIndData = pThis->pSignedData->ContentInfo.u.pIndirectDataContent; 681 Assert(pThis->pIndData); 682 683 /* 684 * Check that things add up. 685 */ 686 rc = RTCrPkcs7SignedData_CheckSanity(pThis->pSignedData, 687 RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE 688 | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH 689 | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, 690 RTErrInfoInitStatic(&ErrInfo), "SD"); 691 if (RT_FAILURE(rc)) 692 RTMsgError("PKCS#7 sanity check failed for '%s': %Rrc - %s\n", pThis->pszFilename, rc, ErrInfo.szMsg); 693 if (RT_SUCCESS(rc)) 694 { 695 rc = RTCrSpcIndirectDataContent_CheckSanityEx(pThis->pIndData, 696 pThis->pSignedData, 697 RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH, 698 RTErrInfoInitStatic(&ErrInfo)); 699 if (RT_FAILURE(rc)) 700 RTMsgError("SPC indirect data content sanity check failed for '%s': %Rrc - %s\n", 701 pThis->pszFilename, rc, ErrInfo.szMsg); 702 } 703 } 704 else 705 RTMsgError("Unexpected the signed content in '%s': %s (expected %s)", pThis->pszFilename, 706 pThis->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 707 } 708 else 709 RTMsgError("PKCS#7 content is inside '%s' is not 'signedData': %s\n", 710 pThis->pszFilename, pThis->ContentInfo.ContentType.szObjId); 711 } 712 else 713 RTMsgError("RTCrPkcs7ContentInfo_DecodeAsn1 failed on '%s': %Rrc - %s\n", pThis->pszFilename, rc, ErrInfo.szMsg); 714 return rc; 715 } 716 717 718 static int HandleShowExeWorkerPkcs7DisplayAttrib(PSHOWEXEPKCS7 pThis, size_t offPrefix, PCRTCRPKCS7ATTRIBUTE pAttr) 719 { 720 const char *pszType; 721 int rc = RTAsn1QueryObjIdName(&pAttr->Type, pThis->szTmp, sizeof(pThis->szTmp)); 722 if (RT_SUCCESS(rc)) 723 RTPrintf("%s%s (%s)\n", pThis->szPrefix, pThis->szTmp, pAttr->Type.szObjId); 724 else 725 RTPrintf("%s%s\n", pThis->szPrefix, pAttr->Type.szObjId); 726 727 rc = VINF_SUCCESS; 728 switch (pAttr->enmType) 729 { 730 case RTCRPKCS7ATTRIBUTETYPE_UNKNOWN: 731 if (pAttr->uValues.pCores->cItems <= 1) 732 RTPrintf("%s %u bytes\n", pThis->szPrefix,pAttr->uValues.pCores->SetCore.Asn1Core.cb); 733 else 734 RTPrintf("%s %u bytes divided by %u items\n", pThis->szPrefix, pAttr->uValues.pCores->SetCore.Asn1Core.cb, pAttr->uValues.pCores->cItems); 735 for (unsigned i = 0; i < pAttr->uValues.pCores->cItems; i++) 736 { 737 738 } 739 break; 740 741 /** Object IDs, use pObjIds. */ 742 case RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS: 743 /** Octet strings, use pOctetStrings. */ 744 case RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS: 745 /** Counter signatures (PKCS \#9), use pCounterSignatures. */ 746 case RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES: 747 /** Signing time (PKCS \#9), use pSigningTime. */ 748 case RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME: 749 /** Microsoft timestamp info (RFC-3161) signed data, use pContentInfo. */ 750 case RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP: 751 case RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE: 752 if (pAttr->uValues.pContentInfos->cItems > 1) 753 RTPrintf("%s%u nested signatures, %u bytes in total\n", pThis->szPrefix, 754 pAttr->uValues.pContentInfos->cItems, pAttr->uValues.pContentInfos->SetCore.Asn1Core.cb); 755 for (unsigned i = 0; i < pAttr->uValues.pContentInfos->cItems; i++) 756 { 757 size_t offPrefix2 = offPrefix; 758 if (pAttr->uValues.pContentInfos->cItems > 1) 759 offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "NestedSig[%u]: ", i); 760 else 761 offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, " "); 762 // offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "NestedSig: ", i); 763 PCRTCRPKCS7CONTENTINFO pContentInfo = &pAttr->uValues.pContentInfos->paItems[i]; 764 int rc2; 765 if (RTCrPkcs7ContentInfo_IsSignedData(&pThis->ContentInfo)) 766 rc2 = HandleShowExeWorkerPkcs7Display(pThis, pContentInfo->u.pSignedData, offPrefix2); 767 else 768 rc2 = RTMsgErrorRc(VERR_ASN1_UNEXPECTED_OBJ_ID, "%sPKCS#7 content in nested signature is not 'signedData': %s", 769 pThis->szPrefix, pContentInfo->ContentType.szObjId); 770 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 771 rc = rc2; 772 } 773 break; 774 775 case RTCRPKCS7ATTRIBUTETYPE_INVALID: 776 RTPrintf("%sINVALID!\n", pThis->szPrefix); 777 break; 778 case RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT: 779 RTPrintf("%sNOT PRESENT!\n", pThis->szPrefix); 780 break; 781 default: 782 RTPrintf("%senmType=%d!\n", pThis->szPrefix, pAttr->enmType); 783 break; 784 } 785 //if (RTAsn1ObjId_CompareWithString(&pAttr->Type, )) 786 //{ 787 //} 788 return rc; 789 } 790 791 792 static int HandleShowExeWorkerPkcs7Display(PSHOWEXEPKCS7 pThis, PRTCRPKCS7SIGNEDDATA pSignedData, size_t offPrefix) 793 { 794 pThis->szPrefix[offPrefix] = '\0'; 795 796 /* Display list of signing algorithms. */ 797 RTPrintf("%sDigestAlgorithms: ", pThis->szPrefix); 798 for (unsigned i = 0; i < pSignedData->DigestAlgorithms.cItems; i++) 799 { 800 PCRTCRX509ALGORITHMIDENTIFIER pAlgoId = &pSignedData->DigestAlgorithms.paItems[i]; 801 const char *pszDigestType = RTCrDigestTypeToName(RTCrX509AlgorithmIdentifier_QueryDigestType(pAlgoId)); 802 if (!pszDigestType) 803 pszDigestType = pAlgoId->Algorithm.szObjId; 804 RTPrintf(i == 0 ? "%s" : ", %s", pszDigestType); 805 } 806 RTPrintf("\n"); 807 808 /* Display certificates (Certificates). */ 809 810 /* Show signatures (SignerInfos). */ 811 unsigned const cSigInfos = pSignedData->SignerInfos.cItems; 812 for (unsigned i = 0; i < cSigInfos; i++) 813 { 814 PRTCRPKCS7SIGNERINFO pSigInfo = &pSignedData->SignerInfos.paItems[i]; 815 size_t offPrefix2 = offPrefix; 816 if (cSigInfos != 1) 817 offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "SignerInfo[%u]: ", i); 818 819 int rc = RTAsn1Integer_ToString(&pSigInfo->IssuerAndSerialNumber.SerialNumber, 820 pThis->szTmp, sizeof(pThis->szTmp), 0 /*fFlags*/, NULL); 821 if (RT_FAILURE(rc)) 822 RTStrPrintf(pThis->szTmp, sizeof(pThis->szTmp), "%Rrc", rc); 823 RTPrintf("%s Serial No: %s\n", pThis->szPrefix, pThis->szTmp); 824 825 rc = RTCrX509Name_FormatAsString(&pSigInfo->IssuerAndSerialNumber.Name, pThis->szTmp, sizeof(pThis->szTmp), NULL); 826 if (RT_FAILURE(rc)) 827 RTStrPrintf(pThis->szTmp, sizeof(pThis->szTmp), "%Rrc", rc); 828 RTPrintf("%s Issuer: %s\n", pThis->szPrefix, pThis->szTmp); 829 830 const char *pszType = RTCrDigestTypeToName(RTCrX509AlgorithmIdentifier_QueryDigestType(&pSigInfo->DigestAlgorithm)); 831 if (!pszType) 832 pszType = pSigInfo->DigestAlgorithm.Algorithm.szObjId; 833 RTPrintf("%s Digest Algorithm: %s\n", pThis->szPrefix, pszType); 834 835 rc = RTAsn1QueryObjIdName(&pSigInfo->DigestEncryptionAlgorithm.Algorithm, pThis->szTmp, sizeof(pThis->szTmp)); 836 if (RT_SUCCESS(rc)) 837 pszType = pThis->szTmp; 838 else 839 pszType = pSigInfo->DigestAlgorithm.Algorithm.szObjId; 840 RTPrintf("%sDigest Encryption Algorithm: %s\n", pThis->szPrefix, pszType); 841 842 if (pSigInfo->AuthenticatedAttributes.cItems == 0) 843 RTPrintf("%s Authenticated Attributes: none\n", pThis->szPrefix); 844 else 845 { 846 RTPrintf("%s Authenticated Attributes: %u item%s\n", pThis->szPrefix, 847 pSigInfo->AuthenticatedAttributes.cItems, pSigInfo->AuthenticatedAttributes.cItems > 1 ? "s" : ""); 848 for (unsigned j = 0; j < pSigInfo->AuthenticatedAttributes.cItems; j++) 849 { 850 PRTCRPKCS7ATTRIBUTE pAttr = &pSigInfo->AuthenticatedAttributes.paItems[j]; 851 size_t offPrefix3 = offPrefix2 + RTStrPrintf(&pThis->szPrefix[offPrefix2], sizeof(pThis->szPrefix) - offPrefix2, 852 " AuthAttrib[%u]: ", j); 853 HandleShowExeWorkerPkcs7DisplayAttrib(pThis, offPrefix3, pAttr); 854 } 855 pThis->szPrefix[offPrefix2] = '\0'; 856 } 857 858 if (pSigInfo->UnauthenticatedAttributes.cItems == 0) 859 RTPrintf("%s Unauthenticated Attributes: none\n", pThis->szPrefix); 860 else 861 { 862 RTPrintf("%s Unauthenticated Attributes: %u item%s\n", pThis->szPrefix, 863 pSigInfo->UnauthenticatedAttributes.cItems, pSigInfo->UnauthenticatedAttributes.cItems > 1 ? "s" : ""); 864 for (unsigned j = 0; j < pSigInfo->UnauthenticatedAttributes.cItems; j++) 865 { 866 PRTCRPKCS7ATTRIBUTE pAttr = &pSigInfo->UnauthenticatedAttributes.paItems[j]; 867 size_t offPrefix3 = offPrefix2 + RTStrPrintf(&pThis->szPrefix[offPrefix2], sizeof(pThis->szPrefix) - offPrefix2, 868 " UnauthAttrib[%u]: ", j); 869 HandleShowExeWorkerPkcs7DisplayAttrib(pThis, offPrefix3, pAttr); 870 } 871 pThis->szPrefix[offPrefix2] = '\0'; 872 } 873 874 #if 0 875 /** Authenticated attributes, optional [0]. 876 * @todo Check how other producers formats this. The microsoft one does not 877 * have explicit tags, but combines it with the SET OF. */ 878 RTCRPKCS7ATTRIBUTES AuthenticatedAttributes; 879 880 /** The encrypted digest. */ 881 RTASN1OCTETSTRING EncryptedDigest; 882 /** Unauthenticated attributes, optional [1]. 883 * @todo Check how other producers formats this. The microsoft one does not 884 * have explicit tags, but combines it with the SET OF. */ 885 RTCRPKCS7ATTRIBUTES UnauthenticatedAttributes; 886 #endif 887 } 888 pThis->szPrefix[offPrefix] = '\0'; 889 890 return VINF_SUCCESS; 891 } 892 893 894 /** 895 * Shows the signing info for one executable. 896 * 897 * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure. 898 * @param pszFilename The path to the executable. 899 * @param cVerbosity The verbosity level. 900 * @param enmLdrArch Sub image selector. 901 */ 902 static RTEXITCODE HandleShowExeWorker(const char *pszFilename, unsigned cVerbosity, RTLDRARCH enmLdrArch) 903 { 904 /* 905 * Open the image and check if it's signed. 906 */ 907 RTLDRMOD hLdrMod; 908 int rc = RTLdrOpen(pszFilename, RTLDR_O_FOR_VALIDATION, enmLdrArch, &hLdrMod); 909 if (RT_FAILURE(rc)) 910 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening executable image '%s': %Rrc", pszFilename, rc); 911 912 bool fIsSigned = false; 913 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_IS_SIGNED, &fIsSigned, sizeof(fIsSigned)); 914 if (RT_SUCCESS(rc) && fIsSigned) 915 { 916 /* 917 * Query the PKCS#7 data (assuming M$ style signing) and hand it to a worker. 918 */ 919 size_t cbActual = 0; 920 size_t cbBuf = _64K; 921 void *pvBuf = RTMemAllocZ(cbBuf); 922 if (pvBuf) 923 { 924 rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbActual); 925 if (rc == VERR_BUFFER_OVERFLOW) 926 { 927 RTMemFree(pvBuf); 928 cbBuf = cbActual; 929 pvBuf = RTMemAllocZ(cbActual); 930 if (pvBuf) 931 rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbActual); 932 else 933 rc = VERR_NO_MEMORY; 934 } 935 } 936 else 937 rc = VERR_NO_MEMORY; 938 if (RT_SUCCESS(rc)) 939 { 940 SHOWEXEPKCS7 This; 941 RT_ZERO(This); 942 This.pbBuf = (uint8_t const *)pvBuf; 943 This.cbBuf = cbActual; 944 This.cVerbosity = cVerbosity; 945 This.pszFilename = pszFilename; 946 This.hLdrMod = hLdrMod; 947 rc = HandleShowExeWorkerPkcs7Decode(&This); 948 if (RT_SUCCESS(rc)) 949 rc = HandleShowExeWorkerPkcs7Display(&This, This.pSignedData, 0); 950 RTCrPkcs7ContentInfo_Delete(&This.ContentInfo); 951 } 952 else 953 RTMsgError("RTLdrQueryPropEx/RTLDRPROP_PKCS7_SIGNED_DATA failed on '%s': %Rrc\n", pszFilename, rc); 954 RTMemFree(pvBuf); 955 } 956 else if (RT_SUCCESS(rc)) 957 RTMsgInfo("'%s': not signed\n", pszFilename); 958 else 959 RTMsgError("RTLdrQueryProp/RTLDRPROP_IS_SIGNED failed on '%s': %Rrc\n", pszFilename, rc); 960 961 int rc2 = RTLdrClose(hLdrMod); 962 if (RT_FAILURE(rc2)) 963 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTLdrClose failed: %Rrc\n", rc2); 964 if (RT_FAILURE(rc)) 965 return rc != VERR_LDRVI_NOT_SIGNED ? RTEXITCODE_FAILURE : RTEXITCODE_SKIPPED; 966 967 return RTEXITCODE_SUCCESS; 968 } 969 970 static RTEXITCODE HandleShowExe(int cArgs, char **papszArgs) 971 { 972 /* Note! This code does not try to clean up the crypto stores on failure. 973 This is intentional as the code is only expected to be used in a 974 one-command-per-process environment where we do exit() upon 975 returning from this function. */ 976 977 /* 978 * Parse arguments. 979 */ 980 static const RTGETOPTDEF s_aOptions[] = 981 { 982 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 983 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, 984 }; 985 986 unsigned cVerbose = 0; 987 RTLDRARCH enmLdrArch = RTLDRARCH_WHATEVER; 988 989 RTGETOPTSTATE GetState; 990 int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); 991 AssertRCReturn(rc, RTEXITCODE_FAILURE); 992 RTGETOPTUNION ValueUnion; 993 int ch; 994 while ((ch = RTGetOpt(&GetState, &ValueUnion)) && ch != VINF_GETOPT_NOT_OPTION) 995 { 996 switch (ch) 997 { 998 case 'v': cVerbose++; break; 999 case 'q': cVerbose = 0; break; 1000 case 'V': return HandleVersion(cArgs, papszArgs); 1001 case 'h': return HelpShowExe(g_pStdOut, RTSIGNTOOLHELP_FULL); 1002 default: return RTGetOptPrintError(ch, &ValueUnion); 1003 } 1004 } 1005 if (ch != VINF_GETOPT_NOT_OPTION) 1006 return RTMsgErrorExit(RTEXITCODE_FAILURE, "No executable given."); 1007 1008 /* 1009 * Do it. 1010 */ 1011 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1012 do 1013 { 1014 RTEXITCODE rcExitThis = HandleShowExeWorker(ValueUnion.psz, cVerbose, enmLdrArch); 1015 if (rcExitThis != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS) 1016 rcExit = rcExitThis; 1017 } while ((ch = RTGetOpt(&GetState, &ValueUnion)) == VINF_GETOPT_NOT_OPTION); 1018 if (ch != 0) 1019 return RTGetOptPrintError(ch, &ValueUnion); 1020 1021 return rcExit; 1022 } 1023 1024 #endif /* !IPRT_IN_BUILD_TOOL */ 1025 //// 621 1026 622 1027 /* … … 882 1287 #ifndef IPRT_IN_BUILD_TOOL 883 1288 { "verify-exe", HandleVerifyExe, HelpVerifyExe }, 1289 { "show-exe", HandleShowExe, HelpShowExe }, 884 1290 #endif 885 1291 { "make-tainfo", HandleMakeTaInfo, HelpMakeTaInfo },
Note:
See TracChangeset
for help on using the changeset viewer.