public static void AddCrlForCertificate( X509Certificate2 cert, SafeX509StoreHandle store, X509RevocationMode revocationMode, DateTime verificationTime, ref TimeSpan remainingDownloadTime) { // In Offline mode, accept any cached CRL we have. // "CRL is Expired" is a better match for Offline than "Could not find CRL" if (revocationMode != X509RevocationMode.Online) { verificationTime = DateTime.MinValue; } if (AddCachedCrl(cert, store, verificationTime)) { return; } // Don't do any work if we're over limit or prohibited from fetching new CRLs if (remainingDownloadTime <= TimeSpan.Zero || revocationMode != X509RevocationMode.Online) { return; } DownloadAndAddCrl(cert, store, ref remainingDownloadTime); }
private static bool AddCachedCrl(X509Certificate2 cert, SafeX509StoreHandle store, DateTime verificationTime) { string crlFile = GetCachedCrlPath(cert); using (SafeBioHandle bio = Interop.libcrypto.BIO_new_file(crlFile, "rb")) { if (bio.IsInvalid) { return false; } // X509_STORE_add_crl will increase the refcount on the CRL object, so we should still // dispose our copy. using (SafeX509CrlHandle crl = Interop.libcrypto.PEM_read_bio_X509_CRL(bio)) { if (crl.IsInvalid) { return false; } // If crl.LastUpdate is in the past, downloading a new version isn't really going // to help, since we can't rewind the Internet. So this is just going to fail, but // at least it can fail without using the network. // // If crl.NextUpdate is in the past, try downloading a newer version. DateTime nextUpdate = OpenSslX509CertificateReader.ExtractValidityDateTime( Interop.Crypto.GetX509CrlNextUpdate(crl)); // OpenSSL is going to convert our input time to universal, so we should be in Local or // Unspecified (local-assumed). Debug.Assert( verificationTime.Kind != DateTimeKind.Utc, "UTC verificationTime should have been normalized to Local"); // In the event that we're to-the-second accurate on the match, OpenSSL will consider this // to be already expired. if (nextUpdate <= verificationTime) { return false; } // TODO (#3063): Check the return value of X509_STORE_add_crl, and throw on any error other // than X509_R_CERT_ALREADY_IN_HASH_TABLE Interop.libcrypto.X509_STORE_add_crl(store, crl); return true; } } }
private static void DownloadAndAddCrl( X509Certificate2 cert, SafeX509StoreHandle store, ref TimeSpan remainingDownloadTime) { string url = GetCdpUrl(cert); if (url == null) { return; } // X509_STORE_add_crl will increase the refcount on the CRL object, so we should still // dispose our copy. using (SafeX509CrlHandle crl = CertificateAssetDownloader.DownloadCrl(url, ref remainingDownloadTime)) { // null is a valid return (e.g. no remainingDownloadTime) if (crl != null && !crl.IsInvalid) { // TODO (#3063): Check the return value of X509_STORE_add_crl, and throw on any error other // than X509_R_CERT_ALREADY_IN_HASH_TABLE Interop.libcrypto.X509_STORE_add_crl(store, crl); // Saving the CRL to the disk is just a performance optimization for later requests to not // need to use the network again, so failure to save shouldn't throw an exception or mark // the chain as invalid. try { string crlFile = GetCachedCrlPath(cert, mkDir: true); using (SafeBioHandle bio = Interop.libcrypto.BIO_new_file(crlFile, "wb")) { if (!bio.IsInvalid) { Interop.libcrypto.PEM_write_bio_X509_CRL(bio, crl); } } } catch (IOException) { } } } }
internal static extern bool X509StoreAddCert(SafeX509StoreHandle ctx, SafeX509Handle x);
internal static extern bool X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509RevocationFlag revocationFlag);
internal static extern bool X509StoreCtxInit(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509);
internal static extern bool X509StoreAddCrl(SafeX509StoreHandle ctx, SafeX509CrlHandle x);
internal static extern bool X509_STORE_CTX_init(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509, IntPtr zero);
internal static extern bool X509_STORE_add_cert(SafeX509StoreHandle ctx, SafeX509Handle x);
internal static extern bool X509_STORE_set_flags(SafeX509StoreHandle ctx, X509VerifyFlags flags);
internal static extern bool X509_STORE_add_crl(SafeX509StoreHandle ctx, SafeX509CrlHandle x);