File: system\security\cryptography\x509certificates\x509utils.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
 
//
// X509Utils.cs
//
 
namespace System.Security.Cryptography.X509Certificates
{
    using System.Runtime.CompilerServices;
    using System.Runtime.Versioning;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    using System.Diagnostics.Contracts;
 
    internal static class X509Constants {
        internal const uint CRYPT_EXPORTABLE     = 0x00000001;
        internal const uint CRYPT_USER_PROTECTED = 0x00000002;
        internal const uint CRYPT_MACHINE_KEYSET = 0x00000020;
        internal const uint CRYPT_USER_KEYSET    = 0x00001000;
        internal const uint PKCS12_ALWAYS_CNG_KSP = 0x00000200;
        internal const uint PKCS12_NO_PERSIST_KEY = 0x00008000;
 
        internal const uint CERT_QUERY_CONTENT_CERT               = 1;
        internal const uint CERT_QUERY_CONTENT_CTL                = 2;
        internal const uint CERT_QUERY_CONTENT_CRL                = 3;
        internal const uint CERT_QUERY_CONTENT_SERIALIZED_STORE   = 4;
        internal const uint CERT_QUERY_CONTENT_SERIALIZED_CERT    = 5;
        internal const uint CERT_QUERY_CONTENT_SERIALIZED_CTL     = 6;
        internal const uint CERT_QUERY_CONTENT_SERIALIZED_CRL     = 7;
        internal const uint CERT_QUERY_CONTENT_PKCS7_SIGNED       = 8;
        internal const uint CERT_QUERY_CONTENT_PKCS7_UNSIGNED     = 9;
        internal const uint CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10;
        internal const uint CERT_QUERY_CONTENT_PKCS10             = 11;
        internal const uint CERT_QUERY_CONTENT_PFX                = 12;
        internal const uint CERT_QUERY_CONTENT_CERT_PAIR          = 13;
 
        internal const uint CERT_STORE_PROV_MEMORY   = 2;
        internal const uint CERT_STORE_PROV_SYSTEM   = 10;
 
        // cert store flags
        internal const uint CERT_STORE_NO_CRYPT_RELEASE_FLAG            = 0x00000001;
        internal const uint CERT_STORE_SET_LOCALIZED_NAME_FLAG          = 0x00000002;
        internal const uint CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004;
        internal const uint CERT_STORE_DELETE_FLAG                      = 0x00000010;
        internal const uint CERT_STORE_SHARE_STORE_FLAG                 = 0x00000040;
        internal const uint CERT_STORE_SHARE_CONTEXT_FLAG               = 0x00000080;
        internal const uint CERT_STORE_MANIFOLD_FLAG                    = 0x00000100;
        internal const uint CERT_STORE_ENUM_ARCHIVED_FLAG               = 0x00000200;
        internal const uint CERT_STORE_UPDATE_KEYID_FLAG                = 0x00000400;
        internal const uint CERT_STORE_BACKUP_RESTORE_FLAG              = 0x00000800;
        internal const uint CERT_STORE_READONLY_FLAG                    = 0x00008000;
        internal const uint CERT_STORE_OPEN_EXISTING_FLAG               = 0x00004000;
        internal const uint CERT_STORE_CREATE_NEW_FLAG                  = 0x00002000;
        internal const uint CERT_STORE_MAXIMUM_ALLOWED_FLAG             = 0x00001000;
 
        internal const uint CERT_NAME_EMAIL_TYPE            = 1;
        internal const uint CERT_NAME_RDN_TYPE              = 2;
        internal const uint CERT_NAME_SIMPLE_DISPLAY_TYPE   = 4;
        internal const uint CERT_NAME_FRIENDLY_DISPLAY_TYPE = 5;
        internal const uint CERT_NAME_DNS_TYPE              = 6;
        internal const uint CERT_NAME_URL_TYPE              = 7;
        internal const uint CERT_NAME_UPN_TYPE              = 8;
    }
 
