| File: System\Security\Cryptography\X509Certificates\X509Utils.cs | Web Access |
| Project: src\runtime\src\libraries\System.Windows.Extensions\src\System.Windows.Extensions.csproj (System.Windows.Extensions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography.X509Certificates { internal static class X509Utils { internal const uint CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200; internal const uint CERT_STORE_CREATE_NEW_FLAG = 0x00002000; internal static SafeCertContextHandle DuplicateCertificateContext(X509Certificate2 certificate) { SafeCertContextHandle safeCertContext = Interop.Crypt32.CertDuplicateCertificateContext(certificate.Handle); GC.KeepAlive(certificate); return safeCertContext; } internal static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection) { SafeCertStoreHandle safeCertStoreHandle; // 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 = Interop.Crypt32.CertOpenStore( new IntPtr(Interop.Crypt32.CERT_STORE_PROV_MEMORY), Interop.Crypt32.X509_ASN_ENCODING | Interop.Crypt32.PKCS_7_ASN_ENCODING, IntPtr.Zero, CERT_STORE_ENUM_ARCHIVED_FLAG | CERT_STORE_CREATE_NEW_FLAG, IntPtr.Zero); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) { Exception e = new CryptographicException(Marshal.GetLastPInvokeError()); safeCertStoreHandle?.Dispose(); throw e; } // 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) { using (SafeCertContextHandle handle = DuplicateCertificateContext(x509)) { if (!Interop.Crypt32.CertAddCertificateLinkToStore( safeCertStoreHandle, handle, Interop.Crypt32.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { throw new CryptographicException(Marshal.GetLastPInvokeError()); } } } return safeCertStoreHandle; } internal static X509Certificate2Collection GetCertificates(SafeCertStoreHandle safeCertStoreHandle) { X509Certificate2Collection collection = new X509Certificate2Collection(); IntPtr pEnumContext = Interop.Crypt32.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); while (pEnumContext != IntPtr.Zero) { X509Certificate2 certificate = new X509Certificate2(pEnumContext); collection.Add(certificate); pEnumContext = Interop.Crypt32.CertEnumCertificatesInStore(safeCertStoreHandle, pEnumContext); } return collection; } } }