private static unsafe SafeCertStoreHandle SelectFromStore(SafeCertStoreHandle safeSourceStoreHandle, string title, string message, X509SelectionFlag selectionFlags, IntPtr hwndParent) { int dwErrorCode = CAPI.ERROR_SUCCESS; // First, create a memory store SafeCertStoreHandle safeCertStoreHandle = CAPI.CertOpenStore((IntPtr)CAPI.CERT_STORE_PROV_MEMORY, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, 0, null); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW csc = new CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW(); // Older versions of CRYPTUI do not check the size correctly, // so always force it to the oldest version of the structure. csc.dwSize = (uint)Marshal.OffsetOf(typeof(CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW), "hSelectedCertStore"); csc.hwndParent = hwndParent; csc.dwFlags = (uint)selectionFlags; csc.szTitle = title; csc.dwDontUseColumn = 0; csc.szDisplayString = message; csc.pFilterCallback = IntPtr.Zero; csc.pDisplayCallback = IntPtr.Zero; csc.pvCallbackData = IntPtr.Zero; csc.cDisplayStores = 1; IntPtr hSourceCertStore = safeSourceStoreHandle.DangerousGetHandle(); csc.rghDisplayStores = new IntPtr(&hSourceCertStore); csc.cStores = 0; csc.rghStores = IntPtr.Zero; csc.cPropSheetPages = 0; csc.rgPropSheetPages = IntPtr.Zero; csc.hSelectedCertStore = safeCertStoreHandle.DangerousGetHandle(); SafeCertContextHandle safeCertContextHandle = CAPI.CryptUIDlgSelectCertificateW(csc); if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { // Single select, so add it to our hCertStore SafeCertContextHandle ppStoreContext = SafeCertContextHandle.InvalidHandle; if (!CAPI.CertAddCertificateLinkToStore(safeCertStoreHandle, safeCertContextHandle, CAPI.CERT_STORE_ADD_ALWAYS, ppStoreContext)) { dwErrorCode = Marshal.GetLastWin32Error(); } } if (dwErrorCode != CAPI.ERROR_SUCCESS) { throw new CryptographicException(Marshal.GetLastWin32Error()); } return(safeCertStoreHandle); }
private static void FindByCert(System.Security.Cryptography.SafeCertStoreHandle safeSourceStoreHandle, uint dwFindType, IntPtr pvFindPara, bool validOnly, FindProcDelegate pfnCertCallback1, FindProcDelegate pfnCertCallback2, object pvCallbackData1, object pvCallbackData2, System.Security.Cryptography.SafeCertStoreHandle safeTargetStoreHandle) { int hr = 0; System.Security.Cryptography.SafeCertContextHandle invalidHandle = System.Security.Cryptography.SafeCertContextHandle.InvalidHandle; invalidHandle = CAPI.CertFindCertificateInStore(safeSourceStoreHandle, 0x10001, 0, dwFindType, pvFindPara, invalidHandle); while ((invalidHandle != null) && !invalidHandle.IsInvalid) { if (pfnCertCallback1 != null) { hr = pfnCertCallback1(invalidHandle, pvCallbackData1); if (hr == 1) { if (pfnCertCallback2 != null) { hr = pfnCertCallback2(invalidHandle, pvCallbackData2); } if (hr == 1) { goto Label_008D; } } if (hr != 0) { break; } } if (validOnly) { hr = System.Security.Cryptography.X509Certificates.X509Utils.VerifyCertificate(invalidHandle, null, null, X509RevocationMode.NoCheck, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), null, new IntPtr(1L), IntPtr.Zero); if (hr == 1) { goto Label_008D; } if (hr != 0) { break; } } if (!CAPI.CertAddCertificateLinkToStore(safeTargetStoreHandle, invalidHandle, 4, System.Security.Cryptography.SafeCertContextHandle.InvalidHandle)) { hr = Marshal.GetHRForLastWin32Error(); break; } Label_008D: GC.SuppressFinalize(invalidHandle); invalidHandle = CAPI.CertFindCertificateInStore(safeSourceStoreHandle, 0x10001, 0, dwFindType, pvFindPara, invalidHandle); } if ((invalidHandle != null) && !invalidHandle.IsInvalid) { invalidHandle.Dispose(); } if ((hr != 1) && (hr != 0)) { throw new CryptographicException(hr); } }
internal static Cryptography.SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection) { // // We need to Assert all StorePermission flags since this is a memory store and we want // semi-trusted code to be able to export certificates to a memory store. // #if !FEATURE_CORESYSTEM StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags); sp.Assert(); #endif Cryptography.SafeCertStoreHandle safeCertStoreHandle = Cryptography.SafeCertStoreHandle.InvalidHandle; // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. safeCertStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(safeCertStoreHandle, x509.CertContext, CAPI.CERT_STORE_ADD_ALWAYS, Cryptography.SafeCertContextHandle.InvalidHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } return(safeCertStoreHandle); }
internal static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection) { new StorePermission(StorePermissionFlags.CreateStore | StorePermissionFlags.DeleteStore | StorePermissionFlags.EnumerateStores | StorePermissionFlags.OpenStore | StorePermissionFlags.AddToStore | StorePermissionFlags.RemoveFromStore | StorePermissionFlags.EnumerateCertificates).Assert(); SafeCertStoreHandle invalidHandle = SafeCertStoreHandle.InvalidHandle; SafeCertStoreHandle hCertStore = CAPI.CertOpenStore(new IntPtr(2L), 65537U, IntPtr.Zero, 8704U, (string)null); if (hCertStore == null || hCertStore.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } foreach (X509Certificate2 certificate in collection) { if (!CAPI.CertAddCertificateLinkToStore(hCertStore, X509Utils.GetCertContext(certificate), 4U, System.Security.Cryptography.SafeCertContextHandle.InvalidHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } return(hCertStore); }
internal static System.Security.Cryptography.SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection) { new StorePermission(StorePermissionFlags.AllFlags).Assert(); System.Security.Cryptography.SafeCertStoreHandle invalidHandle = System.Security.Cryptography.SafeCertStoreHandle.InvalidHandle; invalidHandle = CAPI.CertOpenStore(new IntPtr(2L), 0x10001, IntPtr.Zero, 0x2200, null); if ((invalidHandle == null) || invalidHandle.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } X509Certificate2Enumerator enumerator = collection.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; if (!CAPI.CertAddCertificateLinkToStore(invalidHandle, current.CertContext, 4, System.Security.Cryptography.SafeCertContextHandle.InvalidHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } return(invalidHandle); }
private static void AddToStore(SafeCertStoreHandle safeCertStoreHandle, X509Certificate2Collection collection) { // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // // X509Store.Add(Range) uses CertAddCertificateContextToStore, which would lose information like ephemeral // private key associations. foreach (X509Certificate2 x509 in collection) { using (SafeCertContextHandle ctx = X509Utils.GetCertContext(x509)) { if (!CAPI.CertAddCertificateLinkToStore(safeCertStoreHandle, ctx, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } } }
static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection, IntPtr pCertContext) { CAPI.CERT_CONTEXT certContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(pCertContext, typeof(CAPI.CERT_CONTEXT)); // No extra store nor intermediate certificates if ((collection == null || collection.Count <= 0) && certContext.hCertStore == IntPtr.Zero) { return(SafeCertStoreHandle.InvalidHandle); } // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. SafeCertStoreHandle certStoreHandle = CAPI.CertOpenStore( new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (certStoreHandle == null || certStoreHandle.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // // Add extra store if (collection != null && collection.Count > 0) { foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } // Add intermediates // The hCertStore needs to be acquired from an X509Certificate2 object // constructed using a fresh cert context handle. If we simply refer to the hCertStore // property of the certContext local variable directly, there is a risk that we are accessing // a closed store. This is because if the X509Certificate2(rawdata) constructor closes the store handle (hCertStore). // There is no way to know which constructor was used at this point. // using (SafeCertContextHandle safeCertContext = CAPI.CertCreateCertificateContext(certContext.dwCertEncodingType, certContext.pbCertEncoded, certContext.cbCertEncoded)) { // // Create an X509Certificate2 using the new cert context that dup's the provided certificate. // X509Certificate2 intermediatesCert = new X509Certificate2(safeCertContext.DangerousGetHandle()); // // Dereference the handle to this intermediate cert and use it to access the handle // of this certificate's cert store. Then, call CAPI.CertAddCertificateLinkToStore // on each cert in this store by wrapping this cert store handle with an X509Store // object. // CAPI.CERT_CONTEXT intermediatesCertContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(intermediatesCert.Handle, typeof(CAPI.CERT_CONTEXT)); if (intermediatesCertContext.hCertStore != IntPtr.Zero) { X509Certificate2Collection intermediates = null; X509Store store = new X509Store(intermediatesCertContext.hCertStore); try { intermediates = store.Certificates; foreach (X509Certificate2 x509 in intermediates) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } finally { SecurityUtils.ResetAllCertificates(intermediates); store.Close(); } } } return(certStoreHandle); }