Exemple #1
0
        internal static SafeSecCertificateHandle X509ImportCertificate(
            ReadOnlySpan <byte> bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword,
            SafeKeychainHandle keychain,
            bool exportable,
            out SafeSecIdentityHandle identityHandle)
        {
            SafeCreateHandle?cfPassphrase    = null;
            bool             releasePassword = false;

            try
            {
                if (!importPassword.IsInvalid)
                {
                    importPassword.DangerousAddRef(ref releasePassword);
                    cfPassphrase = CoreFoundation.CFStringCreateFromSpan(importPassword.DangerousGetSpan());
                }

                return(X509ImportCertificate(
                           bytes,
                           contentType,
                           cfPassphrase,
                           keychain,
                           exportable,
                           out identityHandle));
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

                cfPassphrase?.Dispose();
            }
        }
Exemple #2
0
        public override byte[] Export(X509ContentType contentType, SafePasswordHandle password)
        {
            if (_cert == null)
            {
                throw new CryptographicException(empty_error);
            }

            switch (contentType)
            {
            case X509ContentType.Cert:
                return(_cert.RawData);

            case X509ContentType.Pfx:             // this includes Pkcs12
                return(ExportPkcs12(password));

            case X509ContentType.SerializedCert:
                // TODO
                throw new NotSupportedException();

            default:
                string msg = Locale.GetText("This certificate format '{0}' cannot be exported.", contentType);
                throw new CryptographicException(msg);
            }
        }
Exemple #3
0
        public static ICertificatePal FromBlob(byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);

            ICertificatePal cert;

            if (TryReadX509Der(rawData, out cert) ||
                TryReadX509Pem(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs7Der(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs12(rawData, password, out cert))
            {
                if (cert == null)
                {
                    // Empty collection, most likely.
                    throw new CryptographicException();
                }

                return(cert);
            }

            // Unsupported
            throw Interop.Crypto.CreateOpenSslCryptographicException();
        }
Exemple #4
0
        private static bool TryReadPkcs12(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            bool single,
            bool ephemeralSpecified,
            out ICertificatePal?readPal,
            out List <ICertificatePal>?readCerts,
            out Exception?openSslException)
        {
            // DER-PKCS12
            OpenSslPkcs12Reader?pfx;

            if (!OpenSslPkcs12Reader.TryRead(rawData, out pfx, out openSslException))
            {
                readPal   = null;
                readCerts = null;
                return(false);
            }

            using (pfx)
            {
                return(TryReadPkcs12(pfx, password, single, ephemeralSpecified, out readPal, out readCerts));
            }
        }
Exemple #5
0
        public static ICertificatePal FromBlob(ReadOnlySpan <byte> rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);
            ICertificatePal?cert;
            Exception?      exception;

            if (TryReadX509(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs7Der(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) ||
                PkcsFormatReader.TryReadPkcs12(rawData, password, out cert, out exception))
            {
                if (cert == null)
                {
                    // Empty collection, most likely.
                    throw new CryptographicException();
                }

                return(cert);
            }

            // Unsupported
            Debug.Assert(exception != null);
            throw exception;
        }
Exemple #6
0
        public sealed override byte[] Export(X509ContentType contentType, SafePasswordHandle password)
        {
            ThrowIfContextInvalid();

            Debug.Assert(password != null);
            switch (contentType)
            {
            case X509ContentType.Cert:
                return(RawData);

            case X509ContentType.Pkcs12:
                return(ExportPkcs12(password));

            case X509ContentType.Pkcs7:
                return(ExportPkcs12((string)null));

            case X509ContentType.SerializedCert:
            case X509ContentType.SerializedStore:
                throw new PlatformNotSupportedException(SR.Cryptography_Unix_X509_SerializedExport);

            default:
                throw new CryptographicException(SR.Cryptography_X509_InvalidContentType);
            }
        }
Exemple #7
0
 public static ICertificatePal FromBlob(ReadOnlySpan <byte> rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(OpenSslX509CertificateReader.FromBlob(rawData, password, keyStorageFlags));
 }
Exemple #8
0
        public static ICertificatePal FromBlob(
            byte[] rawData,
            SafePasswordHandle password,
            X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);

            X509ContentType contentType = X509Certificate2.GetCertContentType(rawData);

            if (contentType == X509ContentType.Pkcs7)
            {
                // In single mode for a PKCS#7 signed or signed-and-enveloped file we're supposed to return
                // the certificate which signed the PKCS#7 file.
                //
                // X509Certificate2Collection::Export(X509ContentType.Pkcs7) claims to be a signed PKCS#7,
                // but doesn't emit a signature block. So this is hard to test.
                //
                // TODO(2910): Figure out how to extract the signing certificate, when it's present.
                throw new CryptographicException(SR.Cryptography_X509_PKCS7_NoSigner);
            }

            bool exportable = true;

            SafeKeychainHandle keychain;

            if (contentType == X509ContentType.Pkcs12)
            {
                if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
                {
                    throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx);
                }

                exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable;

                bool persist =
                    (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet;

                keychain = persist
                    ? Interop.AppleCrypto.SecKeychainCopyDefault()
                    : Interop.AppleCrypto.CreateTemporaryKeychain();
            }
            else
            {
                keychain = SafeTemporaryKeychainHandle.InvalidHandle;
                password = SafePasswordHandle.InvalidHandle;
            }

            using (keychain)
            {
                SafeSecIdentityHandle    identityHandle;
                SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate(
                    rawData,
                    contentType,
                    password,
                    keychain,
                    exportable,
                    out identityHandle);

                if (identityHandle.IsInvalid)
                {
                    identityHandle.Dispose();
                    return(new AppleCertificatePal(certHandle));
                }

                if (contentType != X509ContentType.Pkcs12)
                {
                    Debug.Fail("Non-PKCS12 import produced an identity handle");

                    identityHandle.Dispose();
                    certHandle.Dispose();
                    throw new CryptographicException();
                }

                Debug.Assert(certHandle.IsInvalid);
                certHandle.Dispose();
                return(new AppleCertificatePal(identityHandle));
            }
        }
Exemple #9
0
 public static partial bool PFXExportCertStore(SafeCertStoreHandle hStore, ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle szPassword, PFXExportFlags dwFlags);
Exemple #10
0
 public static partial SafeCertStoreHandle PFXImportCertStore(ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);
Exemple #11
0
 public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);
Exemple #12
0
 public static ICertificatePal FromBlob(ReadOnlySpan <byte> rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(FromBlobOrFile(rawData, null, password, keyStorageFlags));
 }
Exemple #13
0
 public virtual void Import(string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
 {
     byte[] rawData = File.ReadAllBytes(fileName);
     using (var safePasswordHandle = new SafePasswordHandle(password))
         impl = X509Helper.Import(rawData, safePasswordHandle, keyStorageFlags);
 }
Exemple #14
0
 public static X509Certificate2 CreateCertificate2(byte[] data, string password, bool disallowFallback = false)
 {
     using (var handle = new SafePasswordHandle(password))
         using (var impl = new X509CertificateImplBtls(data, handle, X509KeyStorageFlags.DefaultKeySet))
             return(new X509Certificate2(impl));
 }
Exemple #15
0
        private static ILoaderPal FromBio(SafeBioHandle bio, SafePasswordHandle password)
        {
            int bioPosition = Interop.Crypto.BioTell(bio);

            Debug.Assert(bioPosition >= 0);

            ICertificatePal singleCert;

            if (OpenSslX509CertificateReader.TryReadX509Pem(bio, out singleCert))
            {
                return(SingleCertToLoaderPal(singleCert));
            }

            // Rewind, try again.
            OpenSslX509CertificateReader.RewindBio(bio, bioPosition);

            if (OpenSslX509CertificateReader.TryReadX509Der(bio, out singleCert))
            {
                return(SingleCertToLoaderPal(singleCert));
            }

            // Rewind, try again.
            OpenSslX509CertificateReader.RewindBio(bio, bioPosition);

            List <ICertificatePal> certPals;

            if (PkcsFormatReader.TryReadPkcs7Pem(bio, out certPals))
            {
                return(ListToLoaderPal(certPals));
            }

            // Rewind, try again.
            OpenSslX509CertificateReader.RewindBio(bio, bioPosition);

            if (PkcsFormatReader.TryReadPkcs7Der(bio, out certPals))
            {
                return(ListToLoaderPal(certPals));
            }

            // Rewind, try again.
            OpenSslX509CertificateReader.RewindBio(bio, bioPosition);

            // Capture the exception so in case of failure, the call to BioSeek does not override it.
            Exception openSslException;

            if (PkcsFormatReader.TryReadPkcs12(bio, password, out certPals, out openSslException))
            {
                return(ListToLoaderPal(certPals));
            }

            // Since we aren't going to finish reading, leaving the buffer where it was when we got
            // it seems better than leaving it in some arbitrary other position.
            //
            // Use BioSeek directly for the last seek attempt, because any failure here should instead
            // report the already created (but not yet thrown) exception.
            if (Interop.Crypto.BioSeek(bio, bioPosition) < 0)
            {
                Interop.Crypto.ErrClearError();
            }

            Debug.Assert(openSslException != null);
            throw openSslException;
        }
Exemple #16
0
 internal X509Certificate2Impl GetNativeCertificate(
     byte[] data, SafePasswordHandle password, X509KeyStorageFlags flags)
 {
     return(new X509CertificateImplBtls(data, password, flags));
 }
Exemple #17
0
 internal override X509Certificate2Impl GetNativeCertificate(
     byte[] data, string password, X509KeyStorageFlags flags)
 {
     using (var handle = new SafePasswordHandle(password))
         return(GetNativeCertificate(data, handle, flags));
 }
Exemple #18
0
 public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle szPassword, PFXExportFlags dwFlags);
Exemple #19
0
 public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(OpenSslX509CertificateReader.FromFile(fileName, password, keyStorageFlags));
 }
Exemple #20
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();
                }
            }
        }
Exemple #21
0
 public virtual void Import(byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
 {
     using (var safePasswordHandle = new SafePasswordHandle(password))
         impl = X509Helper.Import(rawData, safePasswordHandle, keyStorageFlags);
 }
Exemple #22
0
 public static X509CertificateImpl Import(byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(CertificateProvider.Import(rawData, password, keyStorageFlags));
 }
Exemple #23
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();
            }
        }
Exemple #24
0
 internal static partial ICertificatePal FromFile(
     string fileName,
     SafePasswordHandle password,
     X509KeyStorageFlags keyStorageFlags);
Exemple #25
0
 public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(FromBlobOrFile(ReadOnlySpan <byte> .Empty, fileName, password, keyStorageFlags));
 }
Exemple #26
0
 public static ILoaderPal FromBlob(byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(FromBlobOrFile(rawData, null, password, keyStorageFlags));
 }
Exemple #27
0
        public static ICertificatePal FromBlob(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);

            X509ContentType contentType = X509Certificate2.GetCertContentType(rawData);

            if (contentType == X509ContentType.Pkcs7)
            {
                // In single mode for a PKCS#7 signed or signed-and-enveloped file we're supposed to return
                // the certificate which signed the PKCS#7 file.
                //
                // X509Certificate2Collection::Export(X509ContentType.Pkcs7) claims to be a signed PKCS#7,
                // but doesn't emit a signature block. So this is hard to test.
                //
                // TODO(2910): Figure out how to extract the signing certificate, when it's present.
                throw new CryptographicException(SR.Cryptography_X509_PKCS7_NoSigner);
            }

            if (contentType == X509ContentType.Pkcs12)
            {
                if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
                {
                    throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx);
                }

                bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable;

                bool persist =
                    (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet;

                SafeKeychainHandle keychain = persist
                    ? Interop.AppleCrypto.SecKeychainCopyDefault()
                    : Interop.AppleCrypto.CreateTemporaryKeychain();

                using (keychain)
                {
                    AppleCertificatePal ret = ImportPkcs12(rawData, password, exportable, keychain);
                    if (!persist)
                    {
                        // If we used temporary keychain we need to prevent deletion.
                        // on 10.15+ if keychain is unlinked, certain certificate operations may fail.
                        bool success = false;
                        keychain.DangerousAddRef(ref success);
                        if (success)
                        {
                            ret._tempKeychain = keychain;
                        }
                    }

                    return(ret);
                }
            }

            SafeSecIdentityHandle    identityHandle;
            SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate(
                rawData,
                contentType,
                SafePasswordHandle.InvalidHandle,
                SafeTemporaryKeychainHandle.InvalidHandle,
                exportable: true,
                out identityHandle);

            if (identityHandle.IsInvalid)
            {
                identityHandle.Dispose();
                return(new AppleCertificatePal(certHandle));
            }

            Debug.Fail("Non-PKCS12 import produced an identity handle");

            identityHandle.Dispose();
            certHandle.Dispose();
            throw new CryptographicException();
        }
Exemple #28
0
 public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
 {
     return(FromBlobOrFile(null, fileName, password, keyStorageFlags));
 }
Exemple #29
0
 public static byte[] Export(X509CertificateImpl impl, X509ContentType contentType, SafePasswordHandle password)
 {
     ThrowIfContextInvalid(impl);
     return(impl.Export(contentType, password));
 }
Exemple #30
0
        private static StorePal FromBlobOrFile(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)
                    {
                        CRYPTOAPI_BLOB    blob           = new CRYPTOAPI_BLOB(fromFile ? 0 : rawData.Length, pRawData);
                        bool              persistKeySet  = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet));
                        PfxCertStoreFlags certStoreFlags = MapKeyStorageFlags(keyStorageFlags);

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

                        ContentType         contentType;
                        SafeCertStoreHandle certStore;

                        if (!Interop.crypt32.CryptQueryObject(
                                fromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB,
                                pvObject,
                                StoreExpectedContentFlags,
                                ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL,
                                0,
                                IntPtr.Zero,
                                out contentType,
                                IntPtr.Zero,
                                out certStore,
                                IntPtr.Zero,
                                IntPtr.Zero
                                ))
                        {
                            throw Marshal.GetLastWin32Error().ToCryptographicException();
                        }

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

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

                            fixed(byte *pRawData2 = rawData)
                            {
                                CRYPTOAPI_BLOB blob2 = new CRYPTOAPI_BLOB(rawData.Length, pRawData2);

                                certStore = Interop.crypt32.PFXImportCertStore(ref blob2, password, certStoreFlags);
                                if (certStore == null || certStore.IsInvalid)
                                {
                                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                                }
                            }

                            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))
                                {
                                    CRYPTOAPI_BLOB nullBlob = new CRYPTOAPI_BLOB(0, null);
                                    if (!Interop.crypt32.CertSetCertificateContextProperty(pCertContext, CertContextPropId.CERT_CLR_DELETE_KEY_PROP_ID, CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, &nullBlob))
                                    {
                                        throw Marshal.GetLastWin32Error().ToCryptographicException();
                                    }
                                }
                            }
                        }

                        return(new StorePal(certStore));
                    }
                }
            }
        }