    /// <summary>
    ///     Groups of OIDs supported by CryptFindOIDInfo
    /// </summary>
    internal enum OidGroup {
        AllGroups = 0,
        HashAlgorithm = 1,                              // CRYPT_HASH_ALG_OID_GROUP_ID
        EncryptionAlgorithm = 2,                        // CRYPT_ENCRYPT_ALG_OID_GROUP_ID
        PublicKeyAlgorithm = 3,                         // CRYPT_PUBKEY_ALG_OID_GROUP_ID
        SignatureAlgorithm = 4,                         // CRYPT_SIGN_ALG_OID_GROUP_ID
        Attribute = 5,                                  // CRYPT_RDN_ATTR_OID_GROUP_ID
        ExtensionOrAttribute = 6,                       // CRYPT_EXT_OR_ATTR_OID_GROUP_ID
        EnhancedKeyUsage = 7,                           // CRYPT_ENHKEY_USAGE_OID_GROUP_ID
        Policy = 8,                                     // CRYPT_POLICY_OID_GROUP_ID
        Template = 9,                                   // CRYPT_TEMPLATE_OID_GROUP_ID
        KeyDerivationFunction = 10,                     // CRYPT_KDF_OID_GROUP_ID
 
        // This can be ORed into the above groups to turn off an AD search
        DisableSearchDS = unchecked((int)0x80000000)    // CRYPT_OID_DISABLE_SEARCH_DS_FLAG
    }
 
    /// <summary>
    ///     Keys that can be used to query information on via CryptFindOIDInfo
    /// </summary>
    internal enum OidKeyType {
        Oid = 1,                                        // CRYPT_OID_INFO_OID_KEY
        Name = 2,                                       // CRYPT_OID_INFO_NAME_KEY
        AlgorithmID = 3,                                // CRYPT_OID_INFO_ALGID_KEY
        SignatureID = 4,                                // CRYPT_OID_INFO_SIGN_KEY
        CngAlgorithmID = 5,                             // CRYPT_OID_INFO_CNG_ALGID_KEY
        CngSignatureID = 6,                             // CRYPT_OID_INFO_CNG_SIGN_KEY
    }
 
    [StructLayout(LayoutKind.Sequential)]
    internal struct CRYPT_OID_INFO {
        internal int cbSize;
        [MarshalAs(UnmanagedType.LPStr)]
        internal string pszOID;
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string pwszName;
        internal OidGroup dwGroupId;
        internal int AlgId;
        internal int cbData;
        internal IntPtr pbData;
    }
 
    internal static class X509Utils
    {
#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
        private static bool OidGroupWillNotUseActiveDirectory(OidGroup group) {
            // These groups will never cause an Active Directory query
            return group == OidGroup.HashAlgorithm ||
                   group == OidGroup.EncryptionAlgorithm ||
                   group == OidGroup.PublicKeyAlgorithm ||
                   group == OidGroup.SignatureAlgorithm  ||
                   group == OidGroup.Attribute ||
                   group == OidGroup.ExtensionOrAttribute ||
                   group == OidGroup.KeyDerivationFunction;
        }
 
        [SecurityCritical]
        private static CRYPT_OID_INFO FindOidInfo(OidKeyType keyType, string key, OidGroup group) {
            Contract.Requires(key != null);
 
            IntPtr rawKey = IntPtr.Zero;
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                if (keyType == OidKeyType.Oid) {
                    rawKey = Marshal.StringToCoTaskMemAnsi(key);
                }
                else {
                    rawKey = Marshal.StringToCoTaskMemUni(key);
                }
 
                // If the group alone isn't sufficient to suppress an active directory lookup, then our
                // first attempt should also include the suppression flag
                if (!OidGroupWillNotUseActiveDirectory(group)) {
                    OidGroup localGroup = group | OidGroup.DisableSearchDS;
                    IntPtr localOidInfo = CryptFindOIDInfo(keyType, rawKey, localGroup);
                    if (localOidInfo != IntPtr.Zero) {
                        return (CRYPT_OID_INFO)Marshal.PtrToStructure(localOidInfo, typeof(CRYPT_OID_INFO));
                    }
                }
 
                // Attempt to query with a specific group, to make try to avoid an AD lookup if possible
                IntPtr fullOidInfo = CryptFindOIDInfo(keyType, rawKey, group);
                if (fullOidInfo != IntPtr.Zero) {
                    return (CRYPT_OID_INFO)Marshal.PtrToStructure(fullOidInfo, typeof(CRYPT_OID_INFO));
                }
 
                // Finally, for compatibility with previous runtimes, if we have a group specified retry the
                // query with no group
                if (group != OidGroup.AllGroups) {
                    IntPtr allGroupOidInfo = CryptFindOIDInfo(keyType, rawKey, OidGroup.AllGroups);
                    if (allGroupOidInfo != IntPtr.Zero) {
                        return (CRYPT_OID_INFO)Marshal.PtrToStructure(allGroupOidInfo, typeof(CRYPT_OID_INFO));
                    }
                }
 
                // Otherwise the lookup failed
                return new CRYPT_OID_INFO();
            }
            finally {
                if (rawKey != IntPtr.Zero) {
                    Marshal.FreeCoTaskMem(rawKey);
                }
            }
        }
 
