Example #1
0
        public void CopyTo(X509Certificate2Collection collection)
        {
            Debug.Assert(collection != null);

            SafeCertContextHandle?pCertContext = null;

            while (Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext))
            {
                X509Certificate2 cert = new X509Certificate2(pCertContext.DangerousGetHandle());
                collection.Add(cert);
            }
        }
        public SafeCertContextHandle(SafeCertContextHandle parent)
        {
            ArgumentNullException.ThrowIfNull(parent);

            Debug.Assert(!parent.IsInvalid);
            Debug.Assert(!parent.IsClosed);

            bool ignored = false;

            parent.DangerousAddRef(ref ignored);
            _parent = parent;

            SetHandle(_parent.handle);
        }
        private static unsafe SafeCertContextHandle GetSignerInPKCS7Store(SafeCertStoreHandle hCertStore, SafeCryptMsgHandle hCryptMsg)
        {
            // make sure that there is at least one signer of the certificate store
            int dwSigners;
            int cbSigners = sizeof(int);

            if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, out dwSigners, ref cbSigners))
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
            }
            if (dwSigners == 0)
            {
                throw ErrorCode.CRYPT_E_SIGNER_NOT_FOUND.ToCryptographicException();
            }

            // get the first signer from the store, and use that as the loaded certificate
            int cbData = 0;

            if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, default(byte *), ref cbData))
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();

                fixed(byte *pCmsgSignerBytes = new byte[cbData])
                {
                    if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, pCmsgSignerBytes, ref cbData))
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }

                    CMSG_SIGNER_INFO_Partial *pCmsgSignerInfo = (CMSG_SIGNER_INFO_Partial *)pCmsgSignerBytes;

                    Interop.Crypt32.CERT_INFO certInfo = default(Interop.Crypt32.CERT_INFO);
                    certInfo.Issuer.cbData       = pCmsgSignerInfo->Issuer.cbData;
                    certInfo.Issuer.pbData       = pCmsgSignerInfo->Issuer.pbData;
                    certInfo.SerialNumber.cbData = pCmsgSignerInfo->SerialNumber.cbData;
                    certInfo.SerialNumber.pbData = pCmsgSignerInfo->SerialNumber.pbData;

                    SafeCertContextHandle?pCertContext = null;

                    if (!Interop.crypt32.CertFindCertificateInStore(hCertStore, Interop.Crypt32.CertFindType.CERT_FIND_SUBJECT_CERT, &certInfo, ref pCertContext))
                    {
                        Exception e = Marshal.GetHRForLastWin32Error().ToCryptographicException();
                        pCertContext.Dispose();
                        throw e;
                    }

                    return(pCertContext);
                }
        }
Example #4
0
        protected override bool ReleaseHandle()
        {
            if (_parent != null)
            {
                _parent.DangerousRelease();
                _parent = null;
            }
            else
            {
                Interop.Crypt32.CertFreeCertificateContext(handle);
            }

            SetHandle(IntPtr.Zero);
            return(true);
        }
Example #5
0
        public SafeCertContextHandle(SafeCertContextHandle parent)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }

            Debug.Assert(!parent.IsInvalid);
            Debug.Assert(!parent.IsClosed);

            bool ignored = false;

            parent.DangerousAddRef(ref ignored);
            _parent = parent;

            SetHandle(_parent.handle);
        }
Example #6
0
        public unsafe void Remove(ICertificatePal certificate)
        {
            using (SafeCertContextHandle existingCertContext = ((CertificatePal)certificate).GetCertContext())
            {
                SafeCertContextHandle?        enumCertContext = null;
                Interop.Crypt32.CERT_CONTEXT *pCertContext    = existingCertContext.CertContext;
                if (!Interop.crypt32.CertFindCertificateInStore(_certStore, Interop.Crypt32.CertFindType.CERT_FIND_EXISTING, pCertContext, ref enumCertContext))
                {
                    return;                                                                        // The certificate is not present in the store, simply return.
                }
                Interop.Crypt32.CERT_CONTEXT *pCertContextToDelete = enumCertContext.Disconnect(); // CertDeleteCertificateFromContext always frees the context (even on error)
                enumCertContext.Dispose();

                if (!Interop.Crypt32.CertDeleteCertificateFromStore(pCertContextToDelete))
                {
                    throw Marshal.GetLastPInvokeError().ToCryptographicException();
                }
            }
        }
Example #7
0
        private unsafe void FindCore(CertFindType dwFindType, void *pvFindPara, Func <SafeCertContextHandle, bool>?filter = null)
        {
            SafeCertStoreHandle findResults = Interop.crypt32.CertOpenStore(
                CertStoreProvider.CERT_STORE_PROV_MEMORY,
                CertEncodingType.All,
                IntPtr.Zero,
                CertStoreFlags.CERT_STORE_ENUM_ARCHIVED_FLAG | CertStoreFlags.CERT_STORE_CREATE_NEW_FLAG,
                null);

            if (findResults.IsInvalid)
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
            }

            SafeCertContextHandle?pCertContext = null;

            while (Interop.crypt32.CertFindCertificateInStore(_storePal.SafeCertStoreHandle, dwFindType, pvFindPara, ref pCertContext))
            {
                if (filter != null && !filter(pCertContext))
                {
                    continue;
                }

                if (_validOnly)
                {
                    if (!VerifyCertificateIgnoringErrors(pCertContext))
                    {
                        continue;
                    }
                }

                if (!Interop.crypt32.CertAddCertificateLinkToStore(findResults, pCertContext, CertStoreAddDisposition.CERT_STORE_ADD_ALWAYS, IntPtr.Zero))
                {
                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                }
            }

            using (StorePal resultsStore = new StorePal(findResults))
            {
                resultsStore.CopyTo(_copyTo);
            }
        }
Example #8
0
        private static ICertificatePal FromBlobOrFile(ReadOnlySpan <byte> rawData, string?fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(!rawData.IsEmpty || fileName != null);
            Debug.Assert(password != null);

            bool loadFromFile = (fileName != null);

            Interop.Crypt32.PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags);
            bool deleteKeyContainer = false;

            Interop.Crypt32.CertEncodingType msgAndCertEncodingType;
            Interop.Crypt32.ContentType      contentType;
            Interop.Crypt32.FormatType       formatType;
            SafeCertStoreHandle?  hCertStore   = null;
            SafeCryptMsgHandle?   hCryptMsg    = null;
            SafeCertContextHandle?pCertContext = null;

            try
            {
                unsafe
                {
                    fixed(byte *pRawData = rawData)
                    {
                        fixed(char *pFileName = fileName)
                        {
                            Interop.Crypt32.DATA_BLOB certBlob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData), (uint)(loadFromFile ? 0 : rawData.Length));

                            Interop.Crypt32.CertQueryObjectType objectType = loadFromFile ? Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_FILE : Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_BLOB;
                            void *pvObject = loadFromFile ? (void *)pFileName : (void *)&certBlob;

                            bool success = Interop.Crypt32.CryptQueryObject(
                                objectType,
                                pvObject,
                                X509ExpectedContentTypeFlags,
                                X509ExpectedFormatTypeFlags,
                                0,
                                out msgAndCertEncodingType,
                                out contentType,
                                out formatType,
                                out hCertStore,
                                out hCryptMsg,
                                out pCertContext
                                );

                            if (!success)
                            {
                                int hr = Marshal.GetHRForLastWin32Error();
                                throw hr.ToCryptographicException();
                            }
                        }
                    }

                    if (contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED)
                    {
                        pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg);
                    }
                    else if (contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PFX)
                    {
                        if (loadFromFile)
                        {
                            rawData = File.ReadAllBytes(fileName !);
                        }
                        pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags);

                        // If PersistKeySet is set we don't delete the key, so that it persists.
                        // If EphemeralKeySet is set we don't delete the key, because there's no file, so it's a wasteful call.
                        const X509KeyStorageFlags DeleteUnless =
                            X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.EphemeralKeySet;

                        deleteKeyContainer = ((keyStorageFlags & DeleteUnless) == 0);
                    }

                    CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer);

                    pCertContext = null;
                    return(pal);
                }
            }
            finally
            {
                if (hCertStore != null)
                {
                    hCertStore.Dispose();
                }
                if (hCryptMsg != null)
                {
                    hCryptMsg.Dispose();
                }
                if (pCertContext != null)
                {
                    pCertContext.Dispose();
                }
            }
        }
Example #9
0
        private static SafeCertContextHandle FilterPFXStore(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            Interop.Crypt32.PfxCertStoreFlags pfxCertStoreFlags)
        {
            SafeCertStoreHandle hStore;

            unsafe
            {
                fixed(byte *pbRawData = rawData)
                {
                    Interop.Crypt32.DATA_BLOB certBlob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pbRawData), (uint)rawData.Length);
                    hStore = Interop.Crypt32.PFXImportCertStore(ref certBlob, password, pfxCertStoreFlags);
                    if (hStore.IsInvalid)
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }
                }
            }

            try
            {
                // Find the first cert with private key. If none, then simply take the very first cert. Along the way, delete the keycontainers
                // of any cert we don't accept.
                SafeCertContextHandle pCertContext = SafeCertContextHandle.InvalidHandle;
                SafeCertContextHandle?pEnumContext = null;
                while (Interop.crypt32.CertEnumCertificatesInStore(hStore, ref pEnumContext))
                {
                    if (pEnumContext.ContainsPrivateKey)
                    {
                        if ((!pCertContext.IsInvalid) && pCertContext.ContainsPrivateKey)
                        {
                            // We already found our chosen one. Free up this one's key and move on.

                            // If this one has a persisted private key, clean up the key file.
                            // If it was an ephemeral private key no action is required.
                            if (pEnumContext.HasPersistedPrivateKey)
                            {
                                SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext);
                            }
                        }
                        else
                        {
                            // Found our first cert that has a private key. Set it up as our chosen one but keep iterating
                            // as we need to free up the keys of any remaining certs.
                            pCertContext.Dispose();
                            pCertContext = pEnumContext.Duplicate();
                        }
                    }
                    else
                    {
                        if (pCertContext.IsInvalid)
                        {
                            // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key.
                            pCertContext = pEnumContext.Duplicate();
                        }
                    }
                }

                if (pCertContext.IsInvalid)
                {
                    throw new CryptographicException(SR.Cryptography_Pfx_NoCertificates);
                }

                return(pCertContext);
            }
            finally
            {
                hStore.Dispose();
            }
        }
Example #10
0
        /// <summary>
        /// A less error-prone wrapper for CertEnumCertificatesInStore().
        ///
        /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with
        /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle
        /// and returns "false" to indicate the end of the store has been reached.
        /// </summary>
        public static unsafe bool CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertFindType dwFindType, void *pvFindPara, [NotNull] ref SafeCertContextHandle?pCertContext)
        {
            CERT_CONTEXT *pPrevCertContext = pCertContext == null ? null : pCertContext.Disconnect();

            pCertContext = CertFindCertificateInStore(hCertStore, CertEncodingType.All, CertFindFlags.None, dwFindType, pvFindPara, pPrevCertContext);
            return(!pCertContext.IsInvalid);
        }
Example #11
0
        /// <summary>
        /// A less error-prone wrapper for CertEnumCertificatesInStore().
        ///
        /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with
        /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle
        /// and returns "false" to indicate the end of the store has been reached.
        /// </summary>
        public static unsafe bool CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, [NotNull] ref SafeCertContextHandle?pCertContext)
        {
            CERT_CONTEXT *pPrevCertContext;

            if (pCertContext == null)
            {
                pCertContext     = new SafeCertContextHandle();
                pPrevCertContext = null;
            }
            else
            {
                pPrevCertContext = pCertContext.Disconnect();
            }

            pCertContext.SetHandle((IntPtr)CertEnumCertificatesInStore(hCertStore, pPrevCertContext));

            if (!pCertContext.IsInvalid)
            {
                return(true);
            }

            pCertContext.Dispose();
            return(false);
        }
Example #12
0
 /// <summary>
 /// A less error-prone wrapper for CertEnumCertificatesInStore().
 ///
 /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with
 /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle
 /// and returns "false" to indicate the end of the store has been reached.
 /// </summary>
 public static bool CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, [NotNull] ref SafeCertContextHandle?pCertContext)
 {
     unsafe
     {
         CERT_CONTEXT *pPrevCertContext = pCertContext == null ? null : pCertContext.Disconnect();
         pCertContext = CertEnumCertificatesInStore(hCertStore, pPrevCertContext);
         return(!pCertContext.IsInvalid);
     }
 }
        private static StorePal FromBlobOrFile(ReadOnlySpan <byte> rawData, string?fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);

            bool fromFile = fileName != null;

            unsafe
            {
                fixed(byte *pRawData = rawData)
                {
                    fixed(char *pFileName = fileName)
                    {
                        Interop.Crypt32.DATA_BLOB blob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData), (uint)(fromFile ? 0 : rawData !.Length));
                        bool persistKeySet             = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet));

                        Interop.Crypt32.PfxCertStoreFlags certStoreFlags = MapKeyStorageFlags(keyStorageFlags);

                        void *pvObject = fromFile ? (void *)pFileName : (void *)&blob;

                        Interop.Crypt32.ContentType contentType;
                        SafeCertStoreHandle         certStore;

                        if (!Interop.Crypt32.CryptQueryObject(
                                fromFile ? Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_FILE : Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_BLOB,
                                pvObject,
                                StoreExpectedContentFlags,
                                Interop.Crypt32.ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL,
                                0,
                                IntPtr.Zero,
                                out contentType,
                                IntPtr.Zero,
                                out certStore,
                                IntPtr.Zero,
                                IntPtr.Zero
                                ))
                        {
                            Exception e = Marshal.GetLastPInvokeError().ToCryptographicException();
                            certStore.Dispose();
                            throw e;
                        }

                        if (contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PFX)
                        {
                            certStore.Dispose();

                            if (fromFile)
                            {
                                rawData = File.ReadAllBytes(fileName !);
                            }

                            fixed(byte *pRawData2 = rawData)
                            {
                                Interop.Crypt32.DATA_BLOB blob2 = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData2), (uint)rawData !.Length);
                                certStore = Interop.Crypt32.PFXImportCertStore(ref blob2, password, certStoreFlags);
                                if (certStore == null || certStore.IsInvalid)
                                {
                                    Exception e = Marshal.GetLastPInvokeError().ToCryptographicException();
                                    certStore?.Dispose();
                                    throw e;
                                }
                            }

                            if (!persistKeySet)
                            {
                                //
                                // If the user did not want us to persist private keys, then we should loop through all
                                // the certificates in the collection and set our custom CERT_CLR_DELETE_KEY_PROP_ID property
                                // so the key container will be deleted when the cert contexts will go away.
                                //
                                SafeCertContextHandle?pCertContext = null;
                                while (Interop.crypt32.CertEnumCertificatesInStore(certStore, ref pCertContext))
                                {
                                    Interop.Crypt32.DATA_BLOB nullBlob = new Interop.Crypt32.DATA_BLOB(IntPtr.Zero, 0);
                                    if (!Interop.Crypt32.CertSetCertificateContextProperty(pCertContext, Interop.Crypt32.CertContextPropId.CERT_CLR_DELETE_KEY_PROP_ID, Interop.Crypt32.CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, &nullBlob))
                                    {
                                        Exception e = Marshal.GetLastPInvokeError().ToCryptographicException();
                                        certStore.Dispose();
                                        throw e;
                                    }
                                }
                            }
                        }

                        return(new StorePal(certStore));
                    }
                }
            }
        }
Example #14
0
        public byte[]? Export(X509ContentType contentType, SafePasswordHandle password)
        {
            Debug.Assert(password != null);
            switch (contentType)
            {
            case X509ContentType.Cert:
            {
                SafeCertContextHandle?pCertContext = null;
                if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext))
                {
                    return(null);
                }
                try
                {
                    unsafe
                    {
                        byte[] rawData = new byte[pCertContext.CertContext->cbCertEncoded];
                        Marshal.Copy((IntPtr)(pCertContext.CertContext->pbCertEncoded), rawData, 0, rawData.Length);
                        GC.KeepAlive(pCertContext);
                        return(rawData);
                    }
                }
                finally
                {
                    pCertContext.Dispose();
                }
            }

            case X509ContentType.SerializedCert:
            {
                SafeCertContextHandle?pCertContext = null;
                if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext))
                {
                    return(null);
                }

                try
                {
                    int cbEncoded = 0;
                    if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, null, ref cbEncoded))
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }

                    byte[] pbEncoded = new byte[cbEncoded];
                    if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, pbEncoded, ref cbEncoded))
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }

                    return(pbEncoded);
                }
                finally
                {
                    pCertContext.Dispose();
                }
            }

            case X509ContentType.Pkcs12:
            {
                unsafe
                {
                    CRYPTOAPI_BLOB dataBlob = new CRYPTOAPI_BLOB(0, (byte *)null);

                    if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }

                    byte[] pbEncoded = new byte[dataBlob.cbData];
                    fixed(byte *ppbEncoded = pbEncoded)
                    {
                        dataBlob.pbData = ppbEncoded;
                        if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
                        {
                            throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                        }
                    }

                    return(pbEncoded);
                }
            }

            case X509ContentType.SerializedStore:
                return(SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_STORE));

            case X509ContentType.Pkcs7:
                return(SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_PKCS7));

            default:
                throw new CryptographicException(SR.Cryptography_X509_InvalidContentType);
            }
        }
        private static ICertificatePal FromBlobOrFile(byte[]?rawData, string?fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(rawData != null || fileName != null);
            Debug.Assert(password != null);

            bool loadFromFile = (fileName != null);

            PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags);
            bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet));

            CertEncodingType      msgAndCertEncodingType;
            ContentType           contentType;
            FormatType            formatType;
            SafeCertStoreHandle?  hCertStore   = null;
            SafeCryptMsgHandle?   hCryptMsg    = null;
            SafeCertContextHandle?pCertContext = null;

            try
            {
                unsafe
                {
                    fixed(byte *pRawData = rawData)
                    {
                        fixed(char *pFileName = fileName)
                        {
                            CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(loadFromFile ? 0 : rawData !.Length, pRawData);

                            CertQueryObjectType objectType = loadFromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB;
                            void *pvObject = loadFromFile ? (void *)pFileName : (void *)&certBlob;

                            bool success = Interop.crypt32.CryptQueryObject(
                                objectType,
                                pvObject,
                                X509ExpectedContentTypeFlags,
                                X509ExpectedFormatTypeFlags,
                                0,
                                out msgAndCertEncodingType,
                                out contentType,
                                out formatType,
                                out hCertStore,
                                out hCryptMsg,
                                out pCertContext
                                );

                            if (!success)
                            {
                                int hr = Marshal.GetHRForLastWin32Error();
                                throw hr.ToCryptographicException();
                            }
                        }
                    }

                    if (contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED)
                    {
                        pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg);
                    }
                    else if (contentType == ContentType.CERT_QUERY_CONTENT_PFX)
                    {
                        if (loadFromFile)
                        {
                            rawData = File.ReadAllBytes(fileName !);
                        }
                        pCertContext = FilterPFXStore(rawData !, password, pfxCertStoreFlags);
                    }

                    CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer: !persistKeySet);

                    pCertContext = null;
                    return(pal);
                }
            }
            finally
            {
                if (hCertStore != null)
                {
                    hCertStore.Dispose();
                }
                if (hCryptMsg != null)
                {
                    hCryptMsg.Dispose();
                }
                if (pCertContext != null)
                {
                    pCertContext.Dispose();
                }
            }
        }
        /// <summary>
        /// A less error-prone wrapper for CertEnumCertificatesInStore().
        ///
        /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with
        /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle
        /// and returns "false" to indicate the end of the store has been reached.
        /// </summary>
        public static unsafe bool CertFindCertificateInStore(SafeCertStoreHandle hCertStore, Interop.Crypt32.CertFindType dwFindType, void *pvFindPara, [NotNull] ref SafeCertContextHandle?pCertContext)
        {
            Interop.Crypt32.CERT_CONTEXT *pPrevCertContext = null;
            if (pCertContext != null)
            {
                pPrevCertContext = pCertContext.Disconnect();
                pCertContext.Dispose();
            }

            pCertContext = Interop.Crypt32.CertFindCertificateInStore(hCertStore, Interop.Crypt32.CertEncodingType.All, Interop.Crypt32.CertFindFlags.None, dwFindType, pvFindPara, pPrevCertContext);
            return(!pCertContext.IsInvalid);
        }