VirtualBox

Changeset 95598 in vbox


Ignore:
Timestamp:
Jul 12, 2022 2:27:37 AM (2 years ago)
Author:
vboxsync
Message:

RTSignTool: Some early timstamping. bugref:8691

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/tools/RTSignTool.cpp

    r95583 r95598  
    4848#include <iprt/crypto/applecodesign.h>
    4949#include <iprt/crypto/digest.h>
     50#include <iprt/crypto/key.h>
    5051#include <iprt/crypto/x509.h>
    5152#include <iprt/crypto/pkcs7.h>
     
    5960# include <iprt/win/imagehlp.h>
    6061#endif
     62
     63
     64/*********************************************************************************************************************************
     65*   Defined Constants And Macros                                                                                                 *
     66*********************************************************************************************************************************/
     67#define OPT_TIMESTAMP_CERT_FILE         1000
     68#define OPT_TIMESTAMP_KEY_FILE          1001
     69#define OPT_TIMESTAMP_TYPE              1002
     70#define OPT_TIMESTAMP_DATE              1003
     71#define OPT_TIMESTAMP_YEAR              1004
    6172
    6273
     
    335346
    336347/**
     348 * Helper that makes sure the UnauthenticatedAttributes are present in the given
     349 * SignerInfo structure.
     350 *
     351 * Call this before trying to modify the array.
     352 *
     353 * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE with error already
     354 *          displayed on failure.
     355 * @param   pSignerInfo         The SignerInfo structure in question.
     356 */
     357static RTEXITCODE SignToolPkcs7_EnsureUnauthenticatedAttributesPresent(PRTCRPKCS7SIGNERINFO pSignerInfo)
     358{
     359   if (pSignerInfo->UnauthenticatedAttributes.cItems == 0)
     360   {
     361       /* HACK ALERT! Invent ASN.1 setters/whatever for members to replace this mess. */
     362
     363       if (pSignerInfo->AuthenticatedAttributes.cItems == 0)
     364           return RTMsgErrorExit(RTEXITCODE_FAILURE, "No authenticated or unauthenticated attributes! Sorry, no can do.");
     365
     366       Assert(pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.uTag == 0);
     367       int rc = RTAsn1SetCore_Init(&pSignerInfo->UnauthenticatedAttributes.SetCore,
     368                                   pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core.pOps);
     369       if (RT_FAILURE(rc))
     370           return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTAsn1SetCore_Init failed: %Rrc", rc);
     371       pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.uTag   = 1;
     372       pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.fClass = ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED;
     373       RTAsn1MemInitArrayAllocation(&pSignerInfo->UnauthenticatedAttributes.Allocation,
     374                                    pSignerInfo->AuthenticatedAttributes.Allocation.pAllocator,
     375                                    sizeof(**pSignerInfo->UnauthenticatedAttributes.papItems));
     376   }
     377   return RTEXITCODE_SUCCESS;
     378}
     379
     380
     381/**
    337382 * Adds the @a pSrc signature as a nested signature.
    338383 *
     
    349394{
    350395    PRTCRPKCS7SIGNERINFO pSignerInfo = pThis->pSignedData->SignerInfos.papItems[0];
    351     int rc;
    352396
    353397    /*
    354398     * Deal with UnauthenticatedAttributes being absent before trying to append to the array.
    355399     */
    356     if (pSignerInfo->UnauthenticatedAttributes.cItems == 0)
    357     {
    358         /* HACK ALERT! Invent ASN.1 setters/whatever for members to replace this mess. */
    359 
    360         if (pSignerInfo->AuthenticatedAttributes.cItems == 0)
    361             return RTMsgErrorExit(RTEXITCODE_FAILURE, "No authenticated or unauthenticated attributes! Sorry, no can do.");
    362 
    363         Assert(pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.uTag == 0);
    364         rc = RTAsn1SetCore_Init(&pSignerInfo->UnauthenticatedAttributes.SetCore,
    365                                 pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core.pOps);
    366         if (RT_FAILURE(rc))
    367             return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTAsn1SetCore_Init failed: %Rrc", rc);
    368         pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.uTag   = 1;
    369         pSignerInfo->UnauthenticatedAttributes.SetCore.Asn1Core.fClass = ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED;
    370         RTAsn1MemInitArrayAllocation(&pSignerInfo->UnauthenticatedAttributes.Allocation,
    371                                      pSignerInfo->AuthenticatedAttributes.Allocation.pAllocator,
    372                                      sizeof(**pSignerInfo->UnauthenticatedAttributes.papItems));
    373     }
     400    RTEXITCODE rcExit = SignToolPkcs7_EnsureUnauthenticatedAttributesPresent(pSignerInfo);
     401    if (rcExit != RTEXITCODE_SUCCESS)
     402        return rcExit;
    374403
    375404    /*
    376405     * Find or add an unauthenticated attribute for nested signatures.
    377406     */
    378     rc = VERR_NOT_FOUND;
     407    int rc = VERR_NOT_FOUND;
    379408    PRTCRPKCS7ATTRIBUTE pAttr = NULL;
    380409    int32_t iPos = pSignerInfo->UnauthenticatedAttributes.cItems;
     
    496525 * Worker for recursively searching for MS nested signatures and signer infos.
    497526 *
    498  * @returns Pointer to the signer info corresponding to @a iSignature.  NULL if
    499  *          not found.
     527 * @returns Pointer to the signer info corresponding to @a iReqSignature.  NULL
     528 *          if not found.
    500529 * @param   pSignedData     The signature to search.
    501530 * @param   piNextSignature Pointer to the variable keeping track of the next
     
    503532 * @param   iReqSignature   The request signature number.
    504533 * @param   ppSignedData    Where to return the signature data structure.
     534 *                          Optional.
    505535 */
    506536static PRTCRPKCS7SIGNERINFO SignToolPkcs7_FindNestedSignatureByIndexWorker(PRTCRPKCS7SIGNEDDATA pSignedData,
     
    515545        if (*piNextSignature == iReqSignature)
    516546        {
    517             *ppSignedData = pSignedData;
     547            if (ppSignedData)
     548                *ppSignedData = pSignedData;
    518549            return pSignerInfo;
    519550        }
     
    547578 * Locates the given nested signature.
    548579 *
    549  * @returns Pointer to the signer info corresponding to @a iSignature.  NULL if
    550  *          not found.
     580 * @returns Pointer to the signer info corresponding to @a iReqSignature.  NULL
     581 *          if not found.
    551582 * @param   pThis           The PKCS\#7 structure to search.
    552583 * @param   iReqSignature   The requested signature number.
     
    882913}
    883914
    884 
    885 
    886 /*
    887  * The 'extract-exe-signer-cert' command.
    888  */
     915#ifndef IPRT_IN_BUILD_TOOL
     916
     917static RTEXITCODE AddAuthAttribsForTimestamp(PRTCRPKCS7ATTRIBUTES pAuthAttribs, bool fTimestampTypeOld,
     918                                             RTTIMESPEC SigningTime,  PCRTCRX509CERTIFICATE pTimestampCert)
     919{
     920    /*
     921     * Signing time.  For the old-style timestamps, Symantec used ASN.1 UTC TIME.
     922     *                              start -vv    vv=ASN1_TAG_UTC_TIME
     923     *  00000187d6a65fd0/23b0: 0d 01 09 05 31 0f 17 0d-31 36 31 30 30 35 30 37 ....1...16100507
     924     *  00000187d6a65fe0/23c0: 35 30 33 30 5a 30 23 06-09 2a 86 48 86 f7 0d 01 5030Z0#..*.H....
     925     *                                     ^^- end 2016-10-05T07:50:30.000000000Z (161005075030Z)
     926     */
     927    int32_t iPos = RTCrPkcs7Attributes_Append(pAuthAttribs);
     928    if (iPos < 0)
     929        return RTMsgErrorExitFailure("RTCrPkcs7Attributes_Append failed: %Rrc", iPos);
     930
     931    /* Create the attrib and its sub-set of timestamps. */
     932    PRTCRPKCS7ATTRIBUTE pAttr = pAuthAttribs->papItems[iPos];
     933    int rc = RTAsn1ObjId_InitFromString(&pAttr->Type, RTCR_PKCS9_ID_SIGNING_TIME_OID, pAttr->Allocation.pAllocator);
     934    if (RT_FAILURE(rc))
     935        return RTMsgErrorExitFailure("RTAsn1ObjId_InitFromString/RTCR_PKCS9_ID_SIGNING_TIME_OID failed: %Rrc", rc);
     936
     937    /** @todo Generalize the Type + enmType DYN stuff and generate setters. */
     938    Assert(pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT);
     939    Assert(pAttr->uValues.pContentInfos == NULL);
     940    pAttr->enmType = RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME;
     941    rc = RTAsn1MemAllocZ(&pAttr->Allocation, (void **)&pAttr->uValues.pSigningTime, sizeof(*pAttr->uValues.pSigningTime));
     942    if (RT_FAILURE(rc))
     943        return RTMsgErrorExitFailure("RTAsn1MemAllocZ failed: %Rrc", rc);
     944
     945    rc = RTAsn1SetOfTimes_Init(pAttr->uValues.pSigningTime, pAttr->Allocation.pAllocator);
     946    if (RT_FAILURE(rc))
     947        return RTMsgErrorExitFailure("RTCrPkcs7ContentInfos_Init failed: %Rrc", rc);
     948
     949    /* Create the timestamp. */
     950    iPos = RTAsn1SetOfTimes_Append(pAttr->uValues.pSigningTime);
     951    if (iPos < 0)
     952        return RTMsgErrorExitFailure("RTCrPkcs7SigningTimes_Append failed: %Rrc", iPos);
     953
     954    PRTASN1TIME pTime = pAttr->uValues.pSigningTime->papItems[iPos];
     955    rc = RTAsn1Time_SetTimeSpec(pTime, pAttr->Allocation.pAllocator, &SigningTime);
     956    if (RT_FAILURE(rc))
     957        return RTMsgErrorExitFailure("RTAsn1Time_SetTimeSpec failed: %Rrc", rc);
     958
     959    /*
     960     * More later if we want to support fTimestampTypeOld = false perhaps?
     961     */
     962    Assert(fTimestampTypeOld);
     963    RT_NOREF(fTimestampTypeOld, pTimestampCert);
     964
     965    return RTEXITCODE_SUCCESS;
     966}
     967
     968
     969static RTEXITCODE SignToolPkcs7_PrependCounterSignature(PRTCRPKCS7SIGNERINFO pSignerInfo,
     970                                                        PCRTCRPKCS7SIGNERINFO pCounterSignerInfo, unsigned cVerbosity)
     971{
     972    /* Make sure the UnauthenticatedAttributes member is there. */
     973    RTEXITCODE rcExit = SignToolPkcs7_EnsureUnauthenticatedAttributesPresent(pSignerInfo);
     974    if (rcExit != RTEXITCODE_SUCCESS)
     975        return rcExit;
     976
     977    /* Append an entry to UnauthenticatedAttributes. */
     978    uint32_t iPos;
     979    int rc = RTCrPkcs7Attributes_InsertEx(&pSignerInfo->UnauthenticatedAttributes, 0 /*iPosition*/, NULL /*pToClone*/,
     980                                          &g_RTAsn1DefaultAllocator, &iPos);
     981    if (RT_FAILURE(rc))
     982        return RTMsgErrorExitFailure("RTCrPkcs7Attributes_Append failed: %Rrc", rc);
     983    Assert(iPos < pSignerInfo->UnauthenticatedAttributes.cItems); Assert(iPos == 0);
     984    PRTCRPKCS7ATTRIBUTE pAttr = pSignerInfo->UnauthenticatedAttributes.papItems[iPos];
     985
     986    if (cVerbosity >= 2)
     987        RTMsgInfo("Adding UnauthenticatedAttribute #%u...", iPos);
     988
     989    /* Create the attrib and its sub-set of counter signatures. */
     990    rc = RTAsn1ObjId_InitFromString(&pAttr->Type, RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID, pAttr->Allocation.pAllocator);
     991    if (RT_FAILURE(rc))
     992        return RTMsgErrorExitFailure("RTAsn1ObjId_InitFromString failed: %Rrc", rc);
     993
     994    /** @todo Generalize the Type + enmType DYN stuff and generate setters. */
     995    Assert(pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT);
     996    Assert(pAttr->uValues.pContentInfos == NULL);
     997    pAttr->enmType = RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES;
     998    rc = RTAsn1MemAllocZ(&pAttr->Allocation, (void **)&pAttr->uValues.pCounterSignatures,
     999                         sizeof(*pAttr->uValues.pCounterSignatures));
     1000    if (RT_FAILURE(rc))
     1001        return RTMsgErrorExitFailure("RTAsn1MemAllocZ failed: %Rrc", rc);
     1002
     1003    rc = RTCrPkcs7SignerInfos_Init(pAttr->uValues.pCounterSignatures, pAttr->Allocation.pAllocator);
     1004    if (RT_FAILURE(rc))
     1005        return RTMsgErrorExitFailure("RTCrPkcs7SignerInfos_Init failed: %Rrc", rc);
     1006
     1007    /* Insert the counter signature. */
     1008    rc = RTCrPkcs7SignerInfos_InsertEx(pAttr->uValues.pCounterSignatures, 0 /*iPosition*/, pCounterSignerInfo,
     1009                                       pAttr->Allocation.pAllocator, NULL);
     1010    if (RT_FAILURE(rc))
     1011        return RTMsgErrorExitFailure("RTCrPkcs7SignerInfos_InsertEx failed: %Rrc", rc);
     1012
     1013    return RTEXITCODE_SUCCESS;
     1014}
     1015
     1016
     1017static RTEXITCODE SignToolPkcs7_AppendCertificate(PRTCRPKCS7SIGNEDDATA pSignedData, PCRTCRX509CERTIFICATE pCertToAppend)
     1018{
     1019    if (pSignedData->Certificates.cItems == 0 && !RTCrPkcs7SetOfCerts_IsPresent(&pSignedData->Certificates))
     1020        return RTMsgErrorExitFailure("PKCS#7 signature includes no certificates! Didn't expect that");
     1021
     1022    /* Already there? */
     1023    PCRTCRX509CERTIFICATE pExisting
     1024        = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates, &pCertToAppend->TbsCertificate.Issuer,
     1025                                                              &pCertToAppend->TbsCertificate.SerialNumber);
     1026    if (!pExisting || RTCrX509Certificate_Compare(pExisting, pCertToAppend) != 0)
     1027    {
     1028        /* Append a RTCRPKCS7CERT entry. */
     1029        //int32_t iPos = RTCrPkcs7SetOfCerts_Append(&pSignedData->Certificates);
     1030        //if (iPos < 0)
     1031        //    return RTMsgErrorExitFailure("RTCrPkcs7SetOfCerts_Append failed: %Rrc", iPos);
     1032        uint32_t iPos;
     1033        int rc = RTCrPkcs7SetOfCerts_InsertEx(&pSignedData->Certificates, 0 /*iPosition*/, NULL /*pToClone*/,
     1034                                              &g_RTAsn1DefaultAllocator, &iPos);
     1035        if (RT_FAILURE(rc))
     1036            return RTMsgErrorExitFailure("RTCrPkcs7SetOfCerts_Append failed: %Rrc", rc);
     1037
     1038        PRTCRPKCS7CERT pCertEntry = pSignedData->Certificates.papItems[iPos];
     1039
     1040        /** @todo Generalize the Type + enmType DYN stuff and generate setters. */
     1041        Assert(pCertEntry->enmChoice == RTCRPKCS7CERTCHOICE_INVALID);
     1042        Assert(pCertEntry->u.pX509Cert == NULL);
     1043        pCertEntry->enmChoice = RTCRPKCS7CERTCHOICE_X509;
     1044        rc = RTAsn1MemAllocZ(&pCertEntry->Allocation, (void **)&pCertEntry->u.pX509Cert, sizeof(*pCertEntry->u.pX509Cert));
     1045        if (RT_FAILURE(rc))
     1046            return RTMsgErrorExitFailure("RTAsn1MemAllocZ failed: %Rrc", rc);
     1047
     1048        /* Copy over the certificate we wish to append. */
     1049        rc = RTCrX509Certificate_Clone(pCertEntry->u.pX509Cert, pCertToAppend, pCertEntry->Allocation.pAllocator);
     1050        if (RT_FAILURE(rc))
     1051            return RTMsgErrorExitFailure("RTCrX509Certificate_Clone failed: %Rrc", rc);
     1052    }
     1053    return RTEXITCODE_SUCCESS;
     1054}
     1055
     1056
     1057static RTEXITCODE Pkcs7SignStuff(const char *pszWhat, const void *pvToDataToSign, size_t cbToDataToSign,
     1058                                 PCRTCRPKCS7ATTRIBUTES pAuthAttribs, RTCRSTORE hAdditionalCerts, uint32_t fExtraFlags,
     1059                                 RTDIGESTTYPE enmDigestType, PCRTCRX509CERTIFICATE pTimestampCert, RTCRKEY hTimestampKey,
     1060                                 unsigned cVerbosity, void **ppvSigned, size_t *pcbSigned,
     1061                                 PRTCRPKCS7CONTENTINFO pContentInfo, PRTCRPKCS7SIGNEDDATA *ppSignedData)
     1062{
     1063    *ppvSigned = NULL;
     1064    if (pcbSigned)
     1065        *pcbSigned = 0;
     1066    if (ppSignedData)
     1067        *ppSignedData = NULL;
     1068
     1069    /* Figure out how large the signature will be. */
     1070    RTERRINFOSTATIC ErrInfo;
     1071    size_t cbSigned = 1024;
     1072    int rc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP | fExtraFlags,
     1073                                           pTimestampCert, hTimestampKey, pvToDataToSign, cbToDataToSign,
     1074                                           enmDigestType, hAdditionalCerts, pAuthAttribs,
     1075                                           NULL, &cbSigned, RTErrInfoInitStatic(&ErrInfo));
     1076    if (rc != VERR_BUFFER_OVERFLOW)
     1077        return RTMsgErrorExitFailure("RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim", rc, &ErrInfo.Core);
     1078
     1079    /* Allocate memory for it and do the actual signing. */
     1080    void *pvSigned = RTMemTmpAllocZ(cbSigned);
     1081    if (!pvSigned)
     1082        return RTMsgErrorExitFailure("Failed to allocate %#zx bytes for %s signature", cbSigned, pszWhat);
     1083    rc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP | fExtraFlags,
     1084                                       pTimestampCert, hTimestampKey, pvToDataToSign, cbToDataToSign,
     1085                                       enmDigestType, hAdditionalCerts, pAuthAttribs,
     1086                                       pvSigned, &cbSigned, RTErrInfoInitStatic(&ErrInfo));
     1087    if (RT_SUCCESS(rc))
     1088    {
     1089        if (cVerbosity > 2)
     1090            RTMsgInfo("%s signature: %#zx bytes\n%.*Rhxd\n", pszWhat, cbSigned, cbSigned, pvSigned);
     1091
     1092        /*
     1093         * Decode the signature and check that it is SignedData.
     1094         */
     1095        RTASN1CURSORPRIMARY PrimaryCursor;
     1096        RTAsn1CursorInitPrimary(&PrimaryCursor, pvSigned, (uint32_t)cbSigned, RTErrInfoInitStatic(&ErrInfo),
     1097                                &g_RTAsn1DefaultAllocator, 0, pszWhat);
     1098        rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, pContentInfo, "CI");
     1099        if (RT_SUCCESS(rc))
     1100        {
     1101            if (RTCrPkcs7ContentInfo_IsSignedData(pContentInfo))
     1102            {
     1103                *ppvSigned = pvSigned;
     1104                if (pcbSigned)
     1105                    *pcbSigned = cbSigned;
     1106                if (ppSignedData)
     1107                    *ppSignedData = pContentInfo->u.pSignedData;
     1108
     1109                if (cVerbosity)
     1110                {
     1111                    SHOWEXEPKCS7 ShowExe;
     1112                    RT_ZERO(ShowExe);
     1113                    ShowExe.cVerbosity = cVerbosity;
     1114                    HandleShowExeWorkerPkcs7Display(&ShowExe, pContentInfo->u.pSignedData, 0, pContentInfo);
     1115                }
     1116                return RTEXITCODE_SUCCESS;
     1117            }
     1118
     1119            RTMsgError("RTCrPkcs7SimpleSignSignedData did not create SignedData: %s", pContentInfo->ContentType.szObjId);
     1120        }
     1121        else
     1122            RTMsgError("RTCrPkcs7ContentInfo_DecodeAsn1 failed: %Rrc%#RTeim", rc, &ErrInfo.Core);
     1123        RTCrPkcs7ContentInfo_Delete(pContentInfo);
     1124    }
     1125    RTMemTmpFree(pvSigned);
     1126    return RTEXITCODE_FAILURE;
     1127}
     1128
     1129
     1130static RTEXITCODE SignToolPkcs7_AddTimestampSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, unsigned iSignature,
     1131                                                      bool fReplaceExisting, bool fTimestampTypeOld, RTTIMESPEC SigningTime,
     1132                                                      PCRTCRX509CERTIFICATE pTimestampCert, RTCRKEY hTimestampKey)
     1133{
     1134    AssertReturn(fTimestampTypeOld, RTMsgErrorExitFailure("New style signatures not supported yet"));
     1135
     1136    /*
     1137     * Locate the signature specified by iSignature:
     1138     */
     1139    PRTCRPKCS7SIGNEDDATA pSignedData = NULL;
     1140    PRTCRPKCS7SIGNERINFO pSignerInfo = SignToolPkcs7_FindNestedSignatureByIndex(pThis, iSignature, &pSignedData);
     1141    if (!pSignerInfo)
     1142        return RTMsgErrorExitFailure("No signature #%u in %s", iSignature, pThis->pszFilename);
     1143
     1144    /*
     1145     * Create a set of attributes we need to include in the AuthenticatedAttributes
     1146     * of the timestamp signature.
     1147     */
     1148    RTCRPKCS7ATTRIBUTES AuthAttribs;
     1149    int rc = RTCrPkcs7Attributes_Init(&AuthAttribs, &g_RTAsn1DefaultAllocator);
     1150    if (RT_FAILURE(rc))
     1151        return RTMsgErrorExitFailure("RTCrPkcs7SetOfAttributes_Init failed: %Rrc", rc);
     1152
     1153    RTEXITCODE rcExit = AddAuthAttribsForTimestamp(&AuthAttribs, fTimestampTypeOld, SigningTime, pTimestampCert);
     1154    if (rcExit == RTEXITCODE_SUCCESS)
     1155    {
     1156        /*
     1157         * Now create a PKCS#7 signature of the encrypted signature from the selected signer info.
     1158         */
     1159        void                *pvSigned      = NULL;
     1160        PRTCRPKCS7SIGNEDDATA pTsSignedData = NULL;
     1161        RTCRPKCS7CONTENTINFO TsContentInfo;
     1162        rcExit = Pkcs7SignStuff("timestamp", pSignerInfo->EncryptedDigest.Asn1Core.uData.pv,
     1163                                pSignerInfo->EncryptedDigest.Asn1Core.cb, &AuthAttribs, NIL_RTCRSTORE /*hAdditionalCerts*/,
     1164                                RTCRPKCS7SIGN_SD_F_DEATCHED, RTDIGESTTYPE_SHA1, pTimestampCert, hTimestampKey, cVerbosity,
     1165                                &pvSigned, NULL /*pcbSigned*/, &TsContentInfo, &pTsSignedData);
     1166        if (rcExit == RTEXITCODE_SUCCESS)
     1167        {
     1168
     1169            /*
     1170             * If we're replacing existing timestamp signatures, remove old ones now.
     1171             */
     1172            if (   fReplaceExisting
     1173                && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->UnauthenticatedAttributes))
     1174            {
     1175                uint32_t iItem = pSignerInfo->UnauthenticatedAttributes.cItems;
     1176                while (iItem-- > 0)
     1177                {
     1178                    PRTCRPKCS7ATTRIBUTE pAttr = pSignerInfo->UnauthenticatedAttributes.papItems[iItem];
     1179                    if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES) /* ASSUMES all counter sigs are timstamps */
     1180                    {
     1181                        if (cVerbosity > 1)
     1182                            RTMsgInfo("Removing counter signature in attribute #%u\n", iItem);
     1183                        rc = RTCrPkcs7Attributes_Erase(&pSignerInfo->UnauthenticatedAttributes, iItem);
     1184                        if (RT_FAILURE(rc))
     1185                            rcExit = RTMsgErrorExitFailure("RTCrPkcs7Attributes_Erase failed on #%u: %Rrc", iItem, rc);
     1186                    }
     1187                }
     1188            }
     1189
     1190            /*
     1191             * Add the new one.
     1192             */
     1193            if (rcExit == RTEXITCODE_SUCCESS)
     1194                rcExit = SignToolPkcs7_PrependCounterSignature(pSignerInfo, pTsSignedData->SignerInfos.papItems[0], cVerbosity);
     1195
     1196            /*
     1197             * Make sure the signing certificate is included.
     1198             */
     1199            if (rcExit == RTEXITCODE_SUCCESS)
     1200                rcExit = SignToolPkcs7_AppendCertificate(pSignedData, pTimestampCert);
     1201
     1202            /*
     1203             * Clean up.
     1204             */
     1205            RTCrPkcs7ContentInfo_Delete(&TsContentInfo);
     1206            RTMemTmpFree(pvSigned);
     1207        }
     1208    }
     1209    RTCrPkcs7Attributes_Delete(&AuthAttribs);
     1210
     1211    RT_NOREF(cVerbosity, fReplaceExisting, fTimestampTypeOld);
     1212    return rcExit;
     1213}
     1214
     1215#endif /* !IPRT_IN_BUILD_TOOL */
     1216
     1217
     1218/*********************************************************************************************************************************
     1219*   The 'extract-exe-signer-cert' command.                                                                                       *
     1220*********************************************************************************************************************************/
     1221
    8891222static RTEXITCODE HelpExtractExeSignerCert(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel)
    8901223{
    8911224    RT_NOREF_PV(enmLevel);
    892     RTStrmPrintf(pStrm, "extract-exe-signer-cert [--ber|--cer|--der] [--signature-index|-i <num>] [--exe|-e] <exe> [--output|-o] <outfile.cer>\n");
     1225    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     1226                        "extract-exe-signer-cert [--ber|--cer|--der] [--signature-index|-i <num>] [--exe|-e] <exe> [--output|-o] <outfile.cer>\n");
    8931227    return RTEXITCODE_SUCCESS;
    8941228}
     
    10161350
    10171351
    1018 /*
    1019  * The 'add-nested-exe-signature' command.
    1020  */
     1352/*********************************************************************************************************************************
     1353*   The 'add-nested-exe-signature' command.                                                                                      *
     1354*********************************************************************************************************************************/
     1355
    10211356static RTEXITCODE HelpAddNestedExeSignature(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel)
    10221357{
    10231358    RT_NOREF_PV(enmLevel);
    1024     RTStrmPrintf(pStrm, "add-nested-exe-signature [-v|--verbose] [-d|--debug] [-p|--prepend] <destination-exe> <source-exe>\n");
     1359    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     1360                        "add-nested-exe-signature [-v|--verbose] [-d|--debug] [-p|--prepend] <destination-exe> <source-exe>\n");
    10251361    if (enmLevel == RTSIGNTOOLHELP_FULL)
    1026         RTStrmPrintf(pStrm,
    1027                      "\n"
    1028                      "The --debug option allows the source-exe to be omitted in order to test the\n"
    1029                      "encoding and PE file modification.\n"
    1030                      "\n"
    1031                      "The --prepend option puts the nested signature first rather than appending it\n"
    1032                      "to the end of of the nested signature set.  Windows reads nested signatures in\n"
    1033                      "reverse order, so --prepend will logically putting it last.\n"
    1034                      );
     1362        RTStrmWrappedPrintf(pStrm, 0,
     1363                            "\n"
     1364                            "The --debug option allows the source-exe to be omitted in order to test the "
     1365                            "encoding and PE file modification.\n"
     1366                            "\n"
     1367                            "The --prepend option puts the nested signature first rather than appending it "
     1368                            "to the end of of the nested signature set.  Windows reads nested signatures in "
     1369                            "reverse order, so --prepend will logically putting it last.\n");
    10351370    return RTEXITCODE_SUCCESS;
    10361371}
     
    11241459
    11251460
    1126 /*
    1127  * The 'add-nested-cat-signature' command.
    1128  */
     1461/*********************************************************************************************************************************
     1462*   The 'add-nested-cat-signature' command.                                                                                      *
     1463*********************************************************************************************************************************/
     1464
    11291465static RTEXITCODE HelpAddNestedCatSignature(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel)
    11301466{
    11311467    RT_NOREF_PV(enmLevel);
    1132     RTStrmPrintf(pStrm, "add-nested-cat-signature [-v|--verbose] [-d|--debug] [-p|--prepend] <destination-cat> <source-cat>\n");
     1468    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     1469                        "add-nested-cat-signature [-v|--verbose] [-d|--debug] [-p|--prepend] <destination-cat> <source-cat>\n");
    11331470    if (enmLevel == RTSIGNTOOLHELP_FULL)
    1134         RTStrmPrintf(pStrm,
    1135                      "\n"
    1136                      "The --debug option allows the source-cat to be omitted in order to test the\n"
    1137                      "ASN.1 re-encoding of the destination catalog file.\n"
    1138                      "\n"
    1139                      "The --prepend option puts the nested signature first rather than appending it\n"
    1140                      "to the end of of the nested signature set.  Windows reads nested signatures in\n"
    1141                      "reverse order, so --prepend will logically putting it last.\n"
    1142                      );
     1471        RTStrmWrappedPrintf(pStrm, 0,
     1472                            "\n"
     1473                            "The --debug option allows the source-cat to be omitted in order to test the "
     1474                            "ASN.1 re-encoding of the destination catalog file.\n"
     1475                            "\n"
     1476                            "The --prepend option puts the nested signature first rather than appending it "
     1477                            "to the end of of the nested signature set.  Windows reads nested signatures in "
     1478                            "reverse order, so --prepend will logically putting it last.\n");
    11431479    return RTEXITCODE_SUCCESS;
    11441480}
     
    12331569#ifndef IPRT_IN_BUILD_TOOL
    12341570
     1571/*********************************************************************************************************************************
     1572*   The 'add-timestamp-exe-signature' command.                                                                                      *
     1573*********************************************************************************************************************************/
     1574
     1575static RTEXITCODE HelpAddTimestampExeSignature(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel)
     1576{
     1577    RT_NOREF_PV(enmLevel);
     1578
     1579    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     1580                        "add-timestamp-exe-signature [-v|--verbose] [--signature-index|-i <num>] "
     1581                        "[--timestamp-cert-file <file>] "
     1582                        "[--timestamp-type old|new] "
     1583                        "[--timestamp-date <fake-isots>] "
     1584                        "[--timestamp-year <fake-year>] "
     1585                        "[--replace-existing|-r] "
     1586                        "<exe>\n");
     1587    if (enmLevel == RTSIGNTOOLHELP_FULL)
     1588        RTStrmWrappedPrintf(pStrm, 0,
     1589                            "This is mainly to test timestamp code.\n"
     1590                            "\n"
     1591                            "The --timestamp-date option takes an ISO timestamp, but will replace the time part with the "
     1592                            "current time.\n"
     1593                            "\n");
     1594    return RTEXITCODE_SUCCESS;
     1595}
     1596
     1597
     1598static RTEXITCODE HandleAddTimestampExeSignature(int cArgs, char **papszArgs)
     1599{
     1600    RTERRINFOSTATIC ErrInfo;
     1601
     1602    /*
     1603     * Parse arguments.
     1604     */
     1605    static const RTGETOPTDEF s_aOptions[] =
     1606    {
     1607        { "--signature-index",      'i',                        RTGETOPT_REQ_UINT32 },
     1608        { "--timestamp-cert-file",  OPT_TIMESTAMP_CERT_FILE,    RTGETOPT_REQ_STRING },
     1609        { "--timestamp-key-file",   OPT_TIMESTAMP_KEY_FILE,     RTGETOPT_REQ_STRING },
     1610        { "--timestamp-type",       OPT_TIMESTAMP_TYPE,         RTGETOPT_REQ_STRING },
     1611        { "--timestamp-date",       OPT_TIMESTAMP_DATE,         RTGETOPT_REQ_STRING },
     1612        { "--timestamp-year",       OPT_TIMESTAMP_YEAR,         RTGETOPT_REQ_UINT32 },
     1613        { "--replace-existing",     'r',                        RTGETOPT_REQ_NOTHING },
     1614        { "--verbose",              'v',                        RTGETOPT_REQ_NOTHING },
     1615    };
     1616
     1617    unsigned                cVerbosity              = 0;
     1618    unsigned                iSignature              = 0;
     1619    bool                    fReplaceExisting        = false;
     1620    bool                    fTimestampTypeOld       = true;
     1621    RTCRX509CERTIFICATE     TimestampCertificate;               /* leaked */
     1622    PCRTCRX509CERTIFICATE   pTimestampCertificate   = NULL;
     1623    RTCRKEY                 hTimestampPrivateKey    = NIL_RTCRKEY;
     1624    RTTIMESPEC              SigningTime;
     1625    RTTimeNow(&SigningTime);
     1626
     1627    RTGETOPTSTATE   GetState;
     1628    int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1629    AssertRCReturn(rc, RTEXITCODE_FAILURE);
     1630
     1631    RTEXITCODE      rcExit = RTEXITCODE_SUCCESS;
     1632    RTGETOPTUNION   ValueUnion;
     1633    int             ch;
     1634    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     1635    {
     1636        switch (ch)
     1637        {
     1638            case 'i':
     1639                iSignature = ValueUnion.u32;
     1640                break;
     1641
     1642            case OPT_TIMESTAMP_CERT_FILE:
     1643            {
     1644                if (pTimestampCertificate == &TimestampCertificate)
     1645                    RTCrX509Certificate_Delete(&TimestampCertificate);
     1646                rc = RTCrX509Certificate_ReadFromFile(&TimestampCertificate, ValueUnion.psz, 0, &g_RTAsn1DefaultAllocator,
     1647                                                      RTErrInfoInitStatic(&ErrInfo));
     1648                if (RT_FAILURE(rc))
     1649                    return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim",
     1650                                                 ValueUnion.psz, rc, &ErrInfo.Core);
     1651                pTimestampCertificate = &TimestampCertificate;
     1652                break;
     1653            }
     1654
     1655            case OPT_TIMESTAMP_KEY_FILE:
     1656                RTCrKeyRelease(hTimestampPrivateKey);
     1657                rc = RTCrKeyCreateFromFile(&hTimestampPrivateKey, 0 /*fFlags*/, ValueUnion.psz,
     1658                                           NULL /*pszPassword*/, RTErrInfoInitStatic(&ErrInfo));
     1659                if (RT_FAILURE(rc))
     1660                    return RTMsgErrorExitFailure("Error reading private key from '%s': %Rrc%#RTeim",
     1661                                                 ValueUnion.psz, rc, &ErrInfo.Core);
     1662                break;
     1663
     1664            case OPT_TIMESTAMP_TYPE:
     1665                if (strcmp(ValueUnion.psz, "old") == 0)
     1666                    fTimestampTypeOld = true;
     1667                else if (strcmp(ValueUnion.psz, "new") == 0)
     1668                    fTimestampTypeOld = false;
     1669                else
     1670                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown timestamp type: %s", ValueUnion.psz);
     1671                break;
     1672
     1673            case OPT_TIMESTAMP_DATE:
     1674            {
     1675                RTTIMESPEC Tmp;
     1676                if (RTTimeSpecFromString(&Tmp, ValueUnion.psz))
     1677                {
     1678                    RTTIME Time, Now;
     1679                    RTTimeExplode(&Time, &Tmp);
     1680                    RTTimeExplode(&Now, RTTimeNow(&Tmp));
     1681                    Time.u8Hour        = Now.u8Hour;
     1682                    Time.u8Minute      = Now.u8Minute;
     1683                    Time.u8Second      = Now.u8Second;
     1684                    Time.u32Nanosecond = Now.u32Nanosecond;
     1685                    RTTimeImplode(&SigningTime, &Time);
     1686                }
     1687                else
     1688                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp: %s", ValueUnion.psz);
     1689                break;
     1690            }
     1691
     1692            case OPT_TIMESTAMP_YEAR:
     1693            {
     1694                if (ValueUnion.u32 <= 1950 || ValueUnion.u32 >= 2050)
     1695                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp year: %u, valid range 1951-2049", ValueUnion.u32);
     1696
     1697                RTTIME Time;
     1698                RTTimeExplode(&Time, RTTimeNow(&SigningTime));
     1699                Time.i32Year = (int32_t)ValueUnion.u32;
     1700                if (Time.u8MonthDay == 29 && Time.u8Month == 2 && !RTTimeIsLeapYear(Time.i32Year))
     1701                    Time.u8MonthDay = 28;
     1702                RTTimeImplode(&SigningTime, &Time);
     1703                break;
     1704            }
     1705
     1706            case 'r':
     1707                fReplaceExisting = true;
     1708                break;
     1709
     1710            case 'v':
     1711                cVerbosity++;
     1712                break;
     1713
     1714            case 'V':
     1715                return HandleVersion(cArgs, papszArgs);
     1716
     1717            case 'h':
     1718                return HelpAddTimestampExeSignature(g_pStdOut, RTSIGNTOOLHELP_FULL);
     1719
     1720            case VINF_GETOPT_NOT_OPTION:
     1721            {
     1722                /* check that we've got all the info we need: */
     1723                if (!pTimestampCertificate)
     1724                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No timestamp certificate was specified");
     1725                if (hTimestampPrivateKey == NIL_RTCRKEY)
     1726                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No timestamp private key was specified");
     1727
     1728                /* Do the work: */
     1729                SIGNTOOLPKCS7EXE Exe;
     1730                RTEXITCODE rcExit2 = SignToolPkcs7Exe_InitFromFile(&Exe, ValueUnion.psz, cVerbosity);
     1731                if (rcExit2 == RTEXITCODE_SUCCESS)
     1732                {
     1733                    rcExit2 = SignToolPkcs7_AddTimestampSignature(&Exe, cVerbosity, iSignature, fReplaceExisting,
     1734                                                                  fTimestampTypeOld, SigningTime,
     1735                                                                  pTimestampCertificate, hTimestampPrivateKey);
     1736                    if (rcExit2 == RTEXITCODE_SUCCESS)
     1737                        rcExit2 = SignToolPkcs7_Encode(&Exe, cVerbosity);
     1738                    if (rcExit2 == RTEXITCODE_SUCCESS)
     1739                        rcExit2 = SignToolPkcs7Exe_WriteSignatureToFile(&Exe, cVerbosity);
     1740                    SignToolPkcs7Exe_Delete(&Exe);
     1741                }
     1742                if (rcExit2 != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS)
     1743                    rcExit = rcExit2;
     1744                break;
     1745            }
     1746
     1747            default:
     1748                return RTGetOptPrintError(ch, &ValueUnion);
     1749        }
     1750    }
     1751    return rcExit;
     1752}
     1753
     1754#endif /*!IPRT_IN_BUILD_TOOL */
     1755#ifndef IPRT_IN_BUILD_TOOL
     1756
    12351757/*
    12361758 * The 'verify-exe' command.
     
    12391761{
    12401762    RT_NOREF_PV(enmLevel);
    1241     RTStrmPrintf(pStrm,
    1242                  "verify-exe [--verbose|--quiet] [--kernel] [--root <root-cert.der>] [--additional <supp-cert.der>]\n"
    1243                  "        [--type <win|osx>] <exe1> [exe2 [..]]\n");
     1763    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     1764                        "verify-exe [--verbose|--quiet] [--kernel] [--root <root-cert.der>] [--additional <supp-cert.der>] "
     1765                        "[--type <win|osx>] <exe1> [exe2 [..]]\n");
    12441766    return RTEXITCODE_SUCCESS;
    12451767}
     
    23502872{
    23512873    RT_NOREF_PV(enmLevel);
    2352     RTStrmPrintf(pStrm,
    2353                  "show-exe [--verbose|-v] [--quiet|-q] <exe1> [exe2 [..]]\n");
     2874    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT, "show-exe [--verbose|-v] [--quiet|-q] <exe1> [exe2 [..]]\n");
    23542875    return RTEXITCODE_SUCCESS;
    23552876}
     
    24282949{
    24292950    RT_NOREF_PV(enmLevel);
    2430     RTStrmPrintf(pStrm,
    2431                  "show-cat [--verbose|-v] [--quiet|-q] <cat1> [cat2 [..]]\n");
     2951    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT, "show-cat [--verbose|-v] [--quiet|-q] <cat1> [cat2 [..]]\n");
    24322952    return RTEXITCODE_SUCCESS;
    24332953}
     
    25073027{
    25083028    RT_NOREF_PV(enmLevel);
    2509     RTStrmPrintf(pStrm,
    2510                  "make-tainfo [--verbose|--quiet] [--cert <cert.der>]  [-o|--output] <tainfo.der>\n");
     3029    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
     3030                        "make-tainfo [--verbose|--quiet] [--cert <cert.der>]  [-o|--output] <tainfo.der>\n");
    25113031    return RTEXITCODE_SUCCESS;
    25123032}
     
    27643284    { "add-nested-cat-signature",       HandleAddNestedCatSignature,        HelpAddNestedCatSignature },
    27653285#ifndef IPRT_IN_BUILD_TOOL
     3286    { "add-timestamp-exe-signature",    HandleAddTimestampExeSignature,     HelpAddTimestampExeSignature },
     3287#endif
     3288#ifndef IPRT_IN_BUILD_TOOL
    27663289    { "verify-exe",                     HandleVerifyExe,                    HelpVerifyExe },
    27673290#endif
     
    27923315    RTSIGNTOOLHELP  enmLevel = cArgs <= 1 ? RTSIGNTOOLHELP_USAGE : RTSIGNTOOLHELP_FULL;
    27933316    uint32_t        cShowed  = 0;
     3317    uint32_t        cchWidth;
     3318    if (RT_FAILURE(RTStrmQueryTerminalWidth(g_pStdOut, &cchWidth)))
     3319        cchWidth = 80;
    27943320    for (uint32_t iCmd = 0; iCmd < RT_ELEMENTS(g_aCommands); iCmd++)
    27953321    {
     
    28003326                fShow = true;
    28013327            else
    2802             {
    28033328                for (int iArg = 1; iArg < cArgs; iArg++)
    28043329                    if (RTStrSimplePatternMultiMatch(papszArgs[iArg], RTSTR_MAX, g_aCommands[iCmd].pszCmd, RTSTR_MAX, NULL))
     
    28073332                        break;
    28083333                    }
    2809             }
    28103334            if (fShow)
    28113335            {
     3336                if (cShowed && enmLevel == RTSIGNTOOLHELP_FULL)
     3337                    RTPrintf("%.*s\n", RT_MIN(cchWidth, 100),
     3338                             "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
    28123339                g_aCommands[iCmd].pfnHelp(g_pStdOut, enmLevel);
    28133340                cShowed++;
Note: See TracChangeset for help on using the changeset viewer.

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