/// <summary> /// can be used to check if the certificate is available in a specific File for CRL. /// </summary> /// <param name="cert"></param> /// <param name="CRLFilePath"></param> /// <returns></returns> internal bool IsCertificateInCrlFile(X509Certificate2 cert, string CRLFilePath) { CRLData = File.ReadAllBytes(CRLFilePath); if (!CheckCRLMessageSignature(CRLData)) { return(false); } IntPtr phCertStore = IntPtr.Zero; IntPtr pvContext = IntPtr.Zero; GCHandle hCrlData = new GCHandle(); GCHandle hCryptBlob = new GCHandle(); try { hCrlData = GCHandle.Alloc(CRLData, GCHandleType.Pinned); WinCrypt32.CRYPTOAPI_BLOB stCryptBlob; stCryptBlob.cbData = CRLData.Length; stCryptBlob.pbData = hCrlData.AddrOfPinnedObject(); hCryptBlob = GCHandle.Alloc(stCryptBlob, GCHandleType.Pinned); if (!WinCrypt32.CryptQueryObject( WinCrypt32.CERT_QUERY_OBJECT_BLOB, hCryptBlob.AddrOfPinnedObject(), WinCrypt32.CERT_QUERY_CONTENT_FLAG_CRL, WinCrypt32.CERT_QUERY_FORMAT_FLAG_BINARY, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref phCertStore, IntPtr.Zero, ref pvContext )) { throw new Win32Exception(Marshal.GetLastWin32Error()); } WinCrypt32.CRL_CONTEXT stCrlContext = (WinCrypt32.CRL_CONTEXT)Marshal.PtrToStructure(pvContext, typeof(WinCrypt32.CRL_CONTEXT)); WinCrypt32.CRL_INFO stCrlInfo = (WinCrypt32.CRL_INFO)Marshal.PtrToStructure(stCrlContext.pCrlInfo, typeof(WinCrypt32.CRL_INFO)); CRLNextUpdate = WinCrypt32.FiletimeToDateTime(stCrlInfo.NextUpdate); if (CRLNextUpdate < DateTime.Now) { throw new CRLExpection("CRL has expired"); } if (IsCertificateInCrl(cert, stCrlInfo)) { return(true); } } finally { if (hCrlData.IsAllocated) { hCrlData.Free(); } if (hCryptBlob.IsAllocated) { hCryptBlob.Free(); } if (!pvContext.Equals(IntPtr.Zero)) { WinCrypt32.CertFreeCRLContext(pvContext); } } return(false); }
/// <summary> /// can be used to check if the certificate is available in a specific URL for CRL. A proxy can be optionally used. /// </summary> /// <param name="cert"></param> /// <param name="url"></param> /// <param name="proxy"></param> /// <returns></returns> internal bool IsCertificateInOnlineCRL(X509Certificate2 cert, string url, WebProxy proxy = null) { if (CRLNextUpdate < DateTime.Now /* is CRLNextupdate expired*/ || CRLDownloadedExpiry < DateTime.Now /*is Downloaded CRL expired*/)//check if locally cached CRL is still valid. { WebClient wc = new WebClient(); if (proxy != null) { wc.Proxy = proxy; } CRLData = wc.DownloadData(url); CRLDownloadedExpiry = DateTime.Now.AddHours(1); } if (!CheckCRLMessageSignature(CRLData)) { return(false); } IntPtr phCertStore = IntPtr.Zero; IntPtr pvContext = IntPtr.Zero; GCHandle hCrlData = new GCHandle(); GCHandle hCryptBlob = new GCHandle(); try { hCrlData = GCHandle.Alloc(CRLData, GCHandleType.Pinned); WinCrypt32.CRYPTOAPI_BLOB stCryptBlob; stCryptBlob.cbData = CRLData.Length; stCryptBlob.pbData = hCrlData.AddrOfPinnedObject(); hCryptBlob = GCHandle.Alloc(stCryptBlob, GCHandleType.Pinned); if (!WinCrypt32.CryptQueryObject( WinCrypt32.CERT_QUERY_OBJECT_BLOB, hCryptBlob.AddrOfPinnedObject(), WinCrypt32.CERT_QUERY_CONTENT_FLAG_CRL, WinCrypt32.CERT_QUERY_FORMAT_FLAG_BINARY, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref phCertStore, IntPtr.Zero, ref pvContext )) { throw new Win32Exception(Marshal.GetLastWin32Error()); } WinCrypt32.CRL_CONTEXT stCrlContext = (WinCrypt32.CRL_CONTEXT)Marshal.PtrToStructure(pvContext, typeof(WinCrypt32.CRL_CONTEXT)); WinCrypt32.CRL_INFO stCrlInfo = (WinCrypt32.CRL_INFO)Marshal.PtrToStructure(stCrlContext.pCrlInfo, typeof(WinCrypt32.CRL_INFO)); CRLNextUpdate = WinCrypt32.FiletimeToDateTime(stCrlInfo.NextUpdate); if (CRLNextUpdate < DateTime.Now) { throw new CRLExpection("CRL has expired"); } if (IsCertificateInCrl(cert, stCrlInfo)) { return(true); } else { url = GetDeltaCrlUrl(stCrlInfo); if (!string.IsNullOrEmpty(url)) { return(IsCertificateInOnlineCRL(cert, url)); } } } finally { if (hCrlData.IsAllocated) { hCrlData.Free(); } if (hCryptBlob.IsAllocated) { hCryptBlob.Free(); } if (!pvContext.Equals(IntPtr.Zero)) { WinCrypt32.CertFreeCRLContext(pvContext); } } return(false); }