- Timestamp:
- May 18, 2020 5:37:30 PM (5 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ApplianceImpl.h
r84312 r84340 172 172 HRESULT i_readSignatureFile(TaskOVF *pTask, RTVFSIOSTREAM hIosCert, const char *pszSubFileNm); 173 173 HRESULT i_readTailProcessing(TaskOVF *pTask); 174 HRESULT i_readTailProcessingGetManifestData(void **ppvData, size_t *pcbData); 174 175 HRESULT i_readTailProcessingSignedData(PRTERRINFOSTATIC pErrInfo); 175 HRESULT i_readTailProcessingGetManifestData(void **ppvData, size_t *pcbData); 176 HRESULT i_readTailProcessingVerifySelfSignedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedCerts, PRTERRINFOSTATIC pErrInfo); 177 HRESULT i_readTailProcessingVerifyIssuedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo); 178 HRESULT i_readTailProcessingVerifyContentInfoCerts(void const *pvData, size_t cbData, 179 RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo); 180 HRESULT i_readTailProcessingVerifyAnalyzeSignerInfo(void const *pvData, size_t cbData, RTCRSTORE hTrustedStore, 181 uint32_t iSigner, PRTTIMESPEC pNow, int vrc, 182 PRTERRINFOSTATIC pErrInfo, PRTCRSTORE phTrustedStore2); 183 HRESULT i_readTailProcessingVerifyContentInfoFailOne(const char *pszSignature, int vrc, PRTERRINFOSTATIC pErrInfo); 184 176 185 HRESULT i_gettingCloudData(TaskCloud *pTask); 177 178 186 /** @} */ 179 187 -
trunk/src/VBox/Main/include/ApplianceImplPrivate.h
r84312 r84340 90 90 , enmSignedDigestType(RTDIGESTTYPE_INVALID) 91 91 , fContentInfoLoaded(false) 92 , fContentInfo Valid(false)92 , fContentInfoOkay(false) 93 93 , fContentInfoSameCert(false) 94 94 , fContentInfoValidSignature(false) … … 231 231 /** Set if the ContentInfo member contains usable data. */ 232 232 bool fContentInfoLoaded; 233 /** Set if the ContentInfo member validated okay (says nothing about the234 * signature or certificates within it). */235 bool fContentInfo Valid;236 /** Set if the ContentInfo member is using the SignerCert too. */233 /** Set by read() if the ContentInfo member checked out okay (says nothing about 234 * the signature or certificates within it). */ 235 bool fContentInfoOkay; 236 /** Set by read() if the ContentInfo member is using the SignerCert too. */ 237 237 bool fContentInfoSameCert; 238 /** Set if the ContentInfo member contains a valid signature (not saying239 * anything about valid signing certificates). */238 /** Set by read() if the ContentInfo member contains valid signatures (not 239 * saying anything about valid signing certificates). */ 240 240 bool fContentInfoValidSignature; 241 /** Set by read() if we've already verified the signed data signature(s). */ 242 bool fContentInfoDoneVerification; 243 244 bool fContentInfoVerifiedOkay; 241 245 /** @} */ 242 246 -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r84312 r84340 2903 2903 Assert(m->fCertificateIsSelfSigned == RTCrX509Certificate_IsSelfSigned(&m->SignerCert)); 2904 2904 2905 /* We'll always needs the trusted cert store. */ 2905 2906 hrc2 = S_OK; 2906 if (m->fCertificateIsSelfSigned) 2907 { 2908 /* 2909 * It's a self signed certificate. We assume the frontend will 2910 * present this fact to the user and give a choice whether this 2911 * is acceptible. But, first make sure it makes internal sense. 2912 */ 2913 m->fCertificateMissingPath = true; /** @todo need to check if the certificate is trusted by the system! */ 2914 vrc = RTCrX509Certificate_VerifySignatureSelfSigned(&m->SignerCert, RTErrInfoInitStatic(&StaticErrInfo)); 2915 if (RT_SUCCESS(vrc)) 2916 { 2917 m->fCertificateValid = true; 2918 2919 /* Check whether the certificate is currently valid, just warn if not. */ 2920 RTTIMESPEC Now; 2921 if (RTCrX509Validity_IsValidAtTimeSpec(&m->SignerCert.TbsCertificate.Validity, RTTimeNow(&Now))) 2907 RTCRSTORE hTrustedCerts; 2908 vrc = RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(&hTrustedCerts, RTErrInfoInitStatic(&StaticErrInfo)); 2909 if (RT_SUCCESS(vrc)) 2910 { 2911 /* If we don't have a PKCS7/CMS signature or if it uses a different 2912 certificate, we try our best to validate the OVF certificate. */ 2913 if (!m->fContentInfoOkay || !m->fContentInfoSameCert) 2914 { 2915 if (m->fCertificateIsSelfSigned) 2916 hrc2 = i_readTailProcessingVerifySelfSignedOvfCert(pTask, hTrustedCerts, &StaticErrInfo); 2917 else 2918 hrc2 = i_readTailProcessingVerifyIssuedOvfCert(pTask, hTrustedCerts, &StaticErrInfo); 2919 } 2920 2921 /* If there is a PKCS7/CMS signature, we always verify its certificates. */ 2922 if (m->fContentInfoOkay) 2923 { 2924 void *pvData = NULL; 2925 size_t cbData = 0; 2926 HRESULT hrc3 = i_readTailProcessingGetManifestData(&pvData, &cbData); 2927 if (SUCCEEDED(hrc3)) 2922 2928 { 2923 m->fCertificateValidTime = true;2924 i_addWarning(tr("A self signed certificate was used to sign '%s'"), pTask->locInfo.strPath.c_str());2929 hrc3 = i_readTailProcessingVerifyContentInfoCerts(pvData, cbData, hTrustedCerts, &StaticErrInfo); 2930 RTMemTmpFree(pvData); 2925 2931 } 2926 else 2927 i_addWarning(tr("Self signed certificate used to sign '%s' is not currently valid"), 2928 pTask->locInfo.strPath.c_str()); 2929 2930 /* Just warn if it's not a CA. Self-signed certificates are 2931 hardly trustworthy to start with without the user's consent. */ 2932 if ( !m->SignerCert.TbsCertificate.T3.pBasicConstraints 2933 || !m->SignerCert.TbsCertificate.T3.pBasicConstraints->CA.fValue) 2934 i_addWarning(tr("Self signed certificate used to sign '%s' is not marked as certificate authority (CA)"), 2935 pTask->locInfo.strPath.c_str()); 2936 } 2937 else 2938 { 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); 2943 } 2932 if (FAILED(hrc3) && SUCCEEDED(hrc2)) 2933 hrc2 = hrc3; 2934 } 2935 RTCrStoreRelease(hTrustedCerts); 2944 2936 } 2945 2937 else 2946 { 2947 /* 2948 * The certificate is not self-signed. Use the system certificate 2949 * stores to try build a path that validates successfully. 2950 */ 2951 RTCRX509CERTPATHS hCertPaths; 2952 vrc = RTCrX509CertPathsCreate(&hCertPaths, &m->SignerCert); 2953 if (RT_SUCCESS(vrc)) 2954 { 2955 /* Get trusted certificates from the system and add them to the path finding mission. */ 2956 RTCRSTORE hTrustedCerts; 2957 vrc = RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(&hTrustedCerts, 2958 RTErrInfoInitStatic(&StaticErrInfo)); 2959 if (RT_SUCCESS(vrc)) 2960 { 2961 vrc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts); 2962 if (RT_FAILURE(vrc)) 2963 hrc2 = setErrorBoth(E_FAIL, vrc, tr("RTCrX509CertPathsSetTrustedStore failed (%Rrc)"), vrc); 2964 RTCrStoreRelease(hTrustedCerts); 2965 } 2966 else 2967 hrc2 = setErrorBoth(E_FAIL, vrc, 2968 tr("Failed to query trusted CAs and Certificates from the system and for the current user (%Rrc, %s)"), 2969 vrc, StaticErrInfo.Core.pszMsg); 2970 2971 /* Add untrusted intermediate certificates. */ 2972 if (RT_SUCCESS(vrc)) 2973 { 2974 /// @todo RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts); 2975 /// By scanning for additional certificates in the .cert file? It would be 2976 /// convenient to be able to supply intermediate certificates for the user, 2977 /// right? Or would that be unacceptable as it may weaken security? 2978 /// 2979 /// Anyway, we should look for intermediate certificates on the system, at 2980 /// least. 2981 } 2982 if (RT_SUCCESS(vrc)) 2983 { 2984 /* 2985 * Do the building and verification of certificate paths. 2986 */ 2987 vrc = RTCrX509CertPathsBuild(hCertPaths, RTErrInfoInitStatic(&StaticErrInfo)); 2988 if (RT_SUCCESS(vrc)) 2989 { 2990 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(&StaticErrInfo)); 2991 if (RT_SUCCESS(vrc)) 2992 { 2993 /* 2994 * Mark the certificate as good. 2995 */ 2996 /** @todo check the certificate purpose? If so, share with self-signed. */ 2997 m->fCertificateValid = true; 2998 m->fCertificateMissingPath = false; 2999 3000 /* 3001 * We add a warning if the certificate path isn't valid at the current 3002 * time. Since the time is only considered during path validation and we 3003 * can repeat the validation process (but not building), it's easy to check. 3004 */ 3005 RTTIMESPEC Now; 3006 vrc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, RTTimeNow(&Now)); 3007 if (RT_SUCCESS(vrc)) 3008 { 3009 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(&StaticErrInfo)); 3010 if (RT_SUCCESS(vrc)) 3011 m->fCertificateValidTime = true; 3012 else 3013 i_addWarning(tr("The certificate used to sign '%s' (or a certificate in the path) is not currently valid (%Rrc)"), 3014 pTask->locInfo.strPath.c_str(), vrc); 3015 } 3016 else 3017 hrc2 = setErrorVrc(vrc, "RTCrX509CertPathsSetValidTimeSpec failed: %Rrc", vrc); 3018 } 3019 else if (vrc == VERR_CR_X509_CPV_NO_TRUSTED_PATHS) 3020 { 3021 m->fCertificateValid = true; 3022 i_addWarning(tr("No trusted certificate paths")); 3023 3024 /* Add another warning if the pathless certificate is not valid at present. */ 3025 RTTIMESPEC Now; 3026 if (RTCrX509Validity_IsValidAtTimeSpec(&m->SignerCert.TbsCertificate.Validity, RTTimeNow(&Now))) 3027 m->fCertificateValidTime = true; 3028 else 3029 i_addWarning(tr("The certificate used to sign '%s' is not currently valid"), 3030 pTask->locInfo.strPath.c_str()); 3031 } 3032 else 3033 hrc2 = setErrorBoth(E_FAIL, vrc, tr("Certificate path validation failed (%Rrc, %s)"), 3034 vrc, StaticErrInfo.Core.pszMsg); 3035 } 3036 else 3037 hrc2 = setErrorBoth(E_FAIL, vrc, tr("Certificate path building failed (%Rrc, %s)"), 3038 vrc, StaticErrInfo.Core.pszMsg); 3039 } 3040 RTCrX509CertPathsRelease(hCertPaths); 3041 } 3042 else 3043 hrc2 = setErrorVrc(vrc, tr("RTCrX509CertPathsCreate failed: %Rrc"), vrc); 3044 } 2938 hrc2 = setErrorBoth(E_FAIL, vrc, 2939 tr("Failed to query trusted CAs and Certificates from the system and for the current user (%Rrc%RTeim)"), 2940 vrc, &StaticErrInfo.Core); 3045 2941 3046 2942 /* Merge statuses from signature and certificate validation, prefering the signature one. */ … … 3054 2950 if (m->fSignerCertLoaded) 3055 2951 { 2952 /** @todo PKCS7/CMS certs too */ 3056 2953 m->ptrCertificateInfo.createObject(); 3057 2954 m->ptrCertificateInfo->initCertificate(&m->SignerCert, … … 3067 2964 return S_OK; 3068 2965 } 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 2966 3078 2967 /** … … 3115 3004 HRESULT Appliance::i_readTailProcessingSignedData(PRTERRINFOSTATIC pErrInfo) 3116 3005 { 3117 m->fContentInfo Valid= false;3006 m->fContentInfoOkay = false; 3118 3007 m->fContentInfoSameCert = false; 3119 3008 m->fContentInfoValidSignature = false; … … 3140 3029 else 3141 3030 { 3142 m->fContentInfo Valid= true;3031 m->fContentInfoOkay = true; 3143 3032 3144 3033 /* … … 3188 3077 return hrc; 3189 3078 } 3079 3080 3081 /** 3082 * Worker for i_readTailProcessing that verifies a self signed certificate when 3083 * no PKCS\#7/CMS signature using the same certificate is present. 3084 */ 3085 HRESULT Appliance::i_readTailProcessingVerifySelfSignedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo) 3086 { 3087 /* 3088 * It's a self signed certificate. We assume the frontend will 3089 * present this fact to the user and give a choice whether this 3090 * is acceptable. But, first make sure it makes internal sense. 3091 */ 3092 m->fCertificateMissingPath = true; 3093 PCRTCRCERTCTX pCertCtx = RTCrStoreCertByIssuerAndSerialNo(hTrustedStore, &m->SignerCert.TbsCertificate.Issuer, 3094 &m->SignerCert.TbsCertificate.SerialNumber); 3095 if (pCertCtx) 3096 { 3097 if (pCertCtx->pCert && RTCrX509Certificate_Compare(pCertCtx->pCert, &m->SignerCert) == 0) 3098 m->fCertificateMissingPath = true; 3099 RTCrCertCtxRelease(pCertCtx); 3100 } 3101 3102 int vrc = RTCrX509Certificate_VerifySignatureSelfSigned(&m->SignerCert, RTErrInfoInitStatic(pErrInfo)); 3103 if (RT_SUCCESS(vrc)) 3104 { 3105 m->fCertificateValid = true; 3106 3107 /* Check whether the certificate is currently valid, just warn if not. */ 3108 RTTIMESPEC Now; 3109 m->fCertificateValidTime = RTCrX509Validity_IsValidAtTimeSpec(&m->SignerCert.TbsCertificate.Validity, RTTimeNow(&Now)); 3110 if (m->fCertificateValidTime) 3111 { 3112 m->fCertificateValidTime = true; 3113 i_addWarning(tr("A self signed certificate was used to sign '%s'"), pTask->locInfo.strPath.c_str()); 3114 } 3115 else 3116 i_addWarning(tr("Self signed certificate used to sign '%s' is not currently valid"), 3117 pTask->locInfo.strPath.c_str()); 3118 } 3119 else 3120 { 3121 m->strCertError.printfNoThrow(tr("Verification of the self signed certificate failed (%Rrc%#RTeim)"), 3122 vrc, &pErrInfo->Core); 3123 i_addWarning(tr("Verification of the self signed certificate used to sign '%s' failed (%Rrc)%RTeim"), 3124 pTask->locInfo.strPath.c_str(), vrc, &pErrInfo->Core); 3125 } 3126 3127 /* Just warn if it's not a CA. Self-signed certificates are 3128 hardly trustworthy to start with without the user's consent. */ 3129 if ( !m->SignerCert.TbsCertificate.T3.pBasicConstraints 3130 || !m->SignerCert.TbsCertificate.T3.pBasicConstraints->CA.fValue) 3131 i_addWarning(tr("Self signed certificate used to sign '%s' is not marked as certificate authority (CA)"), 3132 pTask->locInfo.strPath.c_str()); 3133 3134 return S_OK; 3135 } 3136 3137 /** 3138 * Worker for i_readTailProcessing that verfies a non-self-issued OVF 3139 * certificate when no PKCS\#7/CMS signature using the same certificate is 3140 * present. 3141 */ 3142 HRESULT Appliance::i_readTailProcessingVerifyIssuedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo) 3143 { 3144 /* 3145 * The certificate is not self-signed. Use the system certificate 3146 * stores to try build a path that validates successfully. 3147 */ 3148 HRESULT hrc = S_OK; 3149 RTCRX509CERTPATHS hCertPaths; 3150 int vrc = RTCrX509CertPathsCreate(&hCertPaths, &m->SignerCert); 3151 if (RT_SUCCESS(vrc)) 3152 { 3153 /* Get trusted certificates from the system and add them to the path finding mission. */ 3154 vrc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedStore); 3155 if (RT_FAILURE(vrc)) 3156 hrc = setErrorBoth(E_FAIL, vrc, tr("RTCrX509CertPathsSetTrustedStore failed (%Rrc)"), vrc); 3157 3158 /* Add untrusted intermediate certificates. */ 3159 if (RT_SUCCESS(vrc)) 3160 { 3161 /// @todo RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts); 3162 /// We should look for intermediate certificates on the system, at least. 3163 } 3164 if (RT_SUCCESS(vrc)) 3165 { 3166 /* 3167 * Do the building and verification of certificate paths. 3168 */ 3169 vrc = RTCrX509CertPathsBuild(hCertPaths, RTErrInfoInitStatic(pErrInfo)); 3170 if (RT_SUCCESS(vrc)) 3171 { 3172 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(pErrInfo)); 3173 if (RT_SUCCESS(vrc)) 3174 { 3175 /* 3176 * Mark the certificate as good. 3177 */ 3178 /** @todo check the certificate purpose? If so, share with self-signed. */ 3179 m->fCertificateValid = true; 3180 m->fCertificateMissingPath = false; 3181 3182 /* 3183 * We add a warning if the certificate path isn't valid at the current 3184 * time. Since the time is only considered during path validation and we 3185 * can repeat the validation process (but not building), it's easy to check. 3186 */ 3187 RTTIMESPEC Now; 3188 vrc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, RTTimeNow(&Now)); 3189 if (RT_SUCCESS(vrc)) 3190 { 3191 vrc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, RTErrInfoInitStatic(pErrInfo)); 3192 if (RT_SUCCESS(vrc)) 3193 m->fCertificateValidTime = true; 3194 else 3195 i_addWarning(tr("The certificate used to sign '%s' (or a certificate in the path) is not currently valid (%Rrc)"), 3196 pTask->locInfo.strPath.c_str(), vrc); 3197 } 3198 else 3199 hrc = setErrorVrc(vrc, "RTCrX509CertPathsSetValidTimeSpec failed: %Rrc", vrc); 3200 } 3201 else if (vrc == VERR_CR_X509_CPV_NO_TRUSTED_PATHS) 3202 { 3203 m->fCertificateValid = true; 3204 i_addWarning(tr("No trusted certificate paths")); 3205 3206 /* Add another warning if the pathless certificate is not valid at present. */ 3207 RTTIMESPEC Now; 3208 if (RTCrX509Validity_IsValidAtTimeSpec(&m->SignerCert.TbsCertificate.Validity, RTTimeNow(&Now))) 3209 m->fCertificateValidTime = true; 3210 else 3211 i_addWarning(tr("The certificate used to sign '%s' is not currently valid"), 3212 pTask->locInfo.strPath.c_str()); 3213 } 3214 else 3215 hrc = setErrorBoth(E_FAIL, vrc, tr("Certificate path validation failed (%Rrc%RTeim)"), vrc, &pErrInfo->Core); 3216 } 3217 else 3218 hrc = setErrorBoth(E_FAIL, vrc, tr("Certificate path building failed (%Rrc%RTeim)"), vrc, &pErrInfo->Core); 3219 } 3220 RTCrX509CertPathsRelease(hCertPaths); 3221 } 3222 else 3223 hrc = setErrorVrc(vrc, tr("RTCrX509CertPathsCreate failed: %Rrc"), vrc); 3224 return hrc; 3225 } 3226 3227 /** 3228 * Helper for i_readTailProcessingVerifySignerInfo that reports a verfication 3229 * failure. 3230 * 3231 * @returns S_OK 3232 */ 3233 HRESULT Appliance::i_readTailProcessingVerifyContentInfoFailOne(const char *pszSignature, int vrc, PRTERRINFOSTATIC pErrInfo) 3234 { 3235 i_addWarning(tr("%s verification failed: %Rrc%RTeim"), pszSignature, vrc, &pErrInfo->Core); 3236 if (m->strCertError.isEmpty()) 3237 m->strCertError.printfNoThrow(tr("%s verification failed: %Rrc%RTeim"), pszSignature, vrc, &pErrInfo->Core); 3238 return S_OK; 3239 } 3240 3241 /** 3242 * Worker for i_readTailProcessingVerifyContentInfoCerts that analyzes why the 3243 * standard verification of a signer info entry failed (@a vrc & @a pErrInfo). 3244 * 3245 * There are a couple of things we might want try to investigate deeper here: 3246 * 1. Untrusted signing certificate, often self-signed. 3247 * 2. Untrusted timstamp signing certificate. 3248 * 3. Certificate not valid at the current time and there isn't a 3249 * timestamp counter signature. 3250 * 3251 * That said, it is difficult to get an accurate fix and report on the 3252 * issues here since there are a number of error sources, so just try identify 3253 * the more typical cases. 3254 * 3255 * @note Caller cleans up *phTrustedStore2 if not NIL. 3256 */ 3257 HRESULT Appliance::i_readTailProcessingVerifyAnalyzeSignerInfo(void const *pvData, size_t cbData, RTCRSTORE hTrustedStore, 3258 uint32_t iSigner, PRTTIMESPEC pNow, int vrc, 3259 PRTERRINFOSTATIC pErrInfo, PRTCRSTORE phTrustedStore2) 3260 { 3261 PRTCRPKCS7SIGNEDDATA const pSignedData = m->ContentInfo.u.pSignedData; 3262 PRTCRPKCS7SIGNERINFO const pSigner = pSignedData->SignerInfos.papItems[iSigner]; 3263 3264 /* 3265 * Error/warning message prefix: 3266 */ 3267 const char *pszSignature; 3268 if (iSigner == 0 && m->fContentInfoSameCert) 3269 pszSignature = tr("OVF & PKCS#7/CMS signature"); 3270 else 3271 pszSignature = tr("PKCS#7/CMS signature"); 3272 char szSignatureBuf[64]; 3273 if (pSignedData->SignerInfos.cItems > 1) 3274 { 3275 RTStrPrintf(szSignatureBuf, sizeof(szSignatureBuf), tr("%s #%u"), pszSignature, iSigner + 1); 3276 pszSignature = szSignatureBuf; 3277 } 3278 3279 /* 3280 * Don't try handle weird stuff: 3281 */ 3282 /** @todo Are there more statuses we can deal with here? */ 3283 if ( vrc != VERR_CR_X509_CPV_NOT_VALID_AT_TIME 3284 && vrc != VERR_CR_X509_NO_TRUST_ANCHOR) 3285 return i_readTailProcessingVerifyContentInfoFailOne(pszSignature, vrc, pErrInfo); 3286 3287 /* 3288 * Find the signing certificate. 3289 * We require the certificate to be included in the signed data here. 3290 */ 3291 PCRTCRX509CERTIFICATE pSigningCert; 3292 pSigningCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates, 3293 &pSigner->IssuerAndSerialNumber.Name, 3294 &pSigner->IssuerAndSerialNumber.SerialNumber); 3295 if (!pSigningCert) 3296 { 3297 i_addWarning(tr("PKCS#7/CMS signature #%u does not include the signing certificate"), iSigner + 1); 3298 if (m->strCertError.isEmpty()) 3299 m->strCertError.printfNoThrow(tr("PKCS#7/CMS signature #%u does not include the signing certificate"), iSigner + 1); 3300 return S_OK; 3301 } 3302 3303 PCRTCRCERTCTX const pCertCtxTrusted = RTCrStoreCertByIssuerAndSerialNo(hTrustedStore, &pSigner->IssuerAndSerialNumber.Name, 3304 &pSigner->IssuerAndSerialNumber.SerialNumber); 3305 bool const fSelfSigned = RTCrX509Certificate_IsSelfSigned(pSigningCert); 3306 3307 /* 3308 * Add warning about untrusted self-signed certificate: 3309 */ 3310 if (fSelfSigned && !pCertCtxTrusted) 3311 i_addWarning(tr("%s: Untrusted self-signed certificate"), pszSignature); 3312 3313 /* 3314 * Start by eliminating signing time issues (2 + 3) first as primary problem. 3315 * Keep the error info and status for later failures. 3316 */ 3317 char szTime[RTTIME_STR_LEN]; 3318 RTTIMESPEC Now2 = *pNow; 3319 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED 3320 | RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME 3321 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), NIL_RTCRSTORE, 3322 hTrustedStore, &Now2, NULL, NULL, 3323 pvData, cbData, RTErrInfoInitStatic(pErrInfo)); 3324 if (RT_SUCCESS(vrc)) 3325 { 3326 /* Okay, is it an untrusted time signing certificate or just signing time in general? */ 3327 RTTIMESPEC Now3 = *pNow; 3328 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED 3329 | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 3330 | RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME 3331 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), NIL_RTCRSTORE, 3332 hTrustedStore, &Now3, NULL, NULL, pvData, cbData, NULL); 3333 if (RT_SUCCESS(vrc)) 3334 i_addWarning(tr("%s: Untrusted timestamp (%s)"), pszSignature, RTTimeSpecToString(&Now3, szTime, sizeof(szTime))); 3335 else 3336 i_addWarning(tr("%s: Not valid at current time, but validates fine for untrusted signing time (%s)"), 3337 pszSignature, RTTimeSpecToString(&Now2, szTime, sizeof(szTime))); 3338 return S_OK; 3339 } 3340 3341 /* If we've got a trusted signing certificate (unlikely, but whatever), we can stop already. 3342 If we haven't got a self-signed certificate, stop too as messaging becomes complicated otherwise. */ 3343 if (pCertCtxTrusted || !fSelfSigned) 3344 return i_readTailProcessingVerifyContentInfoFailOne(pszSignature, vrc, pErrInfo); 3345 3346 int const vrcErrInfo = vrc; 3347 3348 /* 3349 * Create a new trust store that includes the signing certificate 3350 * to see what that changes. 3351 */ 3352 vrc = RTCrStoreCreateInMemEx(phTrustedStore2, 1, hTrustedStore); 3353 AssertRCReturn(vrc, setErrorVrc(vrc, "RTCrStoreCreateInMemEx")); 3354 vrc = RTCrStoreCertAddX509(*phTrustedStore2, 0, (PRTCRX509CERTIFICATE)pSigningCert, NULL); 3355 AssertRCReturn(vrc, setErrorVrc(vrc, "RTCrStoreCertAddX509/%u", iSigner)); 3356 3357 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, 3358 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 3359 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), NIL_RTCRSTORE, 3360 *phTrustedStore2, pNow, NULL, NULL, pvData, cbData, NULL); 3361 if (RT_SUCCESS(vrc)) 3362 { 3363 if (!fSelfSigned) 3364 i_readTailProcessingVerifyContentInfoFailOne(pszSignature, vrcErrInfo, pErrInfo); 3365 return S_OK; 3366 } 3367 3368 /* 3369 * Time problems too? Repeat what we did above, but with the modified trust store. 3370 */ 3371 Now2 = *pNow; 3372 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED 3373 | RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME 3374 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), NIL_RTCRSTORE, 3375 *phTrustedStore2, pNow, NULL, NULL, pvData, cbData, NULL); 3376 if (RT_SUCCESS(vrc)) 3377 { 3378 /* Okay, is it an untrusted time signing certificate or just signing time in general? */ 3379 RTTIMESPEC Now3 = *pNow; 3380 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED 3381 | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 3382 | RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME 3383 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), NIL_RTCRSTORE, 3384 *phTrustedStore2, &Now3, NULL, NULL, pvData, cbData, NULL); 3385 if (RT_SUCCESS(vrc)) 3386 i_addWarning(tr("%s: Untrusted timestamp (%s)"), pszSignature, RTTimeSpecToString(&Now3, szTime, sizeof(szTime))); 3387 else 3388 i_addWarning(tr("%s: Not valid at current time, but validates fine for untrusted signing time (%s)"), 3389 pszSignature, RTTimeSpecToString(&Now2, szTime, sizeof(szTime))); 3390 } 3391 else 3392 i_readTailProcessingVerifyContentInfoFailOne(pszSignature, vrcErrInfo, pErrInfo); 3393 3394 return S_OK; 3395 } 3396 3397 /** 3398 * Verify the signing certificates used to sign the PKCS\#7/CMS signature. 3399 * 3400 * ASSUMES that we've previously verified the PKCS\#7/CMS stuff in 3401 * trust-all-certs-without-question mode and it's just the certificate 3402 * validation that can fail now. 3403 */ 3404 HRESULT Appliance::i_readTailProcessingVerifyContentInfoCerts(void const *pvData, size_t cbData, 3405 RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo) 3406 { 3407 /* 3408 * Just do a run and see what happens (note we've already verified 3409 * the data signatures, which just leaves certificates and paths). 3410 */ 3411 RTTIMESPEC Now; 3412 int vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, 3413 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY, 3414 NIL_RTCRSTORE /*hAdditionalCerts*/, hTrustedStore, 3415 RTTimeNow(&Now), NULL /*pfnVerifyCert*/, NULL /*pvUser*/, 3416 pvData, cbData, RTErrInfoInitStatic(pErrInfo)); 3417 if (RT_SUCCESS(vrc)) 3418 m->fContentInfoVerifiedOkay = true; 3419 else 3420 { 3421 /* 3422 * Deal with each of the signatures separately to try figure out 3423 * more exactly what's going wrong. 3424 */ 3425 uint32_t cVerifiedOkay = 0; 3426 PRTCRPKCS7SIGNEDDATA pSignedData = m->ContentInfo.u.pSignedData; 3427 for (uint32_t iSigner = 0; iSigner < pSignedData->SignerInfos.cItems; iSigner++) 3428 { 3429 vrc = RTCrPkcs7VerifySignedDataWithExternalData(&m->ContentInfo, 3430 RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY 3431 | RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(iSigner), 3432 NIL_RTCRSTORE /*hAdditionalCerts*/, hTrustedStore, 3433 &Now, NULL /*pfnVerifyCert*/, NULL /*pvUser*/, 3434 pvData, cbData, RTErrInfoInitStatic(pErrInfo)); 3435 if (RT_SUCCESS(vrc)) 3436 cVerifiedOkay++; 3437 else 3438 { 3439 RTCRSTORE hTrustedStore2 = NIL_RTCRSTORE; 3440 HRESULT hrc = i_readTailProcessingVerifyAnalyzeSignerInfo(pvData, cbData, hTrustedStore, iSigner, &Now, 3441 vrc, pErrInfo, &hTrustedStore2); 3442 RTCrStoreRelease(hTrustedStore2); 3443 if (FAILED(hrc)) 3444 return hrc; 3445 } 3446 } 3447 3448 if ( pSignedData->SignerInfos.cItems > 1 3449 && pSignedData->SignerInfos.cItems != cVerifiedOkay) 3450 i_addWarning(tr("%u out of %u PKCS#7/CMS signatures verfified okay"), 3451 cVerifiedOkay, pSignedData->SignerInfos.cItems); 3452 } 3453 3454 return S_OK; 3455 } 3456 3190 3457 3191 3458
Note:
See TracChangeset
for help on using the changeset viewer.