Changeset 95613 in vbox
- Timestamp:
- Jul 13, 2022 12:52:44 AM (2 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/crypto/spc.h
r93115 r95613 43 43 * @{ 44 44 */ 45 46 /** Value for RTCR_PKCS9_ID_MS_STATEMENT_TYPE. */ 47 #define RTCRSPC_STMT_TYPE_INDIVIDUAL_CODE_SIGNING "1.3.6.1.4.1.311.2.1.21" 45 48 46 49 /** -
trunk/src/VBox/Runtime/tools/RTSignTool.cpp
r95605 r95613 31 31 #include <iprt/assert.h> 32 32 #include <iprt/buildconfig.h> 33 #include <iprt/ctype.h> 33 34 #include <iprt/err.h> 34 35 #include <iprt/getopt.h> … … 65 66 * Defined Constants And Macros * 66 67 *********************************************************************************************************************************/ 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 68 #define OPT_HASH_PAGES 1000 69 #define OPT_NO_HASH_PAGES 1001 70 #define OPT_CERT_FILE 1002 71 #define OPT_KEY_FILE 1003 72 #define OPT_ADD_CERT 1004 73 74 #define OPT_TIMESTAMP_CERT_FILE 1010 75 #define OPT_TIMESTAMP_KEY_FILE 1011 76 #define OPT_TIMESTAMP_TYPE 1012 77 #define OPT_TIMESTAMP_OVERRIDE 1016 72 78 73 79 … … 133 139 } SHOWEXEPKCS7; 134 140 typedef SHOWEXEPKCS7 *PSHOWEXEPKCS7; 141 142 143 /** 144 * Certificate w/ public key + private key pair for signing. 145 */ 146 typedef struct SIGNTOOLKEYPAIR 147 { 148 RTCRX509CERTIFICATE Cert; 149 PCRTCRX509CERTIFICATE pCertificate; 150 RTCRKEY hPrivateKey; 151 152 SIGNTOOLKEYPAIR() 153 : pCertificate(NULL) 154 , hPrivateKey(NIL_RTCRKEY) 155 { 156 RT_ZERO(Cert); 157 } 158 159 ~SIGNTOOLKEYPAIR() 160 { 161 if (hPrivateKey != NIL_RTCRKEY) 162 { 163 RTCrKeyRelease(hPrivateKey); 164 hPrivateKey = NIL_RTCRKEY; 165 } 166 if (pCertificate == &Cert) 167 { 168 RTCrX509Certificate_Delete(&Cert); 169 pCertificate = NULL; 170 } 171 } 172 173 bool isComplete(void) const 174 { 175 return pCertificate && hPrivateKey != NIL_RTCRKEY; 176 } 177 178 bool isNull(void) const 179 { 180 return pCertificate == NULL && hPrivateKey == NIL_RTCRKEY; 181 } 182 } SIGNTOOLKEYPAIR; 135 183 136 184 … … 915 963 #ifndef IPRT_IN_BUILD_TOOL 916 964 917 static RTEXITCODE AddAuthAttribsForTimestamp(PRTCRPKCS7ATTRIBUTES pAuthAttribs, bool fTimestampTypeOld, 918 RTTIMESPEC SigningTime, PCRTCRX509CERTIFICATE pTimestampCert) 965 static RTEXITCODE SignToolPkcs7_AuthAttribsAddSigningTime(PRTCRPKCS7ATTRIBUTES pAuthAttribs, RTTIMESPEC SigningTime) 919 966 { 920 967 /* … … 945 992 rc = RTAsn1SetOfTimes_Init(pAttr->uValues.pSigningTime, pAttr->Allocation.pAllocator); 946 993 if (RT_FAILURE(rc)) 947 return RTMsgErrorExitFailure("RT CrPkcs7ContentInfos_Init failed: %Rrc", rc);994 return RTMsgErrorExitFailure("RTAsn1SetOfTimes_Init failed: %Rrc", rc); 948 995 949 996 /* Create the timestamp. */ 950 997 iPos = RTAsn1SetOfTimes_Append(pAttr->uValues.pSigningTime); 951 998 if (iPos < 0) 952 return RTMsgErrorExitFailure("RT CrPkcs7SigningTimes_Append failed: %Rrc", iPos);999 return RTMsgErrorExitFailure("RTAsn1SetOfTimes_Append failed: %Rrc", iPos); 953 1000 954 1001 PRTASN1TIME pTime = pAttr->uValues.pSigningTime->papItems[iPos]; … … 957 1004 return RTMsgErrorExitFailure("RTAsn1Time_SetTimeSpec failed: %Rrc", rc); 958 1005 1006 return RTEXITCODE_SUCCESS; 1007 } 1008 1009 static RTEXITCODE SignToolPkcs7_AuthAttribsAddObjIdSeqsEmpty(PRTCRPKCS7ATTRIBUTES pAuthAttribs, const char *pszAttrId) 1010 { 1011 int32_t iPos = RTCrPkcs7Attributes_Append(pAuthAttribs); 1012 if (iPos < 0) 1013 return RTMsgErrorExitFailure("RTCrPkcs7Attributes_Append failed: %Rrc", iPos); 1014 1015 /* Create the attrib and its sub-set of timestamps. */ 1016 PRTCRPKCS7ATTRIBUTE pAttr = pAuthAttribs->papItems[iPos]; 1017 int rc = RTAsn1ObjId_InitFromString(&pAttr->Type, pszAttrId, pAttr->Allocation.pAllocator); 1018 if (RT_FAILURE(rc)) 1019 return RTMsgErrorExitFailure("RTAsn1ObjId_InitFromString/%s failed: %Rrc", pszAttrId, rc); 1020 1021 /** @todo Generalize the Type + enmType DYN stuff and generate setters. */ 1022 Assert(pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT); 1023 Assert(pAttr->uValues.pContentInfos == NULL); 1024 pAttr->enmType = RTCRPKCS7ATTRIBUTETYPE_MS_STATEMENT_TYPE; 1025 rc = RTAsn1MemAllocZ(&pAttr->Allocation, (void **)&pAttr->uValues.pObjIdSeqs, sizeof(*pAttr->uValues.pObjIdSeqs)); 1026 if (RT_FAILURE(rc)) 1027 return RTMsgErrorExitFailure("RTAsn1MemAllocZ failed: %Rrc", rc); 1028 1029 rc = RTAsn1SetOfObjIdSeqs_Init(pAttr->uValues.pObjIdSeqs, pAttr->Allocation.pAllocator); 1030 if (RT_FAILURE(rc)) 1031 return RTMsgErrorExitFailure("RTAsn1SetOfObjIdSeqs_Init failed: %Rrc", rc); 1032 1033 return RTEXITCODE_SUCCESS; 1034 } 1035 1036 static RTEXITCODE SignToolPkcs7_AuthAttribsAddObjIdSeqsValue(PRTCRPKCS7ATTRIBUTES pAuthAttribs, const char *pszAttrId, 1037 const char *pszValueId) 1038 { 1039 RTEXITCODE rcExit = SignToolPkcs7_AuthAttribsAddObjIdSeqsEmpty(pAuthAttribs, pszAttrId); 1040 if (rcExit != RTEXITCODE_SUCCESS) 1041 return rcExit; 1042 1043 /* Add attribute value entry. */ 1044 PRTCRPKCS7ATTRIBUTE pAttr = pAuthAttribs->papItems[pAuthAttribs->cItems - 1]; 1045 int32_t iPos = RTAsn1SetOfObjIdSeqs_Append(pAttr->uValues.pObjIdSeqs); 1046 if (iPos < 0) 1047 return RTMsgErrorExitFailure("RTAsn1SetOfObjIdSeqs_Append failed: %Rrc", iPos); 1048 PRTASN1SEQOFOBJIDS pSeqObjIds = pAttr->uValues.pObjIdSeqs->papItems[iPos]; 1049 1050 /* Add a object id to the value. */ 1051 RTASN1OBJID ObjIdValue; 1052 int rc = RTAsn1ObjId_InitFromString(&ObjIdValue, pszValueId, &g_RTAsn1DefaultAllocator); 1053 if (RT_FAILURE(rc)) 1054 return RTMsgErrorExitFailure("RTAsn1ObjId_InitFromString/%s failed: %Rrc", pszAttrId, rc); 1055 1056 rc = RTAsn1SeqOfObjIds_InsertEx(pSeqObjIds, 0 /*iPos*/, &ObjIdValue, &g_RTAsn1DefaultAllocator, NULL); 1057 RTAsn1ObjId_Delete(&ObjIdValue); 1058 if (RT_FAILURE(rc)) 1059 return RTMsgErrorExitFailure("RTAsn1SeqOfObjIds_InsertEx failed: %Rrc", iPos); 1060 1061 return RTEXITCODE_SUCCESS; 1062 } 1063 1064 static RTEXITCODE SignToolPkcs7_AddAuthAttribsForTimestamp(PRTCRPKCS7ATTRIBUTES pAuthAttribs, bool fTimestampTypeOld, 1065 RTTIMESPEC SigningTime, PCRTCRX509CERTIFICATE pTimestampCert) 1066 { 1067 /* 1068 * Add signing time. 1069 */ 1070 RTEXITCODE rcExit = SignToolPkcs7_AuthAttribsAddSigningTime(pAuthAttribs, SigningTime); 1071 if (rcExit != RTEXITCODE_SUCCESS) 1072 return rcExit; 1073 959 1074 /* 960 1075 * More later if we want to support fTimestampTypeOld = false perhaps? … … 962 1077 Assert(fTimestampTypeOld); 963 1078 RT_NOREF(fTimestampTypeOld, pTimestampCert); 1079 1080 return RTEXITCODE_SUCCESS; 1081 } 1082 1083 static RTEXITCODE SignToolPkcs7_AddAuthAttribsForImageSignature(PRTCRPKCS7ATTRIBUTES pAuthAttribs, RTTIMESPEC SigningTime) 1084 { 1085 /* 1086 * Add SpcOpusInfo. No attribute values. 1087 * SEQ start -vv vv- Type ObjId 1088 * 1c60: 0e 03 02 1a 05 00 a0 70-30 10 06 0a 2b 06 01 04 .......p0...+... 1089 * 1c70: 01 82 37 02 01 0c 31 02-30 00 30 19 06 09 2a 86 ..7...1.0.0...*. 1090 * Set Of -^^ ^^- Empty Sequence. 1091 */ 1092 RTEXITCODE rcExit = SignToolPkcs7_AuthAttribsAddObjIdSeqsEmpty(pAuthAttribs, RTCR_PKCS9_ID_MS_SP_OPUS_INFO); 1093 if (rcExit != RTEXITCODE_SUCCESS) 1094 return rcExit; 1095 1096 /* 1097 * Add ContentType = Ms-SpcIndirectDataContext? 1098 * SEQ start -vv vv- Type ObjId 1099 * 1c70: 01 82 37 02 01 0c 31 02-30 00 30 19 06 09 2a 86 ..7...1.0.0...*. 1100 * 1c80: 48 86 f7 0d 01 09 03 31-0c 06 0a 2b 06 01 04 01 H......1...+.... 1101 * 1c90: 82 37 02 01 04 ^^- ^^- ObjId 1102 * ^- Set Of 1103 */ 1104 1105 /* 1106 * Add Ms-SpcStatementType = Ms-SpcIndividualCodeSigning. 1107 * SEQ start -vv vv- Type ObjId 1108 * 1c90: 82 37 02 01 04 30 1c 06-0a 2b 06 01 04 01 82 37 .7...0...+.....7 1109 * 1ca0: 02 01 0b 31 0e 30 0c 06-0a 2b 06 01 04 01 82 37 ...1.0...+.....7 1110 * 1cb0: 02 01 15 ^^ ^^ ^^- ObjId 1111 * Set Of -^^ ^^- Sequence Of 1112 */ 1113 rcExit = SignToolPkcs7_AuthAttribsAddObjIdSeqsValue(pAuthAttribs, RTCR_PKCS9_ID_MS_STATEMENT_TYPE, 1114 RTCRSPC_STMT_TYPE_INDIVIDUAL_CODE_SIGNING); 1115 if (rcExit != RTEXITCODE_SUCCESS) 1116 return rcExit; 1117 1118 /* 1119 * Add signing time. We add this, even if signtool.exe, since OpenSSL will always do it otherwise. 1120 */ 1121 rcExit = SignToolPkcs7_AuthAttribsAddSigningTime(pAuthAttribs, SigningTime); 1122 if (rcExit != RTEXITCODE_SUCCESS) 1123 return rcExit; 1124 1125 /** @todo more? Some certificate stuff? */ 964 1126 965 1127 return RTEXITCODE_SUCCESS; … … 1057 1219 static RTEXITCODE Pkcs7SignStuff(const char *pszWhat, const void *pvToDataToSign, size_t cbToDataToSign, 1058 1220 PCRTCRPKCS7ATTRIBUTES pAuthAttribs, RTCRSTORE hAdditionalCerts, uint32_t fExtraFlags, 1059 RTDIGESTTYPE enmDigestType, PCRTCRX509CERTIFICATE pTimestampCert, RTCRKEY hTimestampKey,1221 RTDIGESTTYPE enmDigestType, SIGNTOOLKEYPAIR *pCertKeyPair, 1060 1222 unsigned cVerbosity, void **ppvSigned, size_t *pcbSigned, 1061 1223 PRTCRPKCS7CONTENTINFO pContentInfo, PRTCRPKCS7SIGNEDDATA *ppSignedData) … … 1071 1233 size_t cbSigned = 1024; 1072 1234 int rc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP | fExtraFlags, 1073 p TimestampCert, hTimestampKey, pvToDataToSign, cbToDataToSign,1235 pCertKeyPair->pCertificate, pCertKeyPair->hPrivateKey, pvToDataToSign, cbToDataToSign, 1074 1236 enmDigestType, hAdditionalCerts, pAuthAttribs, 1075 1237 NULL, &cbSigned, RTErrInfoInitStatic(&ErrInfo)); … … 1078 1240 1079 1241 /* Allocate memory for it and do the actual signing. */ 1080 void *pvSigned = RTMem TmpAllocZ(cbSigned);1242 void *pvSigned = RTMemAllocZ(cbSigned); 1081 1243 if (!pvSigned) 1082 1244 return RTMsgErrorExitFailure("Failed to allocate %#zx bytes for %s signature", cbSigned, pszWhat); 1083 1245 rc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP | fExtraFlags, 1084 p TimestampCert, hTimestampKey, pvToDataToSign, cbToDataToSign,1246 pCertKeyPair->pCertificate, pCertKeyPair->hPrivateKey, pvToDataToSign, cbToDataToSign, 1085 1247 enmDigestType, hAdditionalCerts, pAuthAttribs, 1086 1248 pvSigned, &cbSigned, RTErrInfoInitStatic(&ErrInfo)); … … 1123 1285 RTCrPkcs7ContentInfo_Delete(pContentInfo); 1124 1286 } 1125 RTMem TmpFree(pvSigned);1287 RTMemFree(pvSigned); 1126 1288 return RTEXITCODE_FAILURE; 1127 1289 } 1128 1290 1129 1130 static RTEXITCODE SignToolPkcs7_AddTimestampSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, unsigned iSignature, 1131 bool fReplaceExisting, bool fTimestampTypeOld, RTTIMESPEC SigningTime, 1132 PCRTCRX509CERTIFICATE pTimestampCert, RTCRKEY hTimestampKey) 1291 static RTEXITCODE SignToolPkcs7_AddTimestampSignatureEx(PRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRPKCS7SIGNEDDATA pSignedData, 1292 unsigned cVerbosity, bool fReplaceExisting, bool fTimestampTypeOld, 1293 RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampPair) 1133 1294 { 1134 1295 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 1296 1144 1297 /* … … 1151 1304 return RTMsgErrorExitFailure("RTCrPkcs7SetOfAttributes_Init failed: %Rrc", rc); 1152 1305 1153 RTEXITCODE rcExit = AddAuthAttribsForTimestamp(&AuthAttribs, fTimestampTypeOld, SigningTime, pTimestampCert); 1306 RTEXITCODE rcExit = SignToolPkcs7_AddAuthAttribsForTimestamp(&AuthAttribs, fTimestampTypeOld, SigningTime, 1307 pTimestampPair->pCertificate); 1154 1308 if (rcExit == RTEXITCODE_SUCCESS) 1155 1309 { … … 1162 1316 rcExit = Pkcs7SignStuff("timestamp", pSignerInfo->EncryptedDigest.Asn1Core.uData.pv, 1163 1317 pSignerInfo->EncryptedDigest.Asn1Core.cb, &AuthAttribs, NIL_RTCRSTORE /*hAdditionalCerts*/, 1164 RTCRPKCS7SIGN_SD_F_DEATCHED, RTDIGESTTYPE_SHA1, pTimestamp Cert, hTimestampKey, cVerbosity,1318 RTCRPKCS7SIGN_SD_F_DEATCHED, RTDIGESTTYPE_SHA1, pTimestampPair, cVerbosity, 1165 1319 &pvSigned, NULL /*pcbSigned*/, &TsContentInfo, &pTsSignedData); 1166 1320 if (rcExit == RTEXITCODE_SUCCESS) … … 1198 1352 */ 1199 1353 if (rcExit == RTEXITCODE_SUCCESS) 1200 rcExit = SignToolPkcs7_AppendCertificate(pSignedData, pTimestamp Cert);1354 rcExit = SignToolPkcs7_AppendCertificate(pSignedData, pTimestampPair->pCertificate); 1201 1355 1202 1356 /* … … 1204 1358 */ 1205 1359 RTCrPkcs7ContentInfo_Delete(&TsContentInfo); 1206 RTMem TmpFree(pvSigned);1360 RTMemFree(pvSigned); 1207 1361 } 1208 1362 } 1209 1363 RTCrPkcs7Attributes_Delete(&AuthAttribs); 1210 1211 RT_NOREF(cVerbosity, fReplaceExisting, fTimestampTypeOld); 1364 return rcExit; 1365 } 1366 1367 static RTEXITCODE SignToolPkcs7_AddTimestampSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, unsigned iSignature, 1368 bool fReplaceExisting, bool fTimestampTypeOld, RTTIMESPEC SigningTime, 1369 SIGNTOOLKEYPAIR *pTimestampPair) 1370 { 1371 AssertReturn(fTimestampTypeOld, RTMsgErrorExitFailure("New style signatures not supported yet")); 1372 1373 /* 1374 * Locate the signature specified by iSignature and add a timestamp to it. 1375 */ 1376 PRTCRPKCS7SIGNEDDATA pSignedData = NULL; 1377 PRTCRPKCS7SIGNERINFO pSignerInfo = SignToolPkcs7_FindNestedSignatureByIndex(pThis, iSignature, &pSignedData); 1378 if (!pSignerInfo) 1379 return RTMsgErrorExitFailure("No signature #%u in %s", iSignature, pThis->pszFilename); 1380 1381 return SignToolPkcs7_AddTimestampSignatureEx(pSignerInfo, pSignedData, cVerbosity, fReplaceExisting, fTimestampTypeOld, 1382 SigningTime, pTimestampPair); 1383 } 1384 1385 static RTEXITCODE SignToolPkcs7_SignSpcIndData(SIGNTOOLPKCS7EXE *pThis, RTCRSPCINDIRECTDATACONTENT *pSpcIndData, 1386 unsigned cVerbosity, bool fReplaceExisting, SIGNTOOLKEYPAIR *pSigningCertKey, 1387 RTCRSTORE hAddCerts, bool fTimestampTypeOld, RTTIMESPEC SigningTime, 1388 SIGNTOOLKEYPAIR *pTimestampCertKey) 1389 { 1390 /* 1391 * Encode it. 1392 */ 1393 RTERRINFOSTATIC ErrInfo; 1394 PRTASN1CORE pSpcRoot = RTCrSpcIndirectDataContent_GetAsn1Core(pSpcIndData); 1395 uint32_t cbSpcEncoded = 0; 1396 int rc = RTAsn1EncodePrepare(pSpcRoot, RTASN1ENCODE_F_DER, &cbSpcEncoded, RTErrInfoInitStatic(&ErrInfo)); 1397 if (RT_FAILURE(rc)) 1398 return RTMsgErrorExitFailure("RTAsn1EncodePrepare failed: %Rrc%RTeim", rc, &ErrInfo.Core); 1399 1400 if (cVerbosity >= 4) 1401 RTAsn1Dump(pSpcRoot, 0, 0, RTStrmDumpPrintfV, g_pStdOut); 1402 1403 void *pvSpcEncoded = (uint8_t *)RTMemTmpAllocZ(cbSpcEncoded); 1404 if (!pvSpcEncoded) 1405 return RTMsgErrorExitFailure("Failed to allocate %#z bytes for SpcIndirectData", cbSpcEncoded); 1406 1407 RTEXITCODE rcExit = RTEXITCODE_FAILURE; 1408 rc = RTAsn1EncodeToBuffer(pSpcRoot, RTASN1ENCODE_F_DER, pvSpcEncoded, cbSpcEncoded, RTErrInfoInitStatic(&ErrInfo)); 1409 if (RT_SUCCESS(rc)) 1410 { 1411 /* 1412 * Create additional authenticated attributes. 1413 */ 1414 RTCRPKCS7ATTRIBUTES AuthAttribs; 1415 rc = RTCrPkcs7Attributes_Init(&AuthAttribs, &g_RTAsn1DefaultAllocator); 1416 if (RT_SUCCESS(rc)) 1417 { 1418 rcExit = SignToolPkcs7_AddAuthAttribsForImageSignature(&AuthAttribs, SigningTime); 1419 if (rcExit == RTEXITCODE_SUCCESS) 1420 { 1421 /* 1422 * Ditch the old signature if so desired. 1423 */ 1424 if (fReplaceExisting && pThis->pSignedData) 1425 { 1426 RTCrPkcs7ContentInfo_Delete(&pThis->ContentInfo); 1427 pThis->pSignedData = NULL; 1428 RTMemFree(pThis->pbBuf); 1429 pThis->pbBuf = NULL; 1430 pThis->cbBuf = 0; 1431 } 1432 1433 /* 1434 * Do the actual signing. 1435 */ 1436 SIGNTOOLPKCS7 Src = { NULL, 0, NULL }; 1437 PSIGNTOOLPKCS7 pSigDst = !pThis->pSignedData ? pThis : &Src; 1438 rcExit = Pkcs7SignStuff("image", pvSpcEncoded, cbSpcEncoded, &AuthAttribs, hAddCerts, 0 /*fExtraFlags*/, 1439 RTDIGESTTYPE_SHA1 /** @todo*/, pSigningCertKey, cVerbosity, 1440 (void **)&pSigDst->pbBuf, &pSigDst->cbBuf, &pSigDst->ContentInfo, &pSigDst->pSignedData); 1441 if (rcExit == RTEXITCODE_SUCCESS) 1442 { 1443 /* 1444 * Add a timestamp signature if requested. 1445 */ 1446 if (pTimestampCertKey->isComplete()) 1447 rcExit = SignToolPkcs7_AddTimestampSignatureEx(pSigDst->pSignedData->SignerInfos.papItems[0], 1448 pSigDst->pSignedData, 1449 cVerbosity, false /*fReplaceExisting*/, 1450 fTimestampTypeOld, SigningTime, pTimestampCertKey); 1451 1452 /* 1453 * Append the signature to the existing one, if that's what we're doing. 1454 */ 1455 if (rcExit == RTEXITCODE_SUCCESS && pSigDst == &Src) 1456 rcExit = SignToolPkcs7_AddNestedSignature(pThis, &Src, cVerbosity, true /*fPrepend*/); /** @todo prepend/append option */ 1457 1458 /* cleanup */ 1459 if (pSigDst == &Src) 1460 SignToolPkcs7_Delete(&Src); 1461 } 1462 } 1463 RTCrPkcs7Attributes_Delete(&AuthAttribs); 1464 } 1465 else 1466 RTMsgError("RTCrPkcs7SetOfAttributes_Init failed: %Rrc", rc); 1467 } 1468 else 1469 RTMsgError("RTAsn1EncodeToBuffer failed: %Rrc", rc); 1470 RTMemTmpFree(pvSpcEncoded); 1471 return rcExit; 1472 } 1473 1474 static RTEXITCODE SignToolPkcs7_SpcCompleteWithoutPageHashes(SIGNTOOLPKCS7EXE *pThis, RTCRSPCINDIRECTDATACONTENT *pSpcIndData) 1475 { 1476 RT_NOREF(pThis); 1477 PRTCRSPCPEIMAGEDATA pPeImage = pSpcIndData->Data.uValue.pPeImage; 1478 Assert(pPeImage); 1479 //pPeImage->Flags 1480 1481 return RTEXITCODE_SUCCESS; 1482 } 1483 1484 static RTEXITCODE SignToolPkcs7_SpcAddImagePageHashes(SIGNTOOLPKCS7EXE *pThis, RTCRSPCINDIRECTDATACONTENT *pSpcIndData, 1485 RTDIGESTTYPE enmSigType) 1486 { 1487 RT_NOREF(pThis, pSpcIndData, enmSigType); 1488 return RTEXITCODE_SUCCESS; 1489 } 1490 1491 static RTEXITCODE SignToolPkcs7_SpcAddImageHash(SIGNTOOLPKCS7EXE *pThis, RTCRSPCINDIRECTDATACONTENT *pSpcIndData, 1492 RTDIGESTTYPE enmSigType) 1493 { 1494 uint32_t const cbHash = RTCrDigestTypeToHashSize(enmSigType); 1495 const char * const pszAlgId = RTCrDigestTypeToAlgorithmOid(enmSigType); 1496 1497 /* 1498 * Ask the loader for the hash. 1499 */ 1500 uint8_t abHash[RTSHA512_HASH_SIZE]; 1501 int rc = RTLdrHashImage(pThis->hLdrMod, enmSigType, abHash, sizeof(abHash)); 1502 if (RT_FAILURE(rc)) 1503 return RTMsgErrorExitFailure("RTLdrHashImage/%s failed: %Rrc", RTCrDigestTypeToName(enmSigType), rc); 1504 1505 /* 1506 * Set it. 1507 */ 1508 /** @todo no setter, this should be okay, though... */ 1509 rc = RTAsn1ObjId_InitFromString(&pSpcIndData->DigestInfo.DigestAlgorithm.Algorithm, pszAlgId, &g_RTAsn1DefaultAllocator); 1510 if (RT_FAILURE(rc)) 1511 return RTMsgErrorExitFailure("RTAsn1ObjId_InitFromString/%s failed: %Rrc", pszAlgId, rc); 1512 1513 rc = RTAsn1ContentDup(&pSpcIndData->DigestInfo.Digest.Asn1Core, abHash, cbHash, &g_RTAsn1DefaultAllocator); 1514 if (RT_FAILURE(rc)) 1515 return RTMsgErrorExitFailure("RTAsn1ContentDup/%#x failed: %Rrc", cbHash, rc); 1516 1517 return RTEXITCODE_SUCCESS; 1518 } 1519 1520 1521 static RTEXITCODE SignToolPkcs7_AddOrReplaceSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, RTDIGESTTYPE enmSigType, 1522 bool fReplaceExisting, bool fHashPages, SIGNTOOLKEYPAIR *pSigningCertKey, 1523 RTCRSTORE hAddCerts, bool fTimestampTypeOld, 1524 RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampCertKey) 1525 { 1526 AssertReturn(fTimestampTypeOld || pTimestampCertKey->isNull(), 1527 RTMsgErrorExitFailure("New style signatures not supported yet")); 1528 1529 /* 1530 * We must construct the data to be backed into the PKCS#7 signature 1531 * and signed. 1532 */ 1533 RTCRSPCINDIRECTDATACONTENT SpcIndData; 1534 int rc = RTCrSpcIndirectDataContent_Init(&SpcIndData, &g_RTAsn1DefaultAllocator); 1535 if (RT_FAILURE(rc)) 1536 return RTMsgErrorExitFailure("RTCrSpcIndirectDataContent_Init failed: %Rrc", rc); 1537 1538 /* Set the data to PE image. */ 1539 /** @todo Generalize the Type + enmType DYN stuff and generate setters. */ 1540 Assert(SpcIndData.Data.enmType == RTCRSPCAAOVTYPE_NOT_PRESENT); 1541 Assert(SpcIndData.Data.uValue.pPeImage == NULL); 1542 SpcIndData.Data.enmType = RTCRSPCAAOVTYPE_PE_IMAGE_DATA; 1543 rc = RTAsn1MemAllocZ(&SpcIndData.Data.Allocation, (void **)&SpcIndData.Data.uValue.pPeImage, 1544 sizeof(*SpcIndData.Data.uValue.pPeImage)); 1545 RTEXITCODE rcExit; 1546 if (RT_SUCCESS(rc)) 1547 { 1548 rc = RTCrSpcPeImageData_Init(SpcIndData.Data.uValue.pPeImage, SpcIndData.Data.Allocation.pAllocator); 1549 if (RT_SUCCESS(rc)) 1550 { 1551 /* Add the hashes. */ 1552 rcExit = SignToolPkcs7_SpcAddImageHash(pThis, &SpcIndData, enmSigType); 1553 if (rcExit == RTEXITCODE_SUCCESS) 1554 { 1555 if (fHashPages) 1556 rcExit = SignToolPkcs7_SpcAddImagePageHashes(pThis, &SpcIndData, enmSigType); 1557 else 1558 rcExit = SignToolPkcs7_SpcCompleteWithoutPageHashes(pThis, &SpcIndData); 1559 1560 /* 1561 * Encode and sign the SPC data, timestamp it, and line it up for adding to the executable. 1562 */ 1563 if (rcExit == RTEXITCODE_SUCCESS) 1564 rcExit = SignToolPkcs7_SignSpcIndData(pThis, &SpcIndData, cVerbosity, fReplaceExisting, pSigningCertKey, 1565 hAddCerts, fTimestampTypeOld, SigningTime, pTimestampCertKey); 1566 } 1567 } 1568 else 1569 rcExit = RTMsgErrorExitFailure("RTCrPkcs7SignerInfos_Init failed: %Rrc", rc); 1570 } 1571 else 1572 rcExit = RTMsgErrorExitFailure("RTAsn1MemAllocZ failed for RTCRSPCPEIMAGEDATA: %Rrc", rc); 1573 1574 RTCrSpcIndirectDataContent_Delete(&SpcIndData); 1212 1575 return rcExit; 1213 1576 } … … 1569 1932 1570 1933 /********************************************************************************************************************************* 1934 * Option handlers shared by 'sign-exe', 'sign-cat', 'add-timestamp-exe-signature' and others. * 1935 *********************************************************************************************************************************/ 1936 static RTEXITCODE HandleOptCertFile(SIGNTOOLKEYPAIR *pKeyPair, const char *pszFile) 1937 { 1938 if (pKeyPair->pCertificate == &pKeyPair->Cert) 1939 RTCrX509Certificate_Delete(&pKeyPair->Cert); 1940 pKeyPair->pCertificate = NULL; 1941 1942 RTERRINFOSTATIC ErrInfo; 1943 int rc = RTCrX509Certificate_ReadFromFile(&pKeyPair->Cert, pszFile, 0, &g_RTAsn1DefaultAllocator, 1944 RTErrInfoInitStatic(&ErrInfo)); 1945 if (RT_FAILURE(rc)) 1946 return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core); 1947 pKeyPair->pCertificate = &pKeyPair->Cert; 1948 return RTEXITCODE_SUCCESS; 1949 } 1950 1951 static RTEXITCODE HandleOptKeyFile(SIGNTOOLKEYPAIR *pKeyPair, const char *pszFile) 1952 { 1953 RTCrKeyRelease(pKeyPair->hPrivateKey); 1954 1955 RTERRINFOSTATIC ErrInfo; 1956 int rc = RTCrKeyCreateFromFile(&pKeyPair->hPrivateKey, 0 /*fFlags*/, pszFile, 1957 NULL /*pszPassword*/, RTErrInfoInitStatic(&ErrInfo)); 1958 if (RT_SUCCESS(rc)) 1959 return RTEXITCODE_SUCCESS; 1960 1961 pKeyPair->hPrivateKey = NIL_RTCRKEY; 1962 return RTMsgErrorExitFailure("Error reading private key from '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core); 1963 } 1964 1965 static RTEXITCODE HandleOptAddCert(PRTCRSTORE phStore, const char *pszFile) 1966 { 1967 if (*phStore == NIL_RTCRSTORE) 1968 { 1969 int rc = RTCrStoreCreateInMem(phStore, 2); 1970 if (RT_FAILURE(rc)) 1971 return RTMsgErrorExitFailure("RTCrStoreCreateInMem(,2) failed: %Rrc", rc); 1972 } 1973 RTERRINFOSTATIC ErrInfo; 1974 int rc = RTCrStoreCertAddFromFile(*phStore, RTCRCERTCTX_F_ADD_IF_NOT_FOUND, pszFile, RTErrInfoInitStatic(&ErrInfo)); 1975 if (RT_FAILURE(rc)) 1976 return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core); 1977 return RTEXITCODE_SUCCESS; 1978 } 1979 1980 static RTEXITCODE HandleOptSignatureType(RTDIGESTTYPE *penmSigType, const char *pszType) 1981 { 1982 if ( RTStrICmpAscii(pszType, "sha1") == 0 1983 || RTStrICmpAscii(pszType, "sha-1") == 0) 1984 *penmSigType = RTDIGESTTYPE_SHA1; 1985 else if ( RTStrICmpAscii(pszType, "sha256") == 0 1986 || RTStrICmpAscii(pszType, "sha-256") == 0) 1987 *penmSigType = RTDIGESTTYPE_SHA256; 1988 else 1989 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown signature type: %s (expected sha1 or sha256)", pszType); 1990 return RTEXITCODE_SUCCESS; 1991 } 1992 1993 1994 static RTEXITCODE HandleOptTimestampType(bool *pfOldType, const char *pszType) 1995 { 1996 if (strcmp(pszType, "old") == 0) 1997 *pfOldType = true; 1998 else if (strcmp(pszType, "new") == 0) 1999 *pfOldType = false; 2000 else 2001 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown timestamp type: %s", pszType); 2002 return RTEXITCODE_SUCCESS; 2003 } 2004 2005 static RTEXITCODE HandleOptTimestampOverride(PRTTIMESPEC pSigningTime, const char *pszPartialTs) 2006 { 2007 /* 2008 * First try use it as-is. 2009 */ 2010 if (RTTimeSpecFromString(pSigningTime, pszPartialTs) != NULL) 2011 return RTEXITCODE_SUCCESS; 2012 2013 /* Check the input against a pattern, making sure we've got something that 2014 makes sense before trying to merge. */ 2015 size_t const cchPartialTs = strlen(pszPartialTs); 2016 static char s_szPattern[] = "0000-00-00T00:00:"; 2017 if (cchPartialTs > sizeof(s_szPattern) - 1) /* It is not a partial timestamp if we've got the seconds component. */ 2018 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp: %s", pszPartialTs); 2019 2020 for (size_t off = 0; off < cchPartialTs; off++) 2021 switch (s_szPattern[off]) 2022 { 2023 case '0': 2024 if (!RT_C_IS_DIGIT(pszPartialTs[off])) 2025 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp, expected digit at position %u: %s", 2026 off + 1, pszPartialTs); 2027 break; 2028 case '-': 2029 case ':': 2030 if (pszPartialTs[off] != s_szPattern[off]) 2031 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp, expected '%c' at position %u: %s", 2032 s_szPattern[off], off + 1, pszPartialTs); 2033 break; 2034 case 'T': 2035 if ( pszPartialTs[off] != 'T' 2036 && pszPartialTs[off] != 't' 2037 && pszPartialTs[off] != ' ') 2038 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp, expected 'T' or space at position %u: %s", 2039 off + 1, pszPartialTs); 2040 break; 2041 default: 2042 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Internal error"); 2043 } 2044 2045 if (RT_C_IS_DIGIT(s_szPattern[cchPartialTs]) && RT_C_IS_DIGIT(s_szPattern[cchPartialTs - 1])) 2046 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Incomplete timstamp component: %s", pszPartialTs); 2047 2048 /* 2049 * Take the current time and merge in the components from pszPartialTs. 2050 */ 2051 char szSigningTime[RTTIME_STR_LEN]; 2052 RTTIMESPEC Now; 2053 RTTimeSpecToString(RTTimeNow(&Now), szSigningTime, sizeof(szSigningTime)); 2054 memcpy(szSigningTime, pszPartialTs, cchPartialTs); 2055 szSigningTime[4+1+2+1+2] = 'T'; 2056 2057 /* Fix 29th for non-leap override: */ 2058 if (memcmp(&szSigningTime[5], RT_STR_TUPLE("02-29")) == 0) 2059 { 2060 if (!RTTimeIsLeapYear(RTStrToUInt32(szSigningTime))) 2061 szSigningTime[9] = '8'; 2062 } 2063 if (RTTimeSpecFromString(pSigningTime, szSigningTime) == NULL) 2064 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp: %s (%s)", pszPartialTs, szSigningTime); 2065 2066 return RTEXITCODE_SUCCESS; 2067 } 2068 2069 2070 /********************************************************************************************************************************* 1571 2071 * The 'add-timestamp-exe-signature' command. * 1572 2072 *********************************************************************************************************************************/ … … 1580 2080 "add-timestamp-exe-signature [-v|--verbose] [--signature-index|-i <num>] " 1581 2081 "[--timestamp-cert-file <file>] " 2082 "[--timestamp-key-file <file>] " 1582 2083 "[--timestamp-type old|new] " 1583 2084 "[--timestamp-date <fake-isots>] " … … 1589 2090 "This is mainly to test timestamp code.\n" 1590 2091 "\n" 1591 "The --timestamp- date option takes an ISO timestamp, but will replace the time part with the"1592 " current time.\n"2092 "The --timestamp-override option can take a partial or full ISO timestamp. It is merged " 2093 "with the current time if partial.\n" 1593 2094 "\n"); 1594 2095 return RTEXITCODE_SUCCESS; 1595 2096 } 1596 2097 1597 1598 2098 static RTEXITCODE HandleAddTimestampExeSignature(int cArgs, char **papszArgs) 1599 2099 { 1600 RTERRINFOSTATIC ErrInfo;1601 1602 2100 /* 1603 2101 * Parse arguments. … … 1609 2107 { "--timestamp-key-file", OPT_TIMESTAMP_KEY_FILE, RTGETOPT_REQ_STRING }, 1610 2108 { "--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 }, 2109 { "--timestamp-override", OPT_TIMESTAMP_OVERRIDE, RTGETOPT_REQ_STRING }, 1613 2110 { "--replace-existing", 'r', RTGETOPT_REQ_NOTHING }, 1614 2111 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, … … 1619 2116 bool fReplaceExisting = false; 1620 2117 bool fTimestampTypeOld = true; 1621 RTCRX509CERTIFICATE TimestampCertificate; /* leaked */ 1622 PCRTCRX509CERTIFICATE pTimestampCertificate = NULL; 1623 RTCRKEY hTimestampPrivateKey = NIL_RTCRKEY; 2118 SIGNTOOLKEYPAIR TimestampCertKey; 1624 2119 RTTIMESPEC SigningTime; 1625 2120 RTTimeNow(&SigningTime); … … 1634 2129 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 1635 2130 { 2131 RTEXITCODE rcExit2 = RTEXITCODE_SUCCESS; 1636 2132 switch (ch) 1637 2133 { 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)) 2134 case 'i': iSignature = ValueUnion.u32; break; 2135 case OPT_TIMESTAMP_CERT_FILE: rcExit2 = HandleOptCertFile(&TimestampCertKey, ValueUnion.psz); break; 2136 case OPT_TIMESTAMP_KEY_FILE: rcExit2 = HandleOptKeyFile(&TimestampCertKey, ValueUnion.psz); break; 2137 case OPT_TIMESTAMP_TYPE: rcExit2 = HandleOptTimestampType(&fTimestampTypeOld, ValueUnion.psz); break; 2138 case OPT_TIMESTAMP_OVERRIDE: rcExit2 = HandleOptTimestampOverride(&SigningTime, ValueUnion.psz); break; 2139 case 'r': fReplaceExisting = true; break; 2140 case 'v': cVerbosity++; break; 2141 case 'V': return HandleVersion(cArgs, papszArgs); 2142 case 'h': return HelpAddTimestampExeSignature(g_pStdOut, RTSIGNTOOLHELP_FULL); 2143 2144 case VINF_GETOPT_NOT_OPTION: 2145 /* check that we've got all the info we need: */ 2146 if (TimestampCertKey.isComplete()) 1677 2147 { 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); 2148 /* Do the work: */ 2149 SIGNTOOLPKCS7EXE Exe; 2150 rcExit2 = SignToolPkcs7Exe_InitFromFile(&Exe, ValueUnion.psz, cVerbosity); 2151 if (rcExit2 == RTEXITCODE_SUCCESS) 2152 { 2153 rcExit2 = SignToolPkcs7_AddTimestampSignature(&Exe, cVerbosity, iSignature, fReplaceExisting, 2154 fTimestampTypeOld, SigningTime, &TimestampCertKey); 2155 if (rcExit2 == RTEXITCODE_SUCCESS) 2156 rcExit2 = SignToolPkcs7_Encode(&Exe, cVerbosity); 2157 if (rcExit2 == RTEXITCODE_SUCCESS) 2158 rcExit2 = SignToolPkcs7Exe_WriteSignatureToFile(&Exe, cVerbosity); 2159 SignToolPkcs7Exe_Delete(&Exe); 2160 } 2161 if (rcExit2 != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS) 2162 rcExit = rcExit2; 2163 rcExit2 = RTEXITCODE_SUCCESS; 1686 2164 } 1687 2165 else 1688 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid timestamp: %s", ValueUnion.psz); 2166 { 2167 if (!TimestampCertKey.pCertificate) 2168 RTMsgError("No timestamp certificate was specified"); 2169 if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY) 2170 RTMsgError("No timestamp private key was specified"); 2171 rcExit2 = RTEXITCODE_SYNTAX; 2172 } 1689 2173 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 > 28 && Time.u8Month == 2 && !RTTimeIsLeapYear(Time.i32Year))1701 Time.u8MonthDay = 28;1702 Time.u16YearDay = 0;1703 Time.fFlags &= ~(RTTIME_FLAGS_COMMON_YEAR | RTTIME_FLAGS_LEAP_YEAR);1704 RTTimeImplode(&SigningTime, RTTimeNormalize(&Time));1705 break;1706 }1707 1708 case 'r':1709 fReplaceExisting = true;1710 break;1711 1712 case 'v':1713 cVerbosity++;1714 break;1715 1716 case 'V':1717 return HandleVersion(cArgs, papszArgs);1718 1719 case 'h':1720 return HelpAddTimestampExeSignature(g_pStdOut, RTSIGNTOOLHELP_FULL);1721 1722 case VINF_GETOPT_NOT_OPTION:1723 {1724 /* check that we've got all the info we need: */1725 if (!pTimestampCertificate)1726 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No timestamp certificate was specified");1727 if (hTimestampPrivateKey == NIL_RTCRKEY)1728 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No timestamp private key was specified");1729 1730 /* Do the work: */1731 SIGNTOOLPKCS7EXE Exe;1732 RTEXITCODE rcExit2 = SignToolPkcs7Exe_InitFromFile(&Exe, ValueUnion.psz, cVerbosity);1733 if (rcExit2 == RTEXITCODE_SUCCESS)1734 {1735 rcExit2 = SignToolPkcs7_AddTimestampSignature(&Exe, cVerbosity, iSignature, fReplaceExisting,1736 fTimestampTypeOld, SigningTime,1737 pTimestampCertificate, hTimestampPrivateKey);1738 if (rcExit2 == RTEXITCODE_SUCCESS)1739 rcExit2 = SignToolPkcs7_Encode(&Exe, cVerbosity);1740 if (rcExit2 == RTEXITCODE_SUCCESS)1741 rcExit2 = SignToolPkcs7Exe_WriteSignatureToFile(&Exe, cVerbosity);1742 SignToolPkcs7Exe_Delete(&Exe);1743 }1744 if (rcExit2 != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS)1745 rcExit = rcExit2;1746 break;1747 }1748 2174 1749 2175 default: 1750 2176 return RTGetOptPrintError(ch, &ValueUnion); 1751 2177 } 1752 } 2178 2179 if (rcExit2 != RTEXITCODE_SUCCESS) 2180 { 2181 rcExit = rcExit2; 2182 break; 2183 } 2184 } 2185 return rcExit; 2186 } 2187 2188 #endif /*!IPRT_IN_BUILD_TOOL */ 2189 2190 2191 /********************************************************************************************************************************* 2192 * The 'sign-exe' command. * 2193 *********************************************************************************************************************************/ 2194 #ifndef IPRT_IN_BUILD_TOOL 2195 2196 static RTEXITCODE HelpSignExe(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel) 2197 { 2198 RT_NOREF_PV(enmLevel); 2199 2200 RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT, 2201 "sign-exe [-v|--verbose] " 2202 "[--type sha1|sha256] " 2203 "[--hash-pages] " 2204 "[--no-hash-pages] " 2205 "[--append] " 2206 "[--cert-file <file>] " 2207 "[--cert-key <file>] " 2208 "[--add-cert <file>] " 2209 "[--timestamp-cert-file <file>] " 2210 "[--timestamp-key-file <file>] " 2211 "[--timestamp-type old|new] " 2212 "[--timestamp-date <fake-isots>] " 2213 "[--timestamp-year <fake-year>] " 2214 "[--replace-existing|-r] " 2215 "<exe>\n"); 2216 if (enmLevel == RTSIGNTOOLHELP_FULL) 2217 RTStrmWrappedPrintf(pStrm, 0, 2218 "Create a new code signature for an executable.\n" 2219 "\n" 2220 "The --timestamp-override option can take a partial or full ISO timestamp. It is merged " 2221 "with the current time if partial.\n" 2222 "\n"); 2223 return RTEXITCODE_SUCCESS; 2224 } 2225 2226 2227 static RTEXITCODE HandleSignExe(int cArgs, char **papszArgs) 2228 { 2229 /* 2230 * Parse arguments. 2231 */ 2232 static const RTGETOPTDEF s_aOptions[] = 2233 { 2234 { "--append", 'a', RTGETOPT_REQ_NOTHING }, 2235 { "/as", 'a', RTGETOPT_REQ_NOTHING }, 2236 { "--type", 't', RTGETOPT_REQ_STRING }, 2237 { "/fd", 't', RTGETOPT_REQ_STRING }, 2238 { "--hash-pages", OPT_HASH_PAGES, RTGETOPT_REQ_NOTHING }, 2239 { "/ph", OPT_HASH_PAGES, RTGETOPT_REQ_NOTHING }, 2240 { "--no-hash-pages", OPT_NO_HASH_PAGES, RTGETOPT_REQ_NOTHING }, 2241 { "/nph", OPT_NO_HASH_PAGES, RTGETOPT_REQ_NOTHING }, 2242 { "--add-cert", OPT_ADD_CERT, RTGETOPT_REQ_STRING }, 2243 { "/ac", OPT_ADD_CERT, RTGETOPT_REQ_STRING }, 2244 { "--cert-file", OPT_CERT_FILE, RTGETOPT_REQ_STRING }, 2245 { "--key-file", OPT_KEY_FILE, RTGETOPT_REQ_STRING }, 2246 { "--timestamp-cert-file", OPT_TIMESTAMP_CERT_FILE, RTGETOPT_REQ_STRING }, 2247 { "--timestamp-key-file", OPT_TIMESTAMP_KEY_FILE, RTGETOPT_REQ_STRING }, 2248 { "--timestamp-type", OPT_TIMESTAMP_TYPE, RTGETOPT_REQ_STRING }, 2249 { "--timestamp-override", OPT_TIMESTAMP_OVERRIDE, RTGETOPT_REQ_STRING }, 2250 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 2251 { "/v", 'v', RTGETOPT_REQ_NOTHING }, 2252 { "/debug", 'v', RTGETOPT_REQ_NOTHING }, 2253 }; 2254 2255 unsigned cVerbosity = 0; 2256 RTDIGESTTYPE enmSigType = RTDIGESTTYPE_SHA1; 2257 bool fReplaceExisting = true; 2258 bool fHashPages = false; 2259 SIGNTOOLKEYPAIR SigningCertKey; 2260 RTCRSTORE hAddCerts = NIL_RTCRSTORE; /* leaked if returning directly (--help, --version) */ 2261 bool fTimestampTypeOld = true; 2262 SIGNTOOLKEYPAIR TimestampCertKey; 2263 RTTIMESPEC SigningTime; 2264 RTTimeNow(&SigningTime); 2265 2266 RTGETOPTSTATE GetState; 2267 int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); 2268 AssertRCReturn(rc, RTEXITCODE_FAILURE); 2269 2270 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 2271 RTGETOPTUNION ValueUnion; 2272 int ch; 2273 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 2274 { 2275 RTEXITCODE rcExit2 = RTEXITCODE_SUCCESS; 2276 switch (ch) 2277 { 2278 case 't': rcExit2 = HandleOptSignatureType(&enmSigType, ValueUnion.psz); break; 2279 case 'a': fReplaceExisting = false; break; 2280 case OPT_HASH_PAGES: fHashPages = true; break; 2281 case OPT_NO_HASH_PAGES: fHashPages = false; break; 2282 case OPT_CERT_FILE: rcExit2 = HandleOptCertFile(&SigningCertKey, ValueUnion.psz); break; 2283 case OPT_KEY_FILE: rcExit2 = HandleOptKeyFile(&SigningCertKey, ValueUnion.psz); break; 2284 case OPT_ADD_CERT: rcExit2 = HandleOptAddCert(&hAddCerts, ValueUnion.psz); break; 2285 case OPT_TIMESTAMP_CERT_FILE: rcExit2 = HandleOptCertFile(&TimestampCertKey, ValueUnion.psz); break; 2286 case OPT_TIMESTAMP_KEY_FILE: rcExit2 = HandleOptKeyFile(&TimestampCertKey, ValueUnion.psz); break; 2287 case OPT_TIMESTAMP_TYPE: rcExit2 = HandleOptTimestampType(&fTimestampTypeOld, ValueUnion.psz); break; 2288 case OPT_TIMESTAMP_OVERRIDE: rcExit2 = HandleOptTimestampOverride(&SigningTime, ValueUnion.psz); break; 2289 case 'v': cVerbosity++; break; 2290 case 'V': return HandleVersion(cArgs, papszArgs); 2291 case 'h': return HelpSignExe(g_pStdOut, RTSIGNTOOLHELP_FULL); 2292 2293 case VINF_GETOPT_NOT_OPTION: 2294 /* check that we've got all the info we need: */ 2295 if ( SigningCertKey.isComplete() 2296 && (TimestampCertKey.isNull() || TimestampCertKey.isComplete())) 2297 { 2298 /* Do the work: */ 2299 SIGNTOOLPKCS7EXE Exe; 2300 /** @todo will fail if not already signed. */ 2301 rcExit2 = SignToolPkcs7Exe_InitFromFile(&Exe, ValueUnion.psz, cVerbosity); 2302 if (rcExit2 == RTEXITCODE_SUCCESS) 2303 { 2304 rcExit2 = SignToolPkcs7_AddOrReplaceSignature(&Exe, cVerbosity, enmSigType, fReplaceExisting, fHashPages, 2305 &SigningCertKey, hAddCerts, 2306 fTimestampTypeOld, SigningTime, &TimestampCertKey); 2307 if (rcExit2 == RTEXITCODE_SUCCESS) 2308 rcExit2 = SignToolPkcs7_Encode(&Exe, cVerbosity); 2309 if (rcExit2 == RTEXITCODE_SUCCESS) 2310 rcExit2 = SignToolPkcs7Exe_WriteSignatureToFile(&Exe, cVerbosity); 2311 SignToolPkcs7Exe_Delete(&Exe); 2312 } 2313 if (rcExit2 != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS) 2314 rcExit = rcExit2; 2315 rcExit2 = RTEXITCODE_SUCCESS; 2316 } 2317 else 2318 { 2319 if (!TimestampCertKey.pCertificate) 2320 RTMsgError("No signing certificate was specified"); 2321 if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY) 2322 RTMsgError("No signing private key was specified"); 2323 2324 if (!TimestampCertKey.pCertificate && !TimestampCertKey.isNull()) 2325 RTMsgError("No timestamp certificate was specified"); 2326 if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY && !TimestampCertKey.isNull()) 2327 RTMsgError("No timestamp private key was specified"); 2328 rcExit2 = RTEXITCODE_SYNTAX; 2329 } 2330 break; 2331 2332 default: 2333 return RTGetOptPrintError(ch, &ValueUnion); 2334 } 2335 if (rcExit2 != RTEXITCODE_SUCCESS) 2336 { 2337 rcExit = rcExit2; 2338 break; 2339 } 2340 } 2341 2342 if (hAddCerts != NIL_RTCRSTORE) 2343 RTCrStoreRelease(hAddCerts); 1753 2344 return rcExit; 1754 2345 } … … 2304 2895 { 2305 2896 HandleShowExeWorkerDisplayObjId(pThis, &pAttr->Type, "", ":\n"); 2897 if (pThis->cVerbosity > 4 && pAttr->SeqCore.Asn1Core.uData.pu8) 2898 RTPrintf("%s uData.pu8=%p cb=%#x\n", pThis->szPrefix, pAttr->SeqCore.Asn1Core.uData.pu8, pAttr->SeqCore.Asn1Core.cb); 2306 2899 2307 2900 int rc = VINF_SUCCESS; … … 3288 3881 #ifndef IPRT_IN_BUILD_TOOL 3289 3882 { "add-timestamp-exe-signature", HandleAddTimestampExeSignature, HelpAddTimestampExeSignature }, 3883 { "sign-exe", HandleSignExe, HelpSignExe }, 3290 3884 #endif 3291 3885 #ifndef IPRT_IN_BUILD_TOOL
Note:
See TracChangeset
for help on using the changeset viewer.