Changeset 106264 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Oct 9, 2024 8:50:12 PM (7 weeks ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/tools/RTSignTool.cpp
r106061 r106264 1585 1585 1586 1586 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 */ 1595 static 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 1587 1603 1588 1604 /** … … 3294 3310 RT_NOREF_PV(enmLevel); 3295 3311 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"); 3297 3313 return RTEXITCODE_SUCCESS; 3298 3314 } … … 3331 3347 3332 3348 3349 static 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 3371 static 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 3387 static 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 3333 3408 static RTEXITCODE HandleExtractExeSignerCert(int cArgs, char **papszArgs) 3334 3409 { … … 3346 3421 { "--signature-index", 'i', RTGETOPT_REQ_UINT32 }, 3347 3422 { "--force", 'f', RTGETOPT_REQ_NOTHING }, 3423 { "--as-c-array", 'C', RTGETOPT_REQ_STRING }, 3348 3424 }; 3349 3425 … … 3354 3430 uint32_t fCursorFlags = RTASN1CURSOR_FLAGS_DER; 3355 3431 uint32_t iSignature = 0; 3432 const char *pszCArrayNm = NULL; 3356 3433 bool fForce = false; 3357 3434 … … 3375 3452 case 'h': return HelpExtractExeSignerCert(g_pStdOut, RTSIGNTOOLHELP_FULL); 3376 3453 3454 case 'C': 3455 pszCArrayNm = *ValueUnion.psz ? ValueUnion.psz : NULL; 3456 if (pszCArrayNm) 3457 iSignature = UINT32_MAX; 3458 break; 3459 3377 3460 case VINF_GETOPT_NOT_OPTION: 3378 3461 if (!pszExe) … … 3403 3486 if (rcExit == RTEXITCODE_SUCCESS) 3404 3487 { 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) 3416 3495 { 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."); 3421 3512 } 3422 3513 else 3423 RTMsgError("C ertificate not found.");3514 RTMsgError("Could not locate signature #%u!", iSignature); 3424 3515 } 3425 3516 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 } 3427 3560 3428 3561 /* Delete the signature data. */ … … 3447 3580 /** Timestamp or main signature. */ 3448 3581 bool const fTimestamp; 3582 const char *pszBaseNm; 3449 3583 3450 3584 BaseExtractState(bool a_fTimestamp) … … 3456 3590 , fForce(false) 3457 3591 , fTimestamp(a_fTimestamp) 3592 , pszBaseNm(NULL) 3458 3593 { 3459 3594 } … … 3494 3629 * Locates the target signature and certificate collection. 3495 3630 */ 3496 static PRTCRPKCS7SIGNERINFO BaseExtractFindSignerInfo(SIGNTOOLPKCS7 *pThis, BaseExtractState *pState, 3631 static PRTCRPKCS7SIGNERINFO BaseExtractFindSignerInfo(SIGNTOOLPKCS7 *pThis, BaseExtractState *pState, bool fOptional, 3497 3632 PRTCRPKCS7SIGNEDDATA *ppSignedData, PCRTCRPKCS7SETOFCERTS *ppCerts) 3498 3633 { … … 3557 3692 } 3558 3693 } 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); 3560 3696 pSignerInfo = NULL; 3561 3697 } … … 3566 3702 } 3567 3703 } 3568 else 3704 else if (!fOptional) 3569 3705 RTMsgError("Could not locate signature #%u!", pState->iSignature); 3570 3706 return pSignerInfo; … … 3580 3716 3581 3717 3582 static RTEXITCODE RootExtractWorker2(SIGNTOOLPKCS7 *pThis, RootExtractState *pState, PRTERRINFOSTATIC pStaticErrInfo) 3718 static RTEXITCODE RootExtractWorker3(SIGNTOOLPKCS7 *pThis, RootExtractState *pState, PRTSTREAM pStrm, uint32_t *pidxCert, 3719 PRTERRINFOSTATIC pStaticErrInfo) 3583 3720 { 3584 3721 /* 3585 3722 * Locate the target signature. 3586 3723 */ 3724 bool const fOptional = pidxCert != NULL && pStrm != NULL && pState->fTimestamp /*fOptional*/; 3587 3725 PRTCRPKCS7SIGNEDDATA pSignedData; 3588 3726 PCRTCRPKCS7SETOFCERTS pCerts; 3589 PCRTCRPKCS7SIGNERINFO pSignerInfo = BaseExtractFindSignerInfo(pThis, pState, &pSignedData, &pCerts);3727 PCRTCRPKCS7SIGNERINFO pSignerInfo = BaseExtractFindSignerInfo(pThis, pState, fOptional, &pSignedData, &pCerts); 3590 3728 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 3592 3735 3593 3736 /* The next bit is modelled on first half of rtCrPkcs7VerifySignerInfo. */ … … 3678 3821 * Now copy out the certificate. 3679 3822 */ 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 } 3681 3834 break; 3682 3835 } … … 3717 3870 3718 3871 3872 static 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 3719 3906 static RTEXITCODE RootExtractWorker(RootExtractState *pState, PRTERRINFOSTATIC pStaticErrInfo) 3720 3907 { … … 3765 3952 RT_NOREF_PV(enmLevel); 3766 3953 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", 3770 3958 fTimestamp ? "timestamp" : "signer"); 3771 3959 if (enmLevel == RTSIGNTOOLHELP_FULL) … … 3783 3971 " Controls the noise level. The '-v' options are accumlative while '-q' is absolute.\n" 3784 3972 " 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" 3785 3977 " -i <num>, --signature-index <num>\n" 3786 3978 " Zero-based index of the signature to extract the root for.\n" … … 3831 4023 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 3832 4024 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, 4025 { "--as-c-array", 'C', RTGETOPT_REQ_STRING }, 3833 4026 }; 3834 4027 RTERRINFOSTATIC StaticErrInfo; … … 3873 4066 case 'V': return HandleVersion(cArgs, papszArgs); 3874 4067 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; 3875 4074 3876 4075 case VINF_GETOPT_NOT_OPTION:
Note:
See TracChangeset
for help on using the changeset viewer.