VirtualBox

Changeset 106264 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Oct 9, 2024 8:50:12 PM (7 weeks ago)
Author:
vboxsync
Message:

RTSignTool: Extended the extract-exe-signer-cert, extract-timestamp-root and extract-signer-root commands with a --as-c-array=name option that gets all the designated certificate in a form a C compiler can understand. bugref:10771

File:
1 edited

Legend:

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

    r106061 r106264  
    15851585
    15861586
     1587/**
     1588 * Count the number of signatures, nested or otherwise.
     1589 *
     1590 * @returns Number of signatures.
     1591 * @param   pThis           The PKCS\#7 structure to search.
     1592 *
     1593 * @todo    Move into SPC or PKCS\#7.
     1594 */
     1595static uint32_t SignToolPkcs7_CountSignatures(PSIGNTOOLPKCS7 pThis)
     1596{
     1597    uint32_t             iNextSignature = 0;
     1598    PRTCRPKCS7SIGNEDDATA pSignedData    = NULL;
     1599    SignToolPkcs7_FindNestedSignatureByIndexWorker(pThis->pSignedData, &iNextSignature, UINT32_MAX / 2, &pSignedData);
     1600    return iNextSignature;
     1601}
     1602
    15871603
    15881604/**
     
    32943310    RT_NOREF_PV(enmLevel);
    32953311    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
    3296                         "extract-exe-signer-cert [--ber|--cer|--der] [--signature-index|-i <num>] [--input|--exe|-e] <exe> [--output|-o] <outfile.cer>\n");
     3312                        "extract-exe-signer-cert [--as-c-array=name|--ber|--cer|--der] [--signature-index|-i <num>] [--input|--exe|-e] <exe> [--output|-o] <outfile.cer/h>\n");
    32973313    return RTEXITCODE_SUCCESS;
    32983314}
     
    33313347
    33323348
     3349static void PrintCertAsCArray(PCRTCRX509CERTIFICATE pCert, uint32_t iSignature, const char *pszBaseNm, PRTSTREAM pStrm)
     3350{
     3351    uint32_t const        cbCert = pCert->SeqCore.Asn1Core.cbHdr     + pCert->SeqCore.Asn1Core.cb;
     3352    uint8_t const * const pbCert = pCert->SeqCore.Asn1Core.uData.pu8 - pCert->SeqCore.Asn1Core.cbHdr;
     3353    if (iSignature == UINT32_MAX)
     3354        RTStrmPrintf(pStrm,
     3355                     "uint32_t const g_cb%s = %u;\n"
     3356                     "uint8_t const  g_ab%s[%u] =\n"
     3357                     "{",
     3358                     pszBaseNm, cbCert, pszBaseNm, cbCert);
     3359    else
     3360        RTStrmPrintf(pStrm, "static uint8_t const g_ab%sCert%u[%u] =\n{", pszBaseNm, iSignature, cbCert);
     3361    for (uint32_t off = 0; off < cbCert; off++)
     3362    {
     3363        if (off % 16 == 0)
     3364            RTStrmPrintf(pStrm, "\n   ");
     3365        RTStrmPrintf(pStrm, " %#04x,", pbCert[off]);
     3366    }
     3367    RTStrmPrintf(pStrm, "\n};\n\n");
     3368}
     3369
     3370
     3371static void PrintCertTableAsC(uint32_t cSignatures, const char *pszBaseNm, PRTSTREAM pStrm)
     3372{
     3373    RTStrmPrintf(pStrm,
     3374                 "uint32_t const g_c%s = %u;\n"
     3375                 "struct { uint8_t const *pbCert; size_t cbCert; } const g_a%s[%u] =\n"
     3376                 "{\n"
     3377                 , pszBaseNm, cSignatures, pszBaseNm, cSignatures ? cSignatures : 1);
     3378    for (uint32_t iSignature = 0; iSignature < cSignatures; iSignature++)
     3379        RTStrmPrintf(pStrm, "    { g_ab%sCert%u, sizeof(g_ab%sCert%u) },\n",
     3380                     pszBaseNm, iSignature, pszBaseNm, iSignature);
     3381    if (!cSignatures)
     3382        RTStrmPrintf(pStrm, "    { NULL, 0 } /* dummy */ \n");
     3383    RTStrmPrintf(pStrm, "};\n");
     3384}
     3385
     3386
     3387static RTEXITCODE WriteCertToFileAsC(PCRTCRX509CERTIFICATE pCert, const char *pszFilename, bool fForce, const char *pszBaseNm)
     3388{
     3389    RTEXITCODE rcExit;
     3390    PRTSTREAM  pStrm  = NULL;
     3391    int rc = RTStrmOpen(pszFilename, fForce ? "wt+" : "wtx", &pStrm);
     3392    if (RT_SUCCESS(rc))
     3393    {
     3394        PrintCertAsCArray(pCert, UINT32_MAX, pszBaseNm, pStrm);
     3395        rc = RTStrmClose(pStrm);
     3396        if (RT_SUCCESS(rc))
     3397            rcExit = RTEXITCODE_SUCCESS;
     3398        else
     3399            rcExit = RTMsgErrorExitFailure("Error writing/closing '%s': %Rrc", pszFilename, rc);
     3400    }
     3401    else
     3402        rcExit = RTMsgErrorExitFailure("Failed to open '%s' for writing: %Rrc", pszFilename, rc);
     3403    return rcExit;
     3404}
     3405
     3406
     3407
    33333408static RTEXITCODE HandleExtractExeSignerCert(int cArgs, char **papszArgs)
    33343409{
     
    33463421        { "--signature-index",  'i', RTGETOPT_REQ_UINT32  },
    33473422        { "--force",            'f', RTGETOPT_REQ_NOTHING },
     3423        { "--as-c-array",       'C', RTGETOPT_REQ_STRING  },
    33483424    };
    33493425
     
    33543430    uint32_t    fCursorFlags = RTASN1CURSOR_FLAGS_DER;
    33553431    uint32_t    iSignature   = 0;
     3432    const char *pszCArrayNm  = NULL;
    33563433    bool        fForce       = false;
    33573434
     
    33753452            case 'h':   return HelpExtractExeSignerCert(g_pStdOut, RTSIGNTOOLHELP_FULL);
    33763453
     3454            case 'C':
     3455                pszCArrayNm = *ValueUnion.psz ? ValueUnion.psz : NULL;
     3456                if (pszCArrayNm)
     3457                    iSignature = UINT32_MAX;
     3458                break;
     3459
    33773460            case VINF_GETOPT_NOT_OPTION:
    33783461                if (!pszExe)
     
    34033486    if (rcExit == RTEXITCODE_SUCCESS)
    34043487    {
    3405         /* Find the signing certificate (ASSUMING that the certificate used is shipped in the set of certificates). */
    3406         PRTCRPKCS7SIGNEDDATA  pSignedData;
    3407         PCRTCRPKCS7SIGNERINFO pSignerInfo = SignToolPkcs7_FindNestedSignatureByIndex(&This, iSignature, &pSignedData);
    3408         rcExit = RTEXITCODE_FAILURE;
    3409         if (pSignerInfo)
    3410         {
    3411             PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSignedData->SignerInfos.papItems[0]->IssuerAndSerialNumber;
    3412             PCRTCRX509CERTIFICATE pCert;
    3413             pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
    3414                                                                         &pISN->Name, &pISN->SerialNumber);
    3415             if (pCert)
     3488        if (pszCArrayNm == NULL || iSignature != UINT32_MAX)
     3489        {
     3490            /* Find the signing certificate (ASSUMING that the certificate used is shipped in the set of certificates). */
     3491            PRTCRPKCS7SIGNEDDATA  pSignedData;
     3492            PCRTCRPKCS7SIGNERINFO pSignerInfo = SignToolPkcs7_FindNestedSignatureByIndex(&This, iSignature, &pSignedData);
     3493            rcExit = RTEXITCODE_FAILURE;
     3494            if (pSignerInfo)
    34163495            {
    3417                 /*
    3418                  * Write it out.
    3419                  */
    3420                 rcExit = WriteCertToFile(pCert, pszOut, fForce);
     3496                PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSignedData->SignerInfos.papItems[0]->IssuerAndSerialNumber;
     3497                PCRTCRX509CERTIFICATE pCert;
     3498                pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
     3499                                                                            &pISN->Name, &pISN->SerialNumber);
     3500                if (pCert)
     3501                {
     3502                    /*
     3503                     * Write it out.
     3504                     */
     3505                    if (pszCArrayNm == NULL)
     3506                        rcExit = WriteCertToFile(pCert, pszOut, fForce);
     3507                    else
     3508                        rcExit = WriteCertToFileAsC(pCert, pszOut, fForce, pszCArrayNm);
     3509                }
     3510                else
     3511                    RTMsgError("Certificate not found.");
    34213512            }
    34223513            else
    3423                 RTMsgError("Certificate not found.");
     3514                RTMsgError("Could not locate signature #%u!", iSignature);
    34243515        }
    34253516        else
    3426             RTMsgError("Could not locate signature #%u!", iSignature);
     3517        {
     3518            uint32_t const cSignatures = SignToolPkcs7_CountSignatures(&This);
     3519            if (cSignatures)
     3520            {
     3521                PRTSTREAM pStrm = NULL;
     3522                rc = RTStrmOpen(pszOut, fForce ? "wt+" : "wtx", &pStrm);
     3523                if (RT_SUCCESS(rc))
     3524                {
     3525                    for (iSignature = 0; iSignature < cSignatures; iSignature++)
     3526                    {
     3527                        PRTCRPKCS7SIGNEDDATA  pSignedData;
     3528                        PCRTCRPKCS7SIGNERINFO pSignerInfo = SignToolPkcs7_FindNestedSignatureByIndex(&This, iSignature, &pSignedData);
     3529                        if (!pSignerInfo)
     3530                        {
     3531                            rcExit = RTMsgErrorExitFailure("Could not locate signature #%u out of %u!", iSignature, cSignatures);
     3532                            break;
     3533                        }
     3534                        PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSignedData->SignerInfos.papItems[0]->IssuerAndSerialNumber;
     3535                        PCRTCRX509CERTIFICATE pCert;
     3536                        pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
     3537                                                                                    &pISN->Name, &pISN->SerialNumber);
     3538                        if (pCert)
     3539                            PrintCertAsCArray(pCert, iSignature, pszCArrayNm, pStrm);
     3540                        else
     3541                        {
     3542                            rcExit = RTMsgErrorExitFailure("Could not locate certificate for signature #%u (out of %u)!",
     3543                                                           iSignature, cSignatures);
     3544                            break;
     3545                        }
     3546                    }
     3547
     3548                    PrintCertTableAsC(iSignature, pszCArrayNm, pStrm);
     3549
     3550                    rc = RTStrmClose(pStrm);
     3551                    if (RT_FAILURE(rc))
     3552                        rcExit = RTMsgErrorExitFailure("Error writing/closing '%s': %Rrc", pszOut, rc);
     3553                }
     3554                else
     3555                    rcExit = RTMsgErrorExitFailure("Failed to open '%s' for writing: %Rrc", pszOut, rc);
     3556            }
     3557            else
     3558                rcExit = RTMsgErrorExitFailure("No signatures found!");
     3559        }
    34273560
    34283561        /* Delete the signature data. */
     
    34473580    /** Timestamp or main signature. */
    34483581    bool const  fTimestamp;
     3582    const char *pszBaseNm;
    34493583
    34503584    BaseExtractState(bool a_fTimestamp)
     
    34563590        , fForce(false)
    34573591        , fTimestamp(a_fTimestamp)
     3592        , pszBaseNm(NULL)
    34583593    {
    34593594    }
     
    34943629 * Locates the target signature and certificate collection.
    34953630 */
    3496 static PRTCRPKCS7SIGNERINFO BaseExtractFindSignerInfo(SIGNTOOLPKCS7 *pThis, BaseExtractState *pState,
     3631static PRTCRPKCS7SIGNERINFO BaseExtractFindSignerInfo(SIGNTOOLPKCS7 *pThis, BaseExtractState *pState, bool fOptional,
    34973632                                                      PRTCRPKCS7SIGNEDDATA  *ppSignedData, PCRTCRPKCS7SETOFCERTS *ppCerts)
    34983633{
     
    35573692                }
    35583693            }
    3559             RTMsgError("Cound not find a timestamp signature associated with signature #%u!", pState->iSignature);
     3694            if (!fOptional)
     3695                RTMsgError("Cound not find a timestamp signature associated with signature #%u!", pState->iSignature);
    35603696            pSignerInfo = NULL;
    35613697        }
     
    35663702        }
    35673703    }
    3568     else
     3704    else if (!fOptional)
    35693705        RTMsgError("Could not locate signature #%u!", pState->iSignature);
    35703706    return pSignerInfo;
     
    35803716
    35813717
    3582 static RTEXITCODE RootExtractWorker2(SIGNTOOLPKCS7 *pThis, RootExtractState *pState, PRTERRINFOSTATIC pStaticErrInfo)
     3718static RTEXITCODE RootExtractWorker3(SIGNTOOLPKCS7 *pThis, RootExtractState *pState, PRTSTREAM pStrm, uint32_t *pidxCert,
     3719                                     PRTERRINFOSTATIC pStaticErrInfo)
    35833720{
    35843721    /*
    35853722     * Locate the target signature.
    35863723     */
     3724    bool const            fOptional = pidxCert != NULL && pStrm != NULL && pState->fTimestamp /*fOptional*/;
    35873725    PRTCRPKCS7SIGNEDDATA  pSignedData;
    35883726    PCRTCRPKCS7SETOFCERTS pCerts;
    3589     PCRTCRPKCS7SIGNERINFO pSignerInfo = BaseExtractFindSignerInfo(pThis,pState, &pSignedData, &pCerts);
     3727    PCRTCRPKCS7SIGNERINFO pSignerInfo = BaseExtractFindSignerInfo(pThis, pState, fOptional, &pSignedData, &pCerts);
    35903728    if (!pSignerInfo)
    3591         return RTMsgErrorExitFailure("Could not locate signature #%u!", pState->iSignature);
     3729    {
     3730        if (!fOptional)
     3731            return RTMsgErrorExitFailure("Could not locate signature #%u!", pState->iSignature);
     3732        return RTEXITCODE_SUCCESS;
     3733    }
     3734
    35923735
    35933736    /* The next bit is modelled on first half of rtCrPkcs7VerifySignerInfo. */
     
    36783821                                         * Now copy out the certificate.
    36793822                                         */
    3680                                         rcExit = WriteCertToFile(pRootCert, pState->pszOut, pState->fForce);
     3823                                        if (!pState->pszBaseNm)
     3824                                            rcExit = WriteCertToFile(pRootCert, pState->pszOut, pState->fForce);
     3825                                        else if (!pStrm)
     3826                                            rcExit = WriteCertToFileAsC(pRootCert, pState->pszOut, pState->fForce,
     3827                                                                        pState->pszBaseNm);
     3828                                        else
     3829                                        {
     3830                                            PrintCertAsCArray(pRootCert, *pidxCert, pState->pszBaseNm, pStrm);
     3831                                            *pidxCert += 1;
     3832                                            rcExit = RTEXITCODE_SUCCESS;
     3833                                        }
    36813834                                        break;
    36823835                                    }
     
    37173870
    37183871
     3872static RTEXITCODE RootExtractWorker2(SIGNTOOLPKCS7 *pThis, RootExtractState *pState, PRTERRINFOSTATIC pStaticErrInfo)
     3873{
     3874    if (!pState->pszBaseNm || pState->iSignature != UINT32_MAX)
     3875        return RootExtractWorker3(pThis, pState, NULL, NULL, pStaticErrInfo);
     3876
     3877    /*
     3878     * Dump all these certificates.
     3879     */
     3880    uint32_t const cSignatures = SignToolPkcs7_CountSignatures(pThis);
     3881    if (!cSignatures)
     3882        return RTMsgErrorExitFailure("No signatures found!");
     3883
     3884    PRTSTREAM pStrm = NULL;
     3885    int rc = RTStrmOpen(pState->pszOut, pState->fForce ? "wt+" : "wtx", &pStrm);
     3886    if (RT_FAILURE(rc))
     3887        return RTMsgErrorExitFailure("Failed to open '%s' for writing: %Rrc", pState->pszOut, rc);
     3888
     3889    uint32_t   idxCert = 0; /* tracking separately, as we ignore missing timestamp chains. */
     3890    RTEXITCODE rcExit  = RTEXITCODE_SUCCESS;
     3891    for (uint32_t iSignature = 0; iSignature < cSignatures && rcExit == RTEXITCODE_SUCCESS; iSignature++)
     3892    {
     3893        pState->iSignature = iSignature;
     3894        rcExit = RootExtractWorker3(pThis, pState, pStrm, &idxCert, pStaticErrInfo);
     3895    }
     3896
     3897    PrintCertTableAsC(idxCert, pState->pszBaseNm, pStrm);
     3898
     3899    rc = RTStrmClose(pStrm);
     3900    if (RT_FAILURE(rc))
     3901        rcExit = RTMsgErrorExitFailure("Error writing/closing '%s': %Rrc", pState->pszOut, rc);
     3902    return rcExit;
     3903}
     3904
     3905
    37193906static RTEXITCODE RootExtractWorker(RootExtractState *pState, PRTERRINFOSTATIC pStaticErrInfo)
    37203907{
     
    37653952    RT_NOREF_PV(enmLevel);
    37663953    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
    3767                         "extract-%s-root [-v|--verbose] [-q|--quiet] [--signature-index|-i <num>] [--root <root-cert.der>] "
    3768                         "[--self-signed-roots-from-system] [--additional <supp-cert.der>] [--intermediate-certs-from-system] "
    3769                         "[--input] <signed-file> [-f|--force] [--output|-o] <outfile.cer>\n",
     3954                        "extract-%s-root [-v|--verbose] [-q|--quiet] [--as-c-array <name>] [--signature-index|-i <num>] "
     3955                        "[--root <root-cert.der>] [--self-signed-roots-from-system] [--additional <supp-cert.der>] "
     3956                        "[--intermediate-certs-from-system] [--input] <signed-file> "
     3957                        "[-f|--force] [--output|-o] <outfile.cer/h>\n",
    37703958                        fTimestamp ? "timestamp" : "signer");
    37713959    if (enmLevel == RTSIGNTOOLHELP_FULL)
     
    37833971                            "    Controls the noise level.  The '-v' options are accumlative while '-q' is absolute.\n"
    37843972                            "    Default: -q\n"
     3973                            "  -C <name>, --as-c-array <name>\n"
     3974                            "    Output a C header file containing the roots of all signatures (or a selected one if"
     3975                            "--signature-index is used again after this option.\n"
     3976                            "    Default: Output one binary certificate.\n"
    37853977                            "  -i <num>, --signature-index <num>\n"
    37863978                            "    Zero-based index of the signature to extract the root for.\n"
     
    38314023        { "--verbose",                       'v', RTGETOPT_REQ_NOTHING },
    38324024        { "--quiet",                         'q', RTGETOPT_REQ_NOTHING },
     4025        { "--as-c-array",                    'C', RTGETOPT_REQ_STRING  },
    38334026    };
    38344027    RTERRINFOSTATIC  StaticErrInfo;
     
    38734066            case 'V':   return HandleVersion(cArgs, papszArgs);
    38744067            case 'h':   return HelpExtractRootCommon(g_pStdOut, RTSIGNTOOLHELP_FULL, fTimestamp);
     4068
     4069            case 'C':
     4070                State.pszBaseNm = *ValueUnion.psz ? ValueUnion.psz : NULL;
     4071                if (State.pszBaseNm)
     4072                    State.iSignature = UINT32_MAX;
     4073                break;
    38754074
    38764075            case VINF_GETOPT_NOT_OPTION:
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