        [SecuritySafeCritical]
        internal static int GetAlgIdFromOid(string oid, OidGroup oidGroup) {
            Contract.Requires(oid != null);
 
            // CAPI does not have ALGID mappings for all of the hash algorithms - see if we know the mapping
            // first to avoid doing an AD lookup on these values
            if (String.Equals(oid, Constants.OID_OIWSEC_SHA256, StringComparison.Ordinal)) {
                return Constants.CALG_SHA_256;
            }
            else if (String.Equals(oid, Constants.OID_OIWSEC_SHA384, StringComparison.Ordinal)) {
                return Constants.CALG_SHA_384;
            }
            else if (String.Equals(oid, Constants.OID_OIWSEC_SHA512, StringComparison.Ordinal)) {
                return Constants.CALG_SHA_512;
            }
            else {
                return FindOidInfo(OidKeyType.Oid, oid, oidGroup).AlgId;
            }
        }
 
        [SecuritySafeCritical]
        internal static string GetFriendlyNameFromOid(string oid, OidGroup oidGroup) {
            Contract.Requires(oid != null);
            CRYPT_OID_INFO oidInfo = FindOidInfo(OidKeyType.Oid, oid, oidGroup);
            return oidInfo.pwszName;
        }
 
        [SecuritySafeCritical]
        internal static string GetOidFromFriendlyName(string friendlyName, OidGroup oidGroup) {
            Contract.Requires(friendlyName != null);
            CRYPT_OID_INFO oidInfo = FindOidInfo(OidKeyType.Name, friendlyName, oidGroup);
            return oidInfo.pszOID;
        }
 
        internal static int NameOrOidToAlgId (string oid, OidGroup oidGroup) {
            // Default Algorithm Id is CALG_SHA1
            if (oid == null)
                return Constants.CALG_SHA1;
            string oidValue = CryptoConfig.MapNameToOID(oid, oidGroup);
            if (oidValue == null)
                oidValue = oid; // we were probably passed an OID value directly
 
            int algId = GetAlgIdFromOid(oidValue, oidGroup);
            if (algId == 0 || algId == -1) {
                throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidOID"));
            }
            return algId;
        }
#endif // FEATURE_CRYPTO
 
        // this method maps a cert content type returned from CryptQueryObject
        // to a value in the managed X509ContentType enum
        internal static X509ContentType MapContentType(uint contentType) {
            switch (contentType) {
                case X509Constants.CERT_QUERY_CONTENT_CERT:
                    return X509ContentType.Cert;
#if !FEATURE_CORECLR
                case X509Constants.CERT_QUERY_CONTENT_SERIALIZED_STORE:
                    return X509ContentType.SerializedStore;
                case X509Constants.CERT_QUERY_CONTENT_SERIALIZED_CERT:
                    return X509ContentType.SerializedCert;
                case X509Constants.CERT_QUERY_CONTENT_PKCS7_SIGNED:
                case X509Constants.CERT_QUERY_CONTENT_PKCS7_UNSIGNED:
                    return X509ContentType.Pkcs7;
                case X509Constants.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED:
                    return X509ContentType.Authenticode;
#if !FEATURE_PAL
                case X509Constants.CERT_QUERY_CONTENT_PFX:
                    return X509ContentType.Pkcs12;
#endif // !FEATURE_PAL
#endif // !FEATURE_CORECLR
                default:
                    return X509ContentType.Unknown;
            }
        }
 
