Changeset 84312 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- May 14, 2020 5:46:45 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r84265 r84312 2652 2652 /* 2653 2653 * Parse the signing certificate. Unlike the manifest parser we use below, 2654 * this API ignores par seof the file that aren't relevant.2654 * this API ignores parts of the file that aren't relevant. 2655 2655 */ 2656 2656 RTERRINFOSTATIC StaticErrInfo; … … 2681 2681 pszSplit = (char *)pvSignature + cbSignature; 2682 2682 } 2683 char const chSaved = *pszSplit; 2683 2684 *pszSplit = '\0'; 2684 2685 … … 2758 2759 else 2759 2760 hrc = E_OUTOFMEMORY; 2761 2762 /* 2763 * Look for the additional for PKCS#7/CMS signature we produce when we sign stuff. 2764 */ 2765 if (SUCCEEDED(hrc)) 2766 { 2767 *pszSplit = chSaved; 2768 vrc = RTCrPkcs7_ReadFromBuffer(&m->ContentInfo, pvSignature, cbSignature, RTCRPKCS7_READ_F_PEM_ONLY, 2769 &g_RTAsn1DefaultAllocator, NULL /*pfCmsLabeled*/, 2770 RTErrInfoInitStatic(&StaticErrInfo), pszSubFileNm); 2771 if (RT_SUCCESS(vrc)) 2772 m->fContentInfoLoaded = true; 2773 else if (vrc != VERR_NOT_FOUND) 2774 hrc = setErrorVrc(vrc, tr("Error reading the PKCS#7/CMS signature from '%s' for '%s' (%Rrc): %s"), 2775 pszSubFileNm, pTask->locInfo.strPath.c_str(), vrc, StaticErrInfo.Core.pszMsg); 2776 } 2760 2777 } 2761 2778 else if (vrc == VERR_NOT_FOUND || vrc == VERR_EOF) … … 2784 2801 * Parse and validate the signature file. 2785 2802 * 2786 * The signature file has two parts, manifest part and a PEM encoded 2787 * certificate. The former contains an entry for the manifest file with a 2788 * digest that is encrypted with the certificate in the latter part. 2803 * The signature file nominally has two parts, manifest part and a PEM 2804 * encoded certificate. The former contains an entry for the manifest file 2805 * with a digest that is encrypted with the certificate in the latter part. 2806 * 2807 * When an appliance is signed by VirtualBox, a PKCS#7/CMS signedData part 2808 * is added by default, supplying more info than the bits mandated by the 2809 * OVF specs. We will validate both the signedData and the standard OVF 2810 * signature. Another requirement is that the first signedData signer 2811 * uses the same certificate as the regular OVF signature, allowing us to 2812 * only do path building for the signedData with the additional info it 2813 * ships with. 2789 2814 */ 2790 2815 if (m->pbSignedDigest) … … 2837 2862 2838 2863 /* 2864 * If we have a PKCS#7/CMS signature, validate it and check that the 2865 * certificate matches the first signerInfo entry. 2866 */ 2867 HRESULT hrc2 = i_readTailProcessingSignedData(&StaticErrInfo); 2868 if (FAILED(hrc2) && SUCCEEDED(hrc)) 2869 hrc = hrc2; 2870 2871 /* 2839 2872 * Validate the certificate. 2840 2873 * 2841 * We don't fail here onif we cannot validate the certificate, we postpone2874 * We don't fail here if we cannot validate the certificate, we postpone 2842 2875 * that till the import stage, so that we can allow the user to ignore it. 2843 2876 * … … 2870 2903 Assert(m->fCertificateIsSelfSigned == RTCrX509Certificate_IsSelfSigned(&m->SignerCert)); 2871 2904 2872 HRESULThrc2 = S_OK;2905 hrc2 = S_OK; 2873 2906 if (m->fCertificateIsSelfSigned) 2874 2907 { … … 2904 2937 else 2905 2938 { 2906 try { m->strCertError = Utf8StrFmt(tr("Verification of the self signed certificate failed (%Rrc, %s)"), 2907 vrc, StaticErrInfo.Core.pszMsg); } 2908 catch (...) { AssertFailed(); } 2909 i_addWarning(tr("Verification of the self signed certificate used to sign '%s' failed (%Rrc): %s"), 2910 pTask->locInfo.strPath.c_str(), vrc, StaticErrInfo.Core.pszMsg); 2939 m->strCertError.printfNoThrow(tr("Verification of the self signed certificate failed (%Rrc%#RTeim)"), 2940 vrc, &StaticErrInfo.Core); 2941 i_addWarning(tr("Verification of the self signed certificate used to sign '%s' failed (%Rrc)%RTeim"), 2942 pTask->locInfo.strPath.c_str(), vrc, &StaticErrInfo.Core); 2911 2943 } 2912 2944 } … … 3036 3068 } 3037 3069 3070 ///** @callback_method_impl{FNRTCRPKCS7VERIFYCERTCALLBACK, Dummy.} */ 3071 //static DECLCALLBACK(int) applianceVerifyCertDummyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, 3072 // uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo) 3073 //{ 3074 // RT_NOREF(pCert, hCertPaths, fFlags, pvUser, pErrInfo); 3075 // return VINF_SUCCESS; 3076 //} 3077 3078 /** 3079 * Reads hMemFileTheirManifest into a memory buffer so it can be passed to 3080 * RTCrPkcs7VerifySignedDataWithExternalData. 3081 * 3082 * Use RTMemTmpFree to free the memory. 3083 */ 3084 HRESULT Appliance::i_readTailProcessingGetManifestData(void **ppvData, size_t *pcbData) 3085 { 3086 uint64_t cbData; 3087 int vrc = RTVfsFileQuerySize(m->hMemFileTheirManifest, &cbData); 3088 AssertRCReturn(vrc, setErrorVrc(vrc, "RTVfsFileQuerySize")); 3089 3090 void *pvData = RTMemTmpAllocZ((size_t)cbData); 3091 AssertPtrReturn(pvData, E_OUTOFMEMORY); 3092 3093 vrc = RTVfsFileReadAt(m->hMemFileTheirManifest, 0, pvData, (size_t)cbData, NULL); 3094 AssertRCReturnStmt(vrc, RTMemTmpFree(pvData), setErrorVrc(vrc, "RTVfsFileReadAt")); 3095 3096 *pcbData = (size_t)cbData; 3097 *ppvData = pvData; 3098 return S_OK; 3099 } 3100 3101 /** 3102 * Worker for i_readTailProcessing that validates the signedData. 3103 * 3104 * If we have a PKCS#7/CMS signature: 3105 * - validate it 3106 * - check that the OVF certificate matches the first signerInfo entry 3107 * - verify the signature, but leave the certificate path validation for 3108 * later. 3109 * 3110 * @param pErrInfo Static error info buffer (not for returning, just for 3111 * avoiding wasting stack). 3112 * @returns COM status. 3113 * @throws Nothing! 3114 */ 3115 HRESULT Appliance::i_readTailProcessingSignedData(PRTERRINFOSTATIC pErrInfo) 3116 { 3117 m->fContentInfoValid = false; 3118 m->fContentInfoSameCert = false; 3119 m->fContentInfoValidSignature = false; 3120 3121 if (!m->fContentInfoLoaded) 3122 return S_OK; 3123 3124 /* 3125 * Validate it. 3126 */ 3127 HRESULT hrc = S_OK; 3128 PCRTCRPKCS7SIGNEDDATA pSignedData = m->ContentInfo.u.pSignedData; 3129 if (!RTCrPkcs7ContentInfo_IsSignedData(&m->ContentInfo)) 3130 i_addWarning(tr("Invalid PKCS#7/CMS type: %s, expected %s (signedData)"), 3131 m->ContentInfo.ContentType.szObjId, RTCRPKCS7SIGNEDDATA_OID); 3132 else if (RTAsn1ObjId_CompareWithString(&pSignedData->ContentInfo.ContentType, RTCR_PKCS7_DATA_OID) != 0) 3133 i_addWarning(tr("Invalid PKCS#7/CMS inner type: %s, expected %s (data)"), 3134 pSignedData->ContentInfo.ContentType.szObjId, RTCR_PKCS7_DATA_OID); 3135 else if (RTAsn1OctetString_IsPresent(&pSignedData->ContentInfo.Content)) 3136 i_addWarning(tr("Invalid PKCS#7/CMS data: embedded (%u bytes), expected external"), 3137 pSignedData->ContentInfo.Content.Asn1Core.cb); 3138 else if (pSignedData->SignerInfos.cItems == 0) 3139 i_addWarning(tr("Invalid PKCS#7/CMS: No signers")); 3140 else 3141 { 3142 m->fContentInfoValid = true; 3143 3144 /* 3145 * Same certificate as the OVF signature? 3146 */ 3147 PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignedData->SignerInfos.papItems[0]; 3148 if ( RTCrX509Name_Compare(&pSignerInfo->IssuerAndSerialNumber.Name, &m->SignerCert.TbsCertificate.Issuer) == 0 3149 && RTAsn1Integer_Compare(&pSignerInfo->IssuerAndSerialNumber.SerialNumber, 3150 &m->SignerCert.TbsCertificate.SerialNumber) == 0) 3151 m->fContentInfoSameCert = true; 3152 else 3153 i_addWarning(tr("Invalid PKCS#7/CMS: Using a different certificate")); 3154 3155 /* 3156 * Then perform a validation of the signatures, but first without 3157 * validating the certificate trust paths yet. 3158 */ 3159 RTCRSTORE hTrustedCerts = NIL_RTCRSTORE; 3160 int vrc = RTCrStoreCreateInMem(&hTrustedCerts, 1); 3161 AssertRCReturn(vrc, setErrorVrc(vrc, tr("RTCrStoreCreateInMem failed: %Rrc"), vrc)); 3162 3163 vrc = RTCrStoreCertAddX509(hTrustedCerts, 0, &m->SignerCert, RTErrInfoInitStatic(pErrInfo)); 3164 if (RT_SUCCESS(vrc)) 3165 { 3166 void *pvData = NULL; 3167 size_t cbData = 0; 3168 hrc = i_readTailProcessingGetManifestData(&pvData, &cbData); 3169 if (SUCCEEDED(hrc)) 3170 { 3171 RTTIMESPEC Now; 3172 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, RTCRPKCS7VERIFY_SD_F_TRUST_ALL_CERTS, 3173 NIL_RTCRSTORE /*hAdditionalCerts*/, hTrustedCerts, 3174 RTTimeNow(&Now), NULL /*pfnVerifyCert*/, NULL /*pvUser*/, 3175 pvData, cbData, RTErrInfoInitStatic(pErrInfo)); 3176 if (RT_SUCCESS(vrc)) 3177 m->fContentInfoValidSignature = true; 3178 else 3179 i_addWarning(tr("Failed to validate PKCS#7/CMS signature: %Rrc%RTeim"), vrc, &pErrInfo->Core); 3180 RTMemTmpFree(pvData); 3181 } 3182 } 3183 else 3184 hrc = setErrorVrc(vrc, tr("RTCrStoreCertAddX509 failed: %Rrc%RTeim"), vrc, &pErrInfo->Core); 3185 RTCrStoreRelease(hTrustedCerts); 3186 } 3187 3188 return hrc; 3189 } 3038 3190 3039 3191
Note:
See TracChangeset
for help on using the changeset viewer.