- Timestamp:
- Oct 12, 2020 11:59:53 PM (4 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
r85172 r86549 1353 1353 * @callback_method_impl{FNRTLDRVALIDATESIGNEDDATA} 1354 1354 */ 1355 static DECLCALLBACK(int) supdrvDarwinLdrOpenVerifyCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature, 1356 void const *pvSignature, size_t cbSignature, 1357 void const *pvExternalData, size_t cbExternalData, 1355 static DECLCALLBACK(int) supdrvDarwinLdrOpenVerifyCallback(RTLDRMOD hLdrMod, PCRTLDRSIGNATUREINFO pInfo, 1358 1356 PRTERRINFO pErrInfo, void *pvUser) 1359 1357 { 1360 1358 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 1361 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(cbSignature);1362 1363 switch ( enmSignature)1359 RT_NOREF_PV(hLdrMod); 1360 1361 switch (pInfo->enmType) 1364 1362 { 1365 1363 case RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA: 1366 if (p vExternalData)1364 if (pInfo->pvExternalData) 1367 1365 { 1368 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)p vSignature;1366 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pInfo->pvSignature; 1369 1367 RTTIMESPEC ValidationTime; 1370 1368 RTTimeNow(&ValidationTime); … … 1376 1374 pDevExt->hAdditionalStore, pDevExt->hRootStore, &ValidationTime, 1377 1375 supdrvDarwinLdrOpenVerifyCertificatCallback, pDevExt, 1378 p vExternalData,cbExternalData, pErrInfo);1376 pInfo->pvExternalData, pInfo->cbExternalData, pErrInfo); 1379 1377 } 1380 1378 return RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Expected external data with signature!"); 1381 1379 1382 1380 default: 1383 return RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Unsupported signature type: %d", enmSignature);1381 return RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Unsupported signature type: %d", pInfo->enmType); 1384 1382 } 1385 1383 } -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r85127 r86549 98 98 /** The file handle. */ 99 99 HANDLE hFile; 100 /** Handle to event sempahore in case we're force to deal with asynchronous 101 * I/O. */ 100 /** Handle to event sempahore in case we're force to deal with asynchronous I/O. */ 102 101 HANDLE hEvent; 103 102 /** Current file offset. */ … … 107 106 /** Flags for the verification callback, SUPHNTVI_F_XXX. */ 108 107 uint32_t fFlags; 109 /** The executable timstamp in second since unix epoch. */ 110 uint64_t uTimestamp; 108 /** Number of signatures that verified okay. */ 109 uint16_t cOkaySignatures; 110 /** Number of signatures that couldn't be successfully verified (time stamp 111 * issues, no certificate path, etc) but weren't fatal. */ 112 uint16_t cNokSignatures; 113 /** Total number of signatures. */ 114 uint16_t cTotalSignatures; 115 /** The last non-fatal signature failure. */ 116 int rcLastSignatureFailure; 111 117 /** Log name. */ 112 118 char szFilename[1]; -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
r85127 r86549 1059 1059 1060 1060 1061 static DECLCALLBACK(int) supHardNtViCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature, 1062 void const *pvSignature, size_t cbSignature, 1063 void const *pvExternalData, size_t cbExternalData, 1064 PRTERRINFO pErrInfo, void *pvUser) 1065 { 1066 RT_NOREF(hLdrMod, enmSignature, pvExternalData, cbExternalData); 1061 /** 1062 * RTTimeNow equivaltent that handles ring-3 where we cannot use it. 1063 * 1064 * @returns pNow 1065 * @param pNow Where to return the current time. 1066 */ 1067 static PRTTIMESPEC supHardNtTimeNow(PRTTIMESPEC pNow) 1068 { 1069 #ifdef IN_RING3 1070 /* 1071 * Just read system time. 1072 */ 1073 KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA; 1074 # ifdef RT_ARCH_AMD64 1075 uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->SystemTime; /* This is what KeQuerySystemTime does (missaligned). */ 1076 return RTTimeSpecSetNtTime(pNow, uRet); 1077 # else 1078 1079 LARGE_INTEGER NtTime; 1080 do 1081 { 1082 NtTime.HighPart = pUserSharedData->SystemTime.High1Time; 1083 NtTime.LowPart = pUserSharedData->SystemTime.LowPart; 1084 } while (pUserSharedData->SystemTime.High2Time != NtTime.HighPart); 1085 return RTTimeSpecSetNtTime(pNow, NtTime.QuadPart); 1086 # endif 1087 #else /* IN_RING0 */ 1088 return RTTimeNow(pNow); 1089 #endif /* IN_RING0 */ 1090 } 1091 1092 1093 /** 1094 * @callback_method_impl{FNRTLDRVALIDATESIGNEDDATA} 1095 */ 1096 static DECLCALLBACK(int) supHardNtViCallback(RTLDRMOD hLdrMod, PCRTLDRSIGNATUREINFO pInfo, PRTERRINFO pErrInfo, void *pvUser) 1097 { 1098 RT_NOREF(hLdrMod); 1067 1099 1068 1100 /* … … 1071 1103 PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser; 1072 1104 Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC); 1073 1074 AssertReturn(cbSignature == sizeof(RTCRPKCS7CONTENTINFO), VERR_INTERNAL_ERROR_5); 1075 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pvSignature; 1105 pNtViRdr->cTotalSignatures = pInfo->cSignatures; 1106 1107 AssertReturn(pInfo->enmType == RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA, VERR_INTERNAL_ERROR_5); 1108 AssertReturn(!pInfo->pvExternalData, VERR_INTERNAL_ERROR_5); 1109 AssertReturn(pInfo->cbSignature == sizeof(RTCRPKCS7CONTENTINFO), VERR_INTERNAL_ERROR_5); 1110 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pInfo->pvSignature; 1076 1111 AssertReturn(RTCrPkcs7ContentInfo_IsSignedData(pContentInfo), VERR_INTERNAL_ERROR_5); 1077 1112 AssertReturn(pContentInfo->u.pSignedData->SignerInfos.cItems == 1, VERR_INTERNAL_ERROR_5); 1078 1113 PCRTCRPKCS7SIGNERINFO pSignerInfo = pContentInfo->u.pSignedData->SignerInfos.papItems[0]; 1079 1114 1080 AssertReturn(!pvExternalData, VERR_INTERNAL_ERROR_5);1081 1115 1082 1116 /* 1083 1117 * If special certificate requirements, check them out before validating 1084 * the signature. 1085 */ 1086 if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) 1118 * the signature. These only apply to the first signature (for now). 1119 */ 1120 if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) 1121 && pInfo->iSignature == 0) 1087 1122 { 1088 1123 if (!RTCrX509Certificate_MatchIssuerAndSerialNumber(&g_BuildX509Cert, … … 1098 1133 1099 1134 /* 1100 * Verify the signature. We instruct the verifier to use the signing time 1101 * counter signature present when present, falling back on the timestamp 1102 * planted by the linker when absent. In ring-0 we don't have all the 1103 * necessary timestamp server root certificate info, so we have to allow 1104 * using counter signatures unverified there. Ditto for the early period 1105 * of ring-3 hardened stub execution. 1106 */ 1107 RTTIMESPEC ValidationTime; 1108 RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp); 1109 1135 * We instruction the verifier to use the signing time counter signature 1136 * when present, but provides the linker time then the current time as 1137 * fallbacks should the timestamp be missing or unusable. 1138 * 1139 * Update: Save the first timestamp we validate with build cert and 1140 * use this as a minimum timestamp for further build cert 1141 * validations. This works around issues with old DLLs that 1142 * we sign against with our certificate (crt, sdl, qt). 1143 * 1144 * Update: If the validation fails, retry with the current timestamp. This 1145 * is a workaround for NTDLL.DLL in build 14971 having a weird 1146 * timestamp: 0xDF1E957E (Sat Aug 14 14:05:18 2088). 1147 */ 1110 1148 uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT 1111 1149 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT 1112 1150 | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY; 1151 1152 /* In ring-0 we don't have all the necessary timestamp server root certificate 1153 * info, so we have to allow using counter signatures unverified there. 1154 * Ditto for the early period of ring-3 hardened stub execution. */ 1113 1155 #ifndef IN_RING0 1114 1156 if (!g_fHaveOtherRoots) 1115 1157 #endif 1116 1158 fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED | RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED; 1117 return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore, 1118 &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo); 1119 } 1120 1121 1122 /** 1123 * RTTimeNow equivaltent that handles ring-3 where we cannot use it. 1124 * 1125 * @returns pNow 1126 * @param pNow Where to return the current time. 1127 */ 1128 static PRTTIMESPEC supHardNtTimeNow(PRTTIMESPEC pNow) 1129 { 1130 #ifdef IN_RING3 1131 /* 1132 * Just read system time. 1133 */ 1134 KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA; 1135 # ifdef RT_ARCH_AMD64 1136 uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->SystemTime; /* This is what KeQuerySystemTime does (missaligned). */ 1137 return RTTimeSpecSetNtTime(pNow, uRet); 1138 # else 1139 1140 LARGE_INTEGER NtTime; 1141 do 1142 { 1143 NtTime.HighPart = pUserSharedData->SystemTime.High1Time; 1144 NtTime.LowPart = pUserSharedData->SystemTime.LowPart; 1145 } while (pUserSharedData->SystemTime.High2Time != NtTime.HighPart); 1146 return RTTimeSpecSetNtTime(pNow, NtTime.QuadPart); 1147 # endif 1148 #else /* IN_RING0 */ 1149 return RTTimeNow(pNow); 1150 #endif /* IN_RING0 */ 1159 1160 /* Fallback timestamps to try: */ 1161 struct { RTTIMESPEC TimeSpec; const char *pszDesc; } aTimes[2]; 1162 unsigned cTimes = 0; 1163 1164 /* 1. The linking timestamp: */ 1165 uint64_t uTimestamp = 0; 1166 int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &uTimestamp, sizeof(uTimestamp)); 1167 if (RT_SUCCESS(rc)) 1168 { 1169 #ifdef IN_RING3 /* Hack alert! (see above) */ 1170 if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING) 1171 && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT) 1172 && uTimestamp < g_uBuildTimestampHack) 1173 uTimestamp = g_uBuildTimestampHack; 1174 #endif 1175 RTTimeSpecSetSeconds(&aTimes[0].TimeSpec, uTimestamp); 1176 aTimes[0].pszDesc = "link"; 1177 cTimes++; 1178 } 1179 else 1180 SUP_DPRINTF(("RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %s: %Rrc", pNtViRdr->szFilename, rc)); 1181 1182 /* 2. Current time. */ 1183 supHardNtTimeNow(&aTimes[cTimes].TimeSpec); 1184 aTimes[cTimes].pszDesc = "now"; 1185 cTimes++; 1186 1187 /* Make the verfication attempts. */ 1188 for (unsigned i = 0; ; i++) 1189 { 1190 Assert(i < cTimes); 1191 rc = RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore, 1192 &aTimes[i].TimeSpec, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo); 1193 if (RT_SUCCESS(rc)) 1194 { 1195 if (rc != VINF_SUCCESS) 1196 { 1197 SUP_DPRINTF(("%s: Signature #%u/%u: info status: %d\n", pNtViRdr->szFilename, pInfo->iSignature, pInfo->cbSignature, rc)); 1198 if (pNtViRdr->rcLastSignatureFailure == VINF_SUCCESS) 1199 pNtViRdr->rcLastSignatureFailure = rc; 1200 } 1201 pNtViRdr->cOkaySignatures++; 1202 1203 #ifdef IN_RING3 /* Hack alert! (see above) */ 1204 if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && cTimes > 1) 1205 g_uBuildTimestampHack = uTimestamp; 1206 #endif 1207 return VINF_SUCCESS; 1208 } 1209 1210 if (rc == VERR_CR_X509_CPV_NOT_VALID_AT_TIME && i + 1 < cTimes) 1211 SUP_DPRINTF(("%s: Signature #%u/%u: VERR_CR_X509_CPV_NOT_VALID_AT_TIME for %#RX64; retrying against current time: %#RX64.\n", 1212 pNtViRdr->szFilename, pInfo->iSignature, pInfo->cbSignature, 1213 RTTimeSpecGetSeconds(&aTimes[0].TimeSpec), RTTimeSpecGetSeconds(&aTimes[1].TimeSpec))); 1214 else 1215 { 1216 /* There are a couple of failures we can tollerate if there are more than 1217 one signature and one of them works out fine. The RTLdrVerifySignature 1218 caller will have to check the failure counts though to make sure 1219 something succeeded. */ 1220 pNtViRdr->rcLastSignatureFailure = rc; 1221 if ( rc == VERR_CR_X509_CPV_NOT_VALID_AT_TIME 1222 || rc == VERR_CR_X509_CPV_NO_TRUSTED_PATHS) 1223 { 1224 SUP_DPRINTF(("%s: Signature #%u/%u: %s (%d) w/ timestamp=%#RX64/%s.\n", pNtViRdr->szFilename, pInfo->iSignature, pInfo->cbSignature, 1225 rc == VERR_CR_X509_CPV_NOT_VALID_AT_TIME ? "VERR_CR_X509_CPV_NOT_VALID_AT_TIME" : "VERR_CR_X509_CPV_NO_TRUSTED_PATHS", rc, 1226 RTTimeSpecGetSeconds(&aTimes[i].TimeSpec), aTimes[i].pszDesc)); 1227 1228 /* This leniency is not applicable to build certificate requirements (signature #1 only). */ 1229 if ( !(pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) 1230 || pInfo->iSignature != 0) 1231 { 1232 pNtViRdr->cNokSignatures++; 1233 rc = VINF_SUCCESS; 1234 } 1235 } 1236 else 1237 SUP_DPRINTF(("%s: Signature #%u/%u: %Rrc w/ timestamp=%#RX64/%s.\n", pNtViRdr->szFilename, pInfo->iSignature, pInfo->cbSignature, 1238 rc, RTTimeSpecGetSeconds(&aTimes[i].TimeSpec), aTimes[i].pszDesc)); 1239 return rc; 1240 } 1241 } 1151 1242 } 1152 1243 … … 1222 1313 * The PKCS #7 SignedData signature is checked in the callback. Any 1223 1314 * signing certificate restrictions are also enforced there. 1224 * 1225 * For the time being, we use the executable timestamp as the 1226 * certificate validation date. We must query that first to avoid 1227 * potential issues re-entering the loader code from the callback. 1228 * 1229 * Update: Save the first timestamp we validate with build cert and 1230 * use this as a minimum timestamp for further build cert 1231 * validations. This works around issues with old DLLs that 1232 * we sign against with our certificate (crt, sdl, qt). 1233 * 1234 * Update: If the validation fails, retry with the current timestamp. This 1235 * is a workaround for NTDLL.DLL in build 14971 having a weird 1236 * timestamp: 0xDF1E957E (Sat Aug 14 14:05:18 2088). 1237 */ 1238 int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp)); 1315 */ 1316 pNtViRdr->cOkaySignatures = 0; 1317 pNtViRdr->cNokSignatures = 0; 1318 pNtViRdr->cTotalSignatures = 0; 1319 pNtViRdr->rcLastSignatureFailure = VINF_SUCCESS; 1320 int rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo); 1239 1321 if (RT_SUCCESS(rc)) 1240 1322 { 1241 #ifdef IN_RING3 /* Hack alert! (see above) */ 1242 if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING) 1243 && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT) 1244 && pNtViRdr->uTimestamp < g_uBuildTimestampHack) 1245 pNtViRdr->uTimestamp = g_uBuildTimestampHack; 1246 #endif 1247 1248 rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo); 1249 1250 #ifdef IN_RING3 /* Hack alert! (see above) */ 1251 if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc)) 1252 g_uBuildTimestampHack = pNtViRdr->uTimestamp; 1253 #endif 1254 1255 if (rc == VERR_CR_X509_CPV_NOT_VALID_AT_TIME) 1323 Assert(pNtViRdr->cOkaySignatures + pNtViRdr->cNokSignatures == pNtViRdr->cTotalSignatures); 1324 if ( !pNtViRdr->cOkaySignatures 1325 || pNtViRdr->cOkaySignatures + pNtViRdr->cNokSignatures < pNtViRdr->cTotalSignatures /* paranoia */) 1256 1326 { 1257 RTTIMESPEC Now; 1258 uint64_t uOld = pNtViRdr->uTimestamp; 1259 pNtViRdr->uTimestamp = RTTimeSpecGetSeconds(supHardNtTimeNow(&Now)); 1260 SUP_DPRINTF(("%ls: VERR_CR_X509_CPV_NOT_VALID_AT_TIME for %#RX64; retrying against current time: %#RX64.\n", 1261 pwszName, uOld, pNtViRdr->uTimestamp)); NOREF(uOld); 1262 rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo); 1327 rc = pNtViRdr->rcLastSignatureFailure; 1328 AssertStmt(RT_FAILURE_NP(rc), rc = VERR_INTERNAL_ERROR_3); 1263 1329 } 1264 1265 /*1266 * Microsoft doesn't sign a whole bunch of DLLs, so we have to1267 * ASSUME that a bunch of system DLLs are fine. 1268 */1269 if (rc == VERR_LDRVI_NOT_SIGNED)1270 rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, pNtViRdr->hFile, rc);1271 if (RT_FAILURE(rc))1272 RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName);1273 1274 /*1275 * Check for the signature checking enforcement, if requested to do so.1276 */ 1277 if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT))1278 {1279 bool fEnforced = false;1280 int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced));1281 if (RT_FAILURE(rc2))1282 rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.",1283 pwszName, rc2);1284 else if (!fEnforced)1285 rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED,1286 "The image '%ls' was not linked with /IntegrityCheck.", pwszName);1287 }1288 }1289 else1290 RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc);1330 else if (rc == VINF_SUCCESS && RT_SUCCESS(pNtViRdr->rcLastSignatureFailure)) 1331 rc = pNtViRdr->rcLastSignatureFailure; 1332 } 1333 1334 /* 1335 * Microsoft doesn't sign a whole bunch of DLLs, so we have to 1336 * ASSUME that a bunch of system DLLs are fine. 1337 */ 1338 if (rc == VERR_LDRVI_NOT_SIGNED) 1339 rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, pNtViRdr->hFile, rc); 1340 if (RT_FAILURE(rc)) 1341 RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName); 1342 1343 /* 1344 * Check for the signature checking enforcement, if requested to do so. 1345 */ 1346 if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)) 1347 { 1348 bool fEnforced = false; 1349 int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced)); 1350 if (RT_FAILURE(rc2)) 1351 rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.", 1352 pwszName, rc2); 1353 else if (!fEnforced) 1354 rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED, 1355 "The image '%ls' was not linked with /IntegrityCheck.", pwszName); 1356 } 1291 1357 1292 1358 #ifdef IN_RING3 -
trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp
r85678 r86549 5537 5537 * Finally, let the caller verify the certificate chain for the PKCS#7 bit. 5538 5538 */ 5539 rc = pfnCallback(&pThis->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA, 5540 &pSignature->ContentInfo, sizeof(pSignature->ContentInfo), 5541 pSignature->aCodeDirs[0].pCodeDir, pSignature->aCodeDirs[0].cb, 5542 pErrInfo, pvUser); 5539 RTLDRSIGNATUREINFO Info; 5540 Info.iSignature = 0; 5541 Info.cSignatures = 1; 5542 Info.enmType = RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA; 5543 Info.pvSignature = &pSignature->ContentInfo; 5544 Info.cbSignature = sizeof(pSignature->ContentInfo); 5545 Info.pvExternalData = pSignature->aCodeDirs[0].pCodeDir; 5546 Info.cbExternalData = pSignature->aCodeDirs[0].cb; 5547 rc = pfnCallback(&pThis->Core, &Info, pErrInfo, pvUser); 5543 5548 } 5544 5549 } -
trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
r85121 r86549 216 216 #ifndef IPRT_WITHOUT_LDR_VERIFY 217 217 /** 218 * Parsed signature data.219 */ 220 typedef struct RTLDRPESIGNATURE 218 * Parsed data for one signature. 219 */ 220 typedef struct RTLDRPESIGNATUREONE 221 221 { 222 222 /** The outer content info wrapper. */ 223 RTCRPKCS7CONTENTINFOContentInfo;223 PRTCRPKCS7CONTENTINFO pContentInfo; 224 224 /** Pointer to the decoded SignedData inside the ContentInfo member. */ 225 225 PRTCRPKCS7SIGNEDDATA pSignedData; … … 228 228 /** The digest type employed by the signature. */ 229 229 RTDIGESTTYPE enmDigest; 230 230 /** Set if we've already validate the image hash. */ 231 bool fValidatedImageHash; 232 /** The signature number. */ 233 uint16_t iSignature; 234 /** Hash result. */ 235 RTLDRPEHASHRESUNION HashRes; 236 } RTLDRPESIGNATUREONE; 237 /** Pointer to the parsed data of one signature. */ 238 typedef RTLDRPESIGNATUREONE *PRTLDRPESIGNATUREONE; 239 240 /** 241 * Parsed signature data. 242 */ 243 typedef struct RTLDRPESIGNATURE 244 { 231 245 /** Pointer to the raw signatures. This is allocated in the continuation of 232 246 * this structure to keep things simple. The size is given by the security 233 247 * export directory. */ 234 248 WIN_CERTIFICATE const *pRawData; 235 249 /** The outer content info wrapper (primary signature). */ 250 RTCRPKCS7CONTENTINFO PrimaryContentInfo; 251 /** The info for the primary signature. */ 252 RTLDRPESIGNATUREONE Primary; 253 /** Number of nested signatures (zero if none). */ 254 uint16_t cNested; 255 /** Pointer to an array of nested signatures (NULL if none). */ 256 PRTLDRPESIGNATUREONE paNested; 236 257 /** Hash scratch data. */ 237 258 RTLDRPEHASHCTXUNION HashCtx; 238 /** Hash result. */239 RTLDRPEHASHRESUNION HashRes;240 259 } RTLDRPESIGNATURE; 241 260 /** Pointed to SigneData parsing stat and output. */ … … 2523 2542 { 2524 2543 RT_NOREF_PV(pModPe); 2525 RTCrPkcs7ContentInfo_Delete(&pSignature->ContentInfo); 2544 RTCrPkcs7ContentInfo_Delete(&pSignature->PrimaryContentInfo); 2545 if (pSignature->paNested > 0) 2546 { 2547 RTMemTmpFree(pSignature->paNested); 2548 pSignature->paNested = NULL; 2549 } 2526 2550 RTMemTmpFree(pSignature); 2551 } 2552 2553 2554 /** 2555 * Handles nested signatures. 2556 * 2557 * @returns IPRT status code. 2558 * @param pSignature The signature status structure. Returns with 2559 * cNested = 0 and paNested = NULL if no nested 2560 * signatures. 2561 * @param pErrInfo Where to return extended error info (optional). 2562 */ 2563 static int rtldrPE_VerifySignatureDecodeNested(PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo) 2564 { 2565 Assert(pSignature->cNested == 0); 2566 Assert(pSignature->paNested == NULL); 2567 2568 /* 2569 * Count nested signatures. 2570 */ 2571 uint32_t cNested = 0; 2572 for (uint32_t iSignerInfo = 0; iSignerInfo < pSignature->Primary.pSignedData->SignerInfos.cItems; iSignerInfo++) 2573 { 2574 PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignature->Primary.pSignedData->SignerInfos.papItems[iSignerInfo]; 2575 for (uint32_t iAttrib = 0; iAttrib < pSignerInfo->UnauthenticatedAttributes.cItems; iAttrib++) 2576 { 2577 PCRTCRPKCS7ATTRIBUTE pAttrib = pSignerInfo->UnauthenticatedAttributes.papItems[iAttrib]; 2578 if (pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE) 2579 { 2580 Assert(pAttrib->uValues.pContentInfos); 2581 cNested += pAttrib->uValues.pContentInfos->cItems; 2582 } 2583 } 2584 } 2585 if (!cNested) 2586 return VINF_SUCCESS; 2587 2588 /* 2589 * Allocate and populate the info structures. 2590 */ 2591 pSignature->paNested = (PRTLDRPESIGNATUREONE)RTMemTmpAllocZ(sizeof(pSignature->paNested[0]) * cNested); 2592 if (!pSignature->paNested) 2593 return RTErrInfoSetF(pErrInfo, VERR_NO_TMP_MEMORY, "Failed to allocate space for %u nested signatures", cNested); 2594 pSignature->cNested = cNested; 2595 2596 cNested = 0; 2597 for (uint32_t iSignerInfo = 0; iSignerInfo < pSignature->Primary.pSignedData->SignerInfos.cItems; iSignerInfo++) 2598 { 2599 PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignature->Primary.pSignedData->SignerInfos.papItems[iSignerInfo]; 2600 for (uint32_t iAttrib = 0; iAttrib < pSignerInfo->UnauthenticatedAttributes.cItems; iAttrib++) 2601 { 2602 PCRTCRPKCS7ATTRIBUTE pAttrib = pSignerInfo->UnauthenticatedAttributes.papItems[iAttrib]; 2603 if (pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE) 2604 { 2605 for (uint32_t iItem = 0; iItem < pAttrib->uValues.pContentInfos->cItems; iItem++, cNested++) 2606 { 2607 PRTLDRPESIGNATUREONE pInfo = &pSignature->paNested[cNested]; 2608 PRTCRPKCS7CONTENTINFO pContentInfo = pAttrib->uValues.pContentInfos->papItems[iItem]; 2609 pInfo->pContentInfo = pContentInfo; 2610 pInfo->iSignature = cNested; 2611 2612 if (RTCrPkcs7ContentInfo_IsSignedData(pInfo->pContentInfo)) 2613 { /* likely */ } 2614 else 2615 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/ 2616 "Nested#%u: PKCS#7 is not 'signedData': %s", cNested, pInfo->pContentInfo->ContentType.szObjId); 2617 PRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData; 2618 pInfo->pSignedData = pSignedData; 2619 2620 /* 2621 * Check the authenticode bits. 2622 */ 2623 if (!strcmp(pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID)) 2624 { /* likely */ } 2625 else 2626 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, 2627 "Nested#%u: Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)", 2628 cNested, pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 2629 pInfo->pIndData = pSignedData->ContentInfo.u.pIndirectDataContent; 2630 Assert(pInfo->pIndData); 2631 2632 /* 2633 * Check that things add up. 2634 */ 2635 int rc = RTCrPkcs7SignedData_CheckSanity(pSignedData, 2636 RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE 2637 | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH 2638 | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, 2639 pErrInfo, "SD"); 2640 if (RT_SUCCESS(rc)) 2641 rc = RTCrSpcIndirectDataContent_CheckSanityEx(pInfo->pIndData, 2642 pSignedData, 2643 RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH, 2644 pErrInfo); 2645 if (RT_SUCCESS(rc)) 2646 { 2647 PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pInfo->pIndData->DigestInfo.DigestAlgorithm; 2648 pInfo->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm); 2649 AssertReturn(pInfo->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */ 2650 } 2651 else 2652 return rc; 2653 } 2654 } 2655 } 2656 } 2657 2658 return VINF_SUCCESS; 2527 2659 } 2528 2660 … … 2552 2684 "WinCert"); 2553 2685 2554 int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pSignature->ContentInfo, "CI"); 2686 PRTLDRPESIGNATUREONE pInfo = &pSignature->Primary; 2687 pInfo->pContentInfo = &pSignature->PrimaryContentInfo; 2688 int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, pInfo->pContentInfo, "CI"); 2555 2689 if (RT_SUCCESS(rc)) 2556 2690 { 2557 if (RTCrPkcs7ContentInfo_IsSignedData( &pSignature->ContentInfo))2558 { 2559 p Signature->pSignedData = pSignature->ContentInfo.u.pSignedData;2691 if (RTCrPkcs7ContentInfo_IsSignedData(pInfo->pContentInfo)) 2692 { 2693 pInfo->pSignedData = pInfo->pContentInfo->u.pSignedData; 2560 2694 2561 2695 /* 2562 2696 * Decode the authenticode bits. 2563 2697 */ 2564 if (!strcmp(p Signature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))2565 { 2566 p Signature->pIndData = pSignature->pSignedData->ContentInfo.u.pIndirectDataContent;2567 Assert(p Signature->pIndData);2698 if (!strcmp(pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID)) 2699 { 2700 pInfo->pIndData = pInfo->pSignedData->ContentInfo.u.pIndirectDataContent; 2701 Assert(pInfo->pIndData); 2568 2702 2569 2703 /* 2570 2704 * Check that things add up. 2571 2705 */ 2706 rc = RTCrPkcs7SignedData_CheckSanity(pInfo->pSignedData, 2707 RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE 2708 | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH 2709 | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, 2710 pErrInfo, "SD"); 2572 2711 if (RT_SUCCESS(rc)) 2573 rc = RTCrPkcs7SignedData_CheckSanity(pSignature->pSignedData, 2574 RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE 2575 | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH 2576 | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, 2577 pErrInfo, "SD"); 2578 if (RT_SUCCESS(rc)) 2579 rc = RTCrSpcIndirectDataContent_CheckSanityEx(pSignature->pIndData, 2580 pSignature->pSignedData, 2712 rc = RTCrSpcIndirectDataContent_CheckSanityEx(pInfo->pIndData, 2713 pInfo->pSignedData, 2581 2714 RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH, 2582 2715 pErrInfo); 2583 2716 if (RT_SUCCESS(rc)) 2584 2717 { 2585 PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pSignature->pIndData->DigestInfo.DigestAlgorithm; 2586 pSignature->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm); 2587 AssertReturn(pSignature->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */ 2718 PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pInfo->pIndData->DigestInfo.DigestAlgorithm; 2719 pInfo->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm); 2720 AssertReturn(pInfo->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */ 2721 2722 /* 2723 * Deal with nested signatures. 2724 */ 2725 rc = rtldrPE_VerifySignatureDecodeNested(pSignature, pErrInfo); 2588 2726 } 2589 2727 } … … 2591 2729 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, 2592 2730 "Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)", 2593 p Signature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);2731 pInfo->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 2594 2732 } 2595 2733 else 2596 2734 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/ 2597 "PKCS#7 is not 'signedData': %s", p Signature->ContentInfo.ContentType.szObjId);2735 "PKCS#7 is not 'signedData': %s", pInfo->pContentInfo->ContentType.szObjId); 2598 2736 } 2599 2737 return rc; … … 2601 2739 2602 2740 2741 2603 2742 static int rtldrPE_VerifyAllPageHashes(PRTLDRMODPE pModPe, PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib, RTDIGESTTYPE enmDigest, 2604 void *pvScratch, size_t cbScratch, PRTERRINFO pErrInfo)2743 void *pvScratch, size_t cbScratch, uint32_t iSignature, PRTERRINFO pErrInfo) 2605 2744 { 2606 2745 AssertReturn(cbScratch >= _4K, VERR_INTERNAL_ERROR_3); … … 2618 2757 if (cPages * (cbHash + 4) != pAttrib->u.pPageHashes->RawData.Asn1Core.cb) 2619 2758 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_SIZE_OVERFLOW, 2620 " Page hashes size issue: cb=%#x cbHash=%#x",2621 pAttrib->u.pPageHashes->RawData.Asn1Core.cb, cbHash);2759 "Signature #%u - Page hashes size issue in: cb=%#x cbHash=%#x", 2760 iSignature, pAttrib->u.pPageHashes->RawData.Asn1Core.cb, cbHash); 2622 2761 2623 2762 /* … … 2640 2779 if (RT_UNLIKELY(offPageInFile >= SpecialPlaces.cbToHash)) 2641 2780 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG, 2642 " Page hash entry #%u is beyond the signature table start: %#x, %#x",2643 i Page, offPageInFile, SpecialPlaces.cbToHash);2781 "Signature #%u - Page hash entry #%u is beyond the signature table start: %#x, %#x", 2782 iSignature, iPage, offPageInFile, SpecialPlaces.cbToHash); 2644 2783 if (RT_UNLIKELY(offPageInFile < offPrev)) 2645 2784 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_NOT_STRICTLY_SORTED, 2646 " Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n",2647 i Page, offPageInFile, offPrev);2785 "Signature #%u - Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n", 2786 iSignature, iPage, offPageInFile, offPrev); 2648 2787 2649 2788 #ifdef COMPLICATED_AND_WRONG … … 2666 2805 else 2667 2806 return RTErrInfoSetF(pErrInfo, VERR_PAGE_HASH_TAB_HASHES_NON_SECTION_DATA, 2668 "Page hash entry #%u isn't in any section: %#x", iPage, offPageInFile); 2807 "Signature #%u - Page hash entry #%u isn't in any section: %#x", 2808 iSignature, iPage, offPageInFile); 2669 2809 } 2670 2810 } … … 2710 2850 if (RT_FAILURE(rc)) 2711 2851 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_READ_ERROR_HASH, 2712 " Page hash read error at %#x: %Rrc (cbScratchRead=%#zx)",2713 offScratchRead, rc, cbScratchRead);2852 "Signature #%u - Page hash read error at %#x: %Rrc (cbScratchRead=%#zx)", 2853 iSignature, offScratchRead, rc, cbScratchRead); 2714 2854 } 2715 2855 … … 2778 2918 if (memcmp(pbHashTab, &HashRes, cbHash) != 0) 2779 2919 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_MISMATCH, 2780 "Page hash failed for page #%u, @%#x, %#x bytes: %.*Rhxs != %.*Rhxs", 2781 iPage, offPageInFile, cbPageInFile, (size_t)cbHash, pbHashTab, (size_t)cbHash, &HashRes); 2920 "Signature #%u - Page hash failed for page #%u, @%#x, %#x bytes: %.*Rhxs != %.*Rhxs", 2921 iSignature, iPage, offPageInFile, cbPageInFile, (size_t)cbHash, pbHashTab, 2922 (size_t)cbHash, &HashRes); 2782 2923 pbHashTab += cbHash; 2783 2924 offPrev = offPageInFile; … … 2789 2930 if (!ASMMemIsZero(pbHashTab + 4, cbHash)) 2790 2931 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG, 2791 " Maltformfinal page hash table entry: #%u %#010x %.*Rhxs",2792 cPages - 1, RT_MAKE_U32_FROM_U8(pbHashTab[0], pbHashTab[1], pbHashTab[2], pbHashTab[3]),2932 "Signature #%u - Malformed final page hash table entry: #%u %#010x %.*Rhxs", 2933 iSignature, cPages - 1, RT_MAKE_U32_FROM_U8(pbHashTab[0], pbHashTab[1], pbHashTab[2], pbHashTab[3]), 2793 2934 (size_t)cbHash, pbHashTab + 4); 2794 2935 return VINF_SUCCESS; 2936 } 2937 2938 2939 static int rtldrPE_VerifySignatureValidateOnePageHashes(PRTLDRMODPE pModPe, PRTLDRPESIGNATUREONE pInfo, 2940 void *pvScratch, uint32_t cbScratch, PRTERRINFO pErrInfo) 2941 { 2942 /* 2943 * Compare the page hashes if present. 2944 * 2945 * Seems the difference between V1 and V2 page hash attributes is 2946 * that v1 uses SHA-1 while v2 uses SHA-256. The data structures 2947 * seems to be identical otherwise. Initially we assumed the digest 2948 * algorithm was supposed to be RTCRSPCINDIRECTDATACONTENT::DigestInfo, 2949 * i.e. the same as for the whole image hash. The initial approach 2950 * worked just fine, but this makes more sense. 2951 * 2952 * (See also comments in osslsigncode.c (google it).) 2953 */ 2954 PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib; 2955 /* V2 - SHA-256: */ 2956 pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pInfo->pIndData, 2957 RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2); 2958 if (pAttrib) 2959 return rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA256, pvScratch, cbScratch, 2960 pInfo->iSignature + 1, pErrInfo); 2961 2962 /* V1 - SHA-1: */ 2963 pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pInfo->pIndData, 2964 RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1); 2965 if (pAttrib) 2966 return rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA1, pvScratch, cbScratch, 2967 pInfo->iSignature + 1, pErrInfo); 2968 2969 /* No page hashes: */ 2970 return VINF_SUCCESS; 2971 } 2972 2973 2974 static int rtldrPE_VerifySignatureValidateOneImageHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, 2975 PRTLDRPESIGNATUREONE pInfo, void *pvScratch, uint32_t cbScratch, 2976 PRTERRINFO pErrInfo) 2977 { 2978 /* 2979 * Assert sanity. 2980 */ 2981 AssertReturn(pInfo->enmDigest > RTDIGESTTYPE_INVALID && pInfo->enmDigest < RTDIGESTTYPE_END, VERR_INTERNAL_ERROR_4); 2982 AssertPtrReturn(pInfo->pIndData, VERR_INTERNAL_ERROR_5); 2983 AssertReturn(RTASN1CORE_IS_PRESENT(&pInfo->pIndData->DigestInfo.Digest.Asn1Core), VERR_INTERNAL_ERROR_5); 2984 AssertPtrReturn(pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, VERR_INTERNAL_ERROR_5); 2985 2986 /* 2987 * Skip it if we've already verified it. 2988 */ 2989 if (pInfo->fValidatedImageHash) 2990 return VINF_SUCCESS; 2991 2992 /* 2993 * Calculate it. 2994 */ 2995 uint32_t const cbHash = rtLdrPE_HashGetHashSize(pInfo->enmDigest); 2996 AssertReturn(pInfo->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash, VERR_INTERNAL_ERROR_5); 2997 2998 int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, pInfo->enmDigest, 2999 &pSignature->HashCtx, &pInfo->HashRes, pErrInfo); 3000 if (RT_SUCCESS(rc)) 3001 { 3002 pInfo->fValidatedImageHash = true; 3003 if (memcmp(&pInfo->HashRes, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash) == 0) 3004 { 3005 /* 3006 * Verify other signatures with the same digest type. 3007 */ 3008 RTLDRPEHASHRESUNION const * const pHashRes = &pInfo->HashRes; 3009 for (uint32_t i = 0; i < pSignature->cNested; i++) 3010 { 3011 pInfo = &pSignature->paNested[i]; /* Note! pInfo changes! */ 3012 if ( !pInfo->fValidatedImageHash 3013 && pInfo->enmDigest == pInfo->enmDigest 3014 /* paranoia from the top of this function: */ 3015 && pInfo->pIndData 3016 && RTASN1CORE_IS_PRESENT(&pInfo->pIndData->DigestInfo.Digest.Asn1Core) 3017 && pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv 3018 && pInfo->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash) 3019 { 3020 pInfo->fValidatedImageHash = true; 3021 if (memcmp(pHashRes, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash) != 0) 3022 { 3023 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH, 3024 "Full image signature #%u mismatch: %.*Rhxs, expected %.*Rhxs", pInfo->iSignature + 1, 3025 cbHash, pHashRes, 3026 cbHash, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv); 3027 break; 3028 } 3029 } 3030 } 3031 } 3032 else 3033 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH, 3034 "Full image signature #%u mismatch: %.*Rhxs, expected %.*Rhxs", pInfo->iSignature + 1, 3035 cbHash, &pInfo->HashRes, 3036 cbHash, pInfo->pIndData->DigestInfo.Digest.Asn1Core.uData.pv); 3037 } 3038 return rc; 2795 3039 } 2796 3040 … … 2806 3050 static int rtldrPE_VerifySignatureValidateHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo) 2807 3051 { 2808 AssertReturn(pSignature->enmDigest > RTDIGESTTYPE_INVALID && pSignature->enmDigest < RTDIGESTTYPE_END, VERR_INTERNAL_ERROR_4);2809 AssertPtrReturn(pSignature->pIndData, VERR_INTERNAL_ERROR_5);2810 AssertReturn(RTASN1CORE_IS_PRESENT(&pSignature->pIndData->DigestInfo.Digest.Asn1Core), VERR_INTERNAL_ERROR_5);2811 AssertPtrReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, VERR_INTERNAL_ERROR_5);2812 2813 uint32_t const cbHash = rtLdrPE_HashGetHashSize(pSignature->enmDigest);2814 AssertReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash, VERR_INTERNAL_ERROR_5);2815 2816 3052 /* 2817 3053 * Allocate a temporary memory buffer. … … 2820 3056 * heap fragmentation. 2821 3057 */ 2822 # ifdef IN_RING03058 # ifdef IN_RING0 2823 3059 uint32_t cbScratch = _256K - _4K; 2824 # else3060 # else 2825 3061 uint32_t cbScratch = _1M; 2826 # endif3062 # endif 2827 3063 void *pvScratch = RTMemTmpAlloc(cbScratch); 2828 3064 if (!pvScratch) … … 2835 3071 2836 3072 /* 2837 * Calculate and compare the full image hash. 2838 */ 2839 int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, pSignature->enmDigest, 2840 &pSignature->HashCtx, &pSignature->HashRes, pErrInfo); 3073 * Verify signatures. 3074 */ 3075 /* Image hashes: */ 3076 int rc = rtldrPE_VerifySignatureValidateOneImageHash(pModPe, pSignature, &pSignature->Primary, 3077 pvScratch, cbScratch, pErrInfo); 3078 for (unsigned i = 0; i < pSignature->cNested && RT_SUCCESS(rc); i++) 3079 rc = rtldrPE_VerifySignatureValidateOneImageHash(pModPe, pSignature, &pSignature->paNested[i], 3080 pvScratch, cbScratch, pErrInfo); 3081 3082 /* Page hashes: */ 2841 3083 if (RT_SUCCESS(rc)) 2842 3084 { 2843 if (!memcmp(&pSignature->HashRes, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash)) 2844 { 2845 /* 2846 * Compare the page hashes if present. 2847 * 2848 * Seems the difference between V1 and V2 page hash attributes is 2849 * that v1 uses SHA-1 while v2 uses SHA-256. The data structures 2850 * seems to be identical otherwise. Initially we assumed the digest 2851 * algorithm was supposed to be RTCRSPCINDIRECTDATACONTENT::DigestInfo, 2852 * i.e. the same as for the whole image hash. The initial approach 2853 * worked just fine, but this makes more sense. 2854 * 2855 * (See also comments in osslsigncode.c (google it).) 2856 */ 2857 PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib; 2858 pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pSignature->pIndData, 2859 RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2); 2860 if (pAttrib) 2861 rc = rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA256, pvScratch, cbScratch, pErrInfo); 2862 else 2863 { 2864 pAttrib = RTCrSpcIndirectDataContent_GetPeImageObjAttrib(pSignature->pIndData, 2865 RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1); 2866 if (pAttrib) 2867 rc = rtldrPE_VerifyAllPageHashes(pModPe, pAttrib, RTDIGESTTYPE_SHA1, pvScratch, cbScratch, pErrInfo); 2868 } 2869 } 2870 else 2871 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH, 2872 "Full image signature mismatch: %.*Rhxs, expected %.*Rhxs", 2873 cbHash, &pSignature->HashRes, 2874 cbHash, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv); 2875 } 2876 3085 rc = rtldrPE_VerifySignatureValidateOnePageHashes(pModPe, &pSignature->Primary, pvScratch, cbScratch, pErrInfo); 3086 for (unsigned i = 0; i < pSignature->cNested && RT_SUCCESS(rc); i++) 3087 rc = rtldrPE_VerifySignatureValidateOnePageHashes(pModPe, &pSignature->paNested[i], pvScratch, cbScratch, pErrInfo); 3088 } 3089 3090 /* 3091 * Ditch the scratch buffer. 3092 */ 2877 3093 RTMemTmpFree(pvScratch); 2878 3094 return rc; … … 2901 3117 if (RT_SUCCESS(rc)) 2902 3118 { 2903 rc = pfnCallback(&pModPe->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA, 2904 &pSignature->ContentInfo, sizeof(pSignature->ContentInfo), 2905 NULL /*pvExternalData*/, 0 /*cbExternalData*/, 2906 pErrInfo, pvUser); 3119 /* 3120 * Work the callback. 3121 */ 3122 /* The primary signature: */ 3123 RTLDRSIGNATUREINFO Info; 3124 Info.iSignature = 0; 3125 Info.cSignatures = (uint16_t)(1 + pSignature->cNested); 3126 Info.enmType = RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA; 3127 Info.pvSignature = pSignature->Primary.pContentInfo; 3128 Info.cbSignature = sizeof(*pSignature->Primary.pContentInfo); 3129 Info.pvExternalData = NULL; 3130 Info.cbExternalData = 0; 3131 rc = pfnCallback(&pModPe->Core, &Info, pErrInfo, pvUser); 3132 3133 /* The nested signatures: */ 3134 for (uint32_t iNested = 0; iNested < pSignature->cNested && rc == VINF_SUCCESS; iNested++) 3135 { 3136 Info.iSignature = (uint16_t)(1 + iNested); 3137 Info.cSignatures = (uint16_t)(1 + pSignature->cNested); 3138 Info.enmType = RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA; 3139 Info.pvSignature = pSignature->paNested[iNested].pContentInfo; 3140 Info.cbSignature = sizeof(*pSignature->paNested[iNested].pContentInfo); 3141 Info.pvExternalData = NULL; 3142 Info.cbExternalData = 0; 3143 rc = pfnCallback(&pModPe->Core, &Info, pErrInfo, pvUser); 3144 } 2907 3145 } 2908 3146 rtldrPE_VerifySignatureDestroy(pModPe, pSignature); -
trunk/src/VBox/Runtime/testcase/tstRTLdrVerifyPeImage.cpp
r82968 r86549 44 44 static int g_iDummy = 0; 45 45 46 static DECLCALLBACK(int) TestCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature, 47 void const *pvSignature, size_t cbSignature, 48 void const *pvExternalData, size_t cbExternalData, 49 PRTERRINFO pErrInfo, void *pvUser) 46 47 static DECLCALLBACK(int) TestCallback(RTLDRMOD hLdrMod, PCRTLDRSIGNATUREINFO pInfo, PRTERRINFO pErrInfo, void *pvUser) 50 48 { 51 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(enmSignature); RT_NOREF_PV(pvSignature); RT_NOREF_PV(cbSignature); 52 RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pvUser); RT_NOREF_PV(pvExternalData); RT_NOREF_PV(cbExternalData); 49 RT_NOREF(hLdrMod, pInfo, pErrInfo, pvUser); 53 50 return VINF_SUCCESS; 54 51 } 55 56 52 57 53 -
trunk/src/VBox/Runtime/tools/RTSignTool.cpp
r84380 r86549 1252 1252 int cVerbose; 1253 1253 enum { kSignType_Windows, kSignType_OSX } enmSignType; 1254 uint64_t uTimestamp;1255 1254 RTLDRARCH enmLdrArch; 1255 uint32_t cBad; 1256 uint32_t cOkay; 1257 const char *pszFilename; 1256 1258 } VERIFYEXESTATE; 1257 1259 … … 1402 1404 } 1403 1405 1404 1405 1406 /** @callback_method_impl{FNRTLDRVALIDATESIGNEDDATA} */ 1406 static DECLCALLBACK(int) VerifyExeCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature, 1407 void const *pvSignature, size_t cbSignature, 1408 void const *pvExternalData, size_t cbExternalData, 1409 PRTERRINFO pErrInfo, void *pvUser) 1407 static DECLCALLBACK(int) VerifyExeCallback(RTLDRMOD hLdrMod, PCRTLDRSIGNATUREINFO pInfo, PRTERRINFO pErrInfo, void *pvUser) 1410 1408 { 1411 1409 VERIFYEXESTATE *pState = (VERIFYEXESTATE *)pvUser; 1412 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(cbSignature);1413 1414 switch ( enmSignature)1410 RT_NOREF_PV(hLdrMod); 1411 1412 switch (pInfo->enmType) 1415 1413 { 1416 1414 case RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA: 1417 1415 { 1418 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pvSignature; 1419 1420 RTTIMESPEC ValidationTime; 1421 RTTimeSpecSetSeconds(&ValidationTime, pState->uTimestamp); 1416 PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pInfo->pvSignature; 1422 1417 1423 1418 /* 1424 * Dump the signed data if so requested. 1419 * Dump the signed data if so requested and it's the first one, assuming that 1420 * additional signatures in contained wihtin the same ContentInfo structure. 1425 1421 */ 1426 if (pState->cVerbose )1422 if (pState->cVerbose && pInfo->iSignature == 0) 1427 1423 RTAsn1Dump(&pContentInfo->SeqCore.Asn1Core, 0, 0, RTStrmDumpPrintfV, g_pStdOut); 1428 1424 1429 1430 1425 /* 1431 * Do the actual verification. Will have to modify this so it takes 1432 * the authenticode policies into account. 1426 * We'll try different alternative timestamps here. 1433 1427 */ 1434 if (pvExternalData) 1435 return RTCrPkcs7VerifySignedDataWithExternalData(pContentInfo, 1436 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 1437 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT 1438 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT 1439 | RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS, 1440 pState->hAdditionalStore, pState->hRootStore, &ValidationTime, 1441 VerifyExecCertVerifyCallback, pState, 1442 pvExternalData, cbExternalData, pErrInfo); 1443 return RTCrPkcs7VerifySignedData(pContentInfo, 1444 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 1445 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT 1446 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT 1447 | RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS, 1448 pState->hAdditionalStore, pState->hRootStore, &ValidationTime, 1449 VerifyExecCertVerifyCallback, pState, pErrInfo); 1428 struct { RTTIMESPEC TimeSpec; const char *pszDesc; } aTimes[2]; 1429 unsigned cTimes = 0; 1430 1431 /* Linking timestamp: */ 1432 uint64_t uLinkingTime = 0; 1433 int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &uLinkingTime, sizeof(uLinkingTime)); 1434 if (RT_SUCCESS(rc)) 1435 { 1436 RTTimeSpecSetSeconds(&aTimes[0].TimeSpec, uLinkingTime); 1437 aTimes[0].pszDesc = "at link time"; 1438 cTimes++; 1439 } 1440 else if (rc != VERR_NOT_FOUND) 1441 RTMsgError("RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on '%s': %Rrc\n", pState->pszFilename, rc); 1442 1443 /* Now: */ 1444 RTTimeNow(&aTimes[cTimes].TimeSpec); 1445 aTimes[cTimes].pszDesc = "now"; 1446 cTimes++; 1447 1448 /* 1449 * Do the actual verification. 1450 */ 1451 for (unsigned iTime = 0; iTime < cTimes; iTime++) 1452 { 1453 if (pInfo->pvExternalData) 1454 rc = RTCrPkcs7VerifySignedDataWithExternalData(pContentInfo, 1455 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 1456 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT 1457 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT 1458 | RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS, 1459 pState->hAdditionalStore, pState->hRootStore, 1460 &aTimes[iTime].TimeSpec, 1461 VerifyExecCertVerifyCallback, pState, 1462 pInfo->pvExternalData, pInfo->cbExternalData, pErrInfo); 1463 else 1464 rc = RTCrPkcs7VerifySignedData(pContentInfo, 1465 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 1466 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT 1467 | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT 1468 | RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS, 1469 pState->hAdditionalStore, pState->hRootStore, 1470 &aTimes[iTime].TimeSpec, 1471 VerifyExecCertVerifyCallback, pState, pErrInfo); 1472 if (RT_SUCCESS(rc)) 1473 { 1474 Assert(rc == VINF_SUCCESS); 1475 if (pInfo->cSignatures == 1) 1476 RTMsgInfo("'%s' is valid %s.\n", pState->pszFilename, aTimes[iTime].pszDesc); 1477 else 1478 RTMsgInfo("'%s' signature #%u is valid %s.\n", 1479 pState->pszFilename, pInfo->iSignature + 1, aTimes[iTime].pszDesc); 1480 pState->cOkay++; 1481 return VINF_SUCCESS; 1482 } 1483 if (rc != VERR_CR_X509_CPV_NOT_VALID_AT_TIME) 1484 { 1485 if (pInfo->cSignatures == 1) 1486 RTMsgError("%s: Failed to verify signature: %Rrc%#RTeim\n", pState->pszFilename, rc, pErrInfo); 1487 else 1488 RTMsgError("%s: Failed to verify signature #%u: %Rrc%#RTeim\n", 1489 pState->pszFilename, pInfo->iSignature + 1, rc, pErrInfo); 1490 pState->cBad++; 1491 return VINF_SUCCESS; 1492 } 1493 } 1494 1495 if (pInfo->cSignatures == 1) 1496 RTMsgError("%s: Signature is not valid at present or link time.\n", pState->pszFilename); 1497 else 1498 RTMsgError("%s: Signature #%u is not valid at present or link time.\n", 1499 pState->pszFilename, pInfo->iSignature + 1); 1500 pState->cBad++; 1501 return VINF_SUCCESS; 1450 1502 } 1451 1503 1452 1504 default: 1453 return RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Unsupported signature type: %d", enmSignature);1505 return RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Unsupported signature type: %d", pInfo->enmType); 1454 1506 } 1455 1507 } … … 1468 1520 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening executable image '%s': %Rrc", pszFilename, rc); 1469 1521 1470 1471 RTTIMESPEC Now; 1472 bool fTriedNow = false; 1473 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pState->uTimestamp, sizeof(pState->uTimestamp)); 1474 if (rc == VERR_NOT_FOUND) 1475 { 1476 fTriedNow = true; 1477 pState->uTimestamp = RTTimeSpecGetSeconds(RTTimeNow(&Now)); 1478 rc = VINF_SUCCESS; 1479 } 1480 if (RT_SUCCESS(rc)) 1481 { 1482 rc = RTLdrVerifySignature(hLdrMod, VerifyExeCallback, pState, RTErrInfoInitStatic(pStaticErrInfo)); 1483 if (RT_SUCCESS(rc)) 1484 RTMsgInfo("'%s' is valid.\n", pszFilename); 1485 else if (rc == VERR_CR_X509_CPV_NOT_VALID_AT_TIME && !fTriedNow) 1486 { 1487 pState->uTimestamp = RTTimeSpecGetSeconds(RTTimeNow(&Now)); 1488 rc = RTLdrVerifySignature(hLdrMod, VerifyExeCallback, pState, RTErrInfoInitStatic(pStaticErrInfo)); 1489 if (RT_SUCCESS(rc)) 1490 RTMsgInfo("'%s' is valid now, but not at link time.\n", pszFilename); 1491 } 1492 if (RT_FAILURE(rc)) 1493 RTMsgError("RTLdrVerifySignature failed on '%s': %Rrc - %s\n", pszFilename, rc, pStaticErrInfo->szMsg); 1494 } 1495 else 1496 RTMsgError("RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on '%s': %Rrc\n", pszFilename, rc); 1522 /* Reset the state. */ 1523 pState->cBad = 0; 1524 pState->cOkay = 0; 1525 pState->pszFilename = pszFilename; 1526 1527 rc = RTLdrVerifySignature(hLdrMod, VerifyExeCallback, pState, RTErrInfoInitStatic(pStaticErrInfo)); 1528 if (RT_FAILURE(rc)) 1529 RTMsgError("RTLdrVerifySignature failed on '%s': %Rrc - %s\n", pszFilename, rc, pStaticErrInfo->szMsg); 1497 1530 1498 1531 int rc2 = RTLdrClose(hLdrMod); … … 1502 1535 return rc != VERR_LDRVI_NOT_SIGNED ? RTEXITCODE_FAILURE : RTEXITCODE_SKIPPED; 1503 1536 1504 return RTEXITCODE_SUCCESS;1537 return pState->cOkay > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 1505 1538 } 1506 1539 … … 1531 1564 VERIFYEXESTATE State = 1532 1565 { 1533 NIL_RTCRSTORE, NIL_RTCRSTORE, NIL_RTCRSTORE, false, false, 1534 VERIFYEXESTATE::kSignType_Windows, 0, RTLDRARCH_WHATEVER 1566 NIL_RTCRSTORE, NIL_RTCRSTORE, NIL_RTCRSTORE, false, 0, 1567 VERIFYEXESTATE::kSignType_Windows, RTLDRARCH_WHATEVER, 1568 0, 0, NULL 1535 1569 }; 1536 1570 int rc = RTCrStoreCreateInMem(&State.hRootStore, 0);
Note:
See TracChangeset
for help on using the changeset viewer.