        // this method maps a X509KeyStorageFlags enum to a combination of crypto API flags
        internal static uint MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags) {
#if FEATURE_LEGACYNETCF
            if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
                if (keyStorageFlags != X509KeyStorageFlags.DefaultKeySet)
                    throw new NotSupportedException(Environment.GetResourceString("Argument_InvalidFlag"), 
                                                    new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "keyStorageFlags"));
            }            
#endif
            if ((keyStorageFlags & X509Certificate.KeyStorageFlagsAll) != keyStorageFlags)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "keyStorageFlags");
 
            const X509KeyStorageFlags EphemeralPersist =
                X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.PersistKeySet;
 
            X509KeyStorageFlags persistenceFlags = keyStorageFlags & EphemeralPersist;
 
            if (persistenceFlags == EphemeralPersist)
            {
                throw new ArgumentException(
                    Environment.GetResourceString(
                        "Cryptography_X509_InvalidFlagCombination",
                        persistenceFlags),
                    "keyStorageFlags");
            }
 
#if !FEATURE_LEGACYNETCF  // CompatibilitySwitches causes problems with CCRewrite
            Contract.EndContractBlock();
#endif
 
            uint dwFlags = 0;
#if FEATURE_CORECLR
            if (keyStorageFlags != X509KeyStorageFlags.DefaultKeySet) {
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "keyStorageFlags",
                                            new NotSupportedException());
            }
#else // FEATURE_CORECLR                        
            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
                dwFlags |= X509Constants.CRYPT_USER_KEYSET;
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
                dwFlags |= X509Constants.CRYPT_MACHINE_KEYSET;
 
            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
                dwFlags |= X509Constants.CRYPT_EXPORTABLE;
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
                dwFlags |= X509Constants.CRYPT_USER_PROTECTED;
 
            if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
                dwFlags |= X509Constants.PKCS12_NO_PERSIST_KEY | X509Constants.PKCS12_ALWAYS_CNG_KSP;
 
#endif // FEATURE_CORECLR else
 
            return dwFlags;
        }
 
#if !FEATURE_CORECLR
        // this method creates a memory store from a certificate
        [System.Security.SecurityCritical]  // auto-generated
        internal static SafeCertStoreHandle ExportCertToMemoryStore(X509Certificate certificate) {
            SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle;
            X509Utils.OpenX509Store(X509Constants.CERT_STORE_PROV_MEMORY,
                                    X509Constants.CERT_STORE_ENUM_ARCHIVED_FLAG | X509Constants.CERT_STORE_CREATE_NEW_FLAG,
                                    null,
                                    safeCertStoreHandle);
            X509Utils._AddCertificateToStore(safeCertStoreHandle, certificate.CertContext);
            return safeCertStoreHandle;
        }
#endif // !FEATURE_CORECLR
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static IntPtr PasswordToHGlobalUni(object password) {
            if (password != null) {
                string pwd = password as string;
                if (pwd != null)
                    return Marshal.StringToHGlobalUni(pwd);
#if FEATURE_X509_SECURESTRINGS
                SecureString securePwd = password as SecureString;
                if (securePwd != null)
                    return Marshal.SecureStringToGlobalAllocUnicode(securePwd);
#endif // FEATURE_X509_SECURESTRINGS
            }
            return IntPtr.Zero;
        }
 
#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
        [SecurityCritical]
        [SuppressUnmanagedCodeSecurity]
        [DllImport("crypt32")]
        private static extern IntPtr CryptFindOIDInfo(OidKeyType dwKeyType, IntPtr pvKey, OidGroup dwGroupId);
#endif // FEATURE_CRYPTO
 
#if !FEATURE_CORECLR
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void _AddCertificateToStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext);
#endif // !FEATURE_CORECLR
 
        // Do not call this method without considering that as an InternalCall the same object goes in and
        // comes out, even if the handle value changes.  Therefore an input object may have been
        // SuppressFinalized and will need to be re-registered for finalization.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void _DuplicateCertContext(IntPtr handle, ref SafeCertContextHandle safeCertContext);
 
#if !FEATURE_CORECLR
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, IntPtr password);
#endif // !FEATURE_CORECLR
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _GetCertRawData(SafeCertContextHandle safeCertContext);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void _GetDateNotAfter(SafeCertContextHandle safeCertContext, ref Win32Native.FILE_TIME fileTime);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void _GetDateNotBefore(SafeCertContextHandle safeCertContext, ref Win32Native.FILE_TIME fileTime);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern string _GetIssuerName(SafeCertContextHandle safeCertContext, bool legacyV1Mode);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern string _GetPublicKeyOid(SafeCertContextHandle safeCertContext);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _GetPublicKeyParameters(SafeCertContextHandle safeCertContext);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _GetPublicKeyValue(SafeCertContextHandle safeCertContext);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern string _GetSubjectInfo(SafeCertContextHandle safeCertContext, uint displayType, bool legacyV1Mode);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _GetSerialNumber(SafeCertContextHandle safeCertContext);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern byte[] _GetThumbprint(SafeCertContextHandle safeCertContext);
 
        // Do not call this method without considering that as an InternalCall the same object goes in and
        // comes out, even if the handle value changes.  Therefore an input object may have been
        // SuppressFinalized and will need to be re-registered for finalization.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void _LoadCertFromBlob(byte[] rawData, IntPtr password, uint dwFlags, bool persistKeySet, ref SafeCertContextHandle pCertCtx);
 
        // Do not call this method without considering that as an InternalCall the same object goes in and
        // comes out, even if the handle value changes.  Therefore an input object may have been
        // SuppressFinalized and will need to be re-registered for finalization.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void _LoadCertFromFile(string fileName, IntPtr password, uint dwFlags, bool persistKeySet, ref SafeCertContextHandle pCertCtx);
 
#if !FEATURE_CORECLR
        // Do not call this method without considering that as an InternalCall the same object goes in and
        // comes out, even if the handle value changes.  Therefore an input object may have been
        // SuppressFinalized and will need to be re-registered for finalization.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void _OpenX509Store(uint storeType, uint flags, string storeName, ref SafeCertStoreHandle safeCertStoreHandle);
#endif // !FEATURE_CORECLR
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern uint _QueryCertBlobType(byte[] rawData);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern uint _QueryCertFileType(string fileName);
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void DuplicateCertContext(IntPtr handle, SafeCertContextHandle safeCertContext)
        {
            _DuplicateCertContext(handle, ref safeCertContext);
 
            if (!safeCertContext.IsInvalid) {
                GC.ReRegisterForFinalize(safeCertContext);
            }
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void LoadCertFromBlob(byte[] rawData, IntPtr password, uint dwFlags, bool persistKeySet, SafeCertContextHandle pCertCtx) {
            _LoadCertFromBlob(rawData, password, dwFlags, persistKeySet, ref pCertCtx);
 
            if (!pCertCtx.IsInvalid) {
                GC.ReRegisterForFinalize(pCertCtx);
            }
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void LoadCertFromFile(string fileName, IntPtr password, uint dwFlags, bool persistKeySet, SafeCertContextHandle pCertCtx) {
            _LoadCertFromFile(fileName, password, dwFlags, persistKeySet, ref pCertCtx);
 
            if (!pCertCtx.IsInvalid) {
                GC.ReRegisterForFinalize(pCertCtx);
            }
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static void OpenX509Store(uint storeType, uint flags, string storeName, SafeCertStoreHandle safeCertStoreHandle) {
            _OpenX509Store(storeType, flags, storeName, ref safeCertStoreHandle);
 
            if (!safeCertStoreHandle.IsInvalid) {
                GC.ReRegisterForFinalize(safeCertStoreHandle);
            }
        }
    }
}