예제 #1
0
        // this method maps a X509KeyStorageFlags enum to a combination of crypto API flags
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            PfxCertStoreFlags dwFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
            {
                dwFlags |= PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP;
            }

            return(dwFlags);
        }
예제 #2
0
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            if ((keyStorageFlags & X509Certificate.KeyStorageFlagsAll) != keyStorageFlags)
            {
                throw new ArgumentException(SR.Argument_InvalidFlag, nameof(keyStorageFlags));
            }

            PfxCertStoreFlags pfxCertStoreFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            // If a user is asking for an Ephemeral key they should be willing to test their code to find out
            // that it will no longer import into CAPI. This solves problems of legacy CSPs being
            // difficult to do SHA-2 RSA signatures with, simplifies the story for UWP, and reduces the
            // complexity of pointer interpretation.
            if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
                pfxCertStoreFlags |= PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP; }
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            if ((keyStorageFlags & (X509KeyStorageFlags) ~0x1F) != 0)
            {
                throw new ArgumentException(SR.Argument_InvalidFlag, "keyStorageFlags");
            }

            PfxCertStoreFlags pfxCertStoreFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            return(pfxCertStoreFlags);
        }
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            if ((keyStorageFlags & X509Certificate.KeyStorageFlagsAll) != keyStorageFlags)
            {
                throw new ArgumentException(SR.Argument_InvalidFlag, nameof(keyStorageFlags));
            }

            PfxCertStoreFlags pfxCertStoreFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            // If a user is asking for an Ephemeral key they should be willing to test their code to find out
            // that it will no longer import into CAPI. This solves problems of legacy CSPs being
            // difficult to do SHA-2 RSA signatures with, simplifies the story for UWP, and reduces the
            // complexity of pointer interpretation.
            if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP;
            }

            // In the full .NET Framework loading a PFX then adding the key to the Windows Certificate Store would
            // enable a native application compiled against CAPI to find that private key and interoperate with it.
            //
            // For CoreFX this behavior is being retained.
            //
            // For .NET Native (UWP) the API used to delete the private key (if it wasn't added to a store) is not
            // allowed to be called if the key is stored in CAPI.  So for UWP force the key to be stored in the
            // CNG Key Storage Provider, then deleting the key with CngKey.Delete will clean up the file on disk, too.
#if NETNATIVE
            pfxCertStoreFlags |= PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP;
#endif

            return(pfxCertStoreFlags);
        }
예제 #5
0
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            if ((keyStorageFlags & (X509KeyStorageFlags) ~0x1F) != 0)
            {
                throw new ArgumentException(SR.Argument_InvalidFlag, "keyStorageFlags");
            }

            PfxCertStoreFlags pfxCertStoreFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                pfxCertStoreFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            // In the full .NET Framework loading a PFX then adding the key to the Windows Certificate Store would
            // enable a native application compiled against CAPI to find that private key and interoperate with it.
            //
            // For CoreFX this behavior is being retained.
            //
            // For .NET Native (UWP) the API used to delete the private key (if it wasn't added to a store) is not
            // allowed to be called if the key is stored in CAPI.  So for UWP force the key to be stored in the
            // CNG Key Storage Provider, then deleting the key with CngKey.Delete will clean up the file on disk, too.
#if NETNATIVE
            pfxCertStoreFlags |= PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP;
#endif

            return(pfxCertStoreFlags);
        }
예제 #6
0
        // this method maps a X509KeyStorageFlags enum to a combination of crypto API flags
        private static PfxCertStoreFlags MapKeyStorageFlags(X509KeyStorageFlags keyStorageFlags)
        {
            PfxCertStoreFlags dwFlags = 0;

            if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_USER_KEYSET;
            }
            else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_MACHINE_KEYSET;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected)
            {
                dwFlags |= PfxCertStoreFlags.CRYPT_USER_PROTECTED;
            }

            if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
            {
                dwFlags |= PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP;
            }

            // begin: gost
            // Allows to import pfx without csp windows
            if ((keyStorageFlags & X509KeyStorageFlags.CspNoPersistKeySet) == X509KeyStorageFlags.CspNoPersistKeySet)
            {
                dwFlags |= PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | PfxCertStoreFlags.CRYPT_EXPORTABLE;
            }
            // end: gost

            return(dwFlags);
        }
예제 #7
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));
                    }
                }
            }
        }
예제 #8
0
 public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);
예제 #9
0
        private static ICertificatePal FromBlobOrFile(byte[] rawData, String fileName, String password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(rawData != null || fileName != 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();
                }
            }
        }
예제 #10
0
        private static SafeCertContextHandle FilterPFXStore(byte[] rawData, String password, PfxCertStoreFlags pfxCertStoreFlags)
        {
            SafeCertStoreHandle hStore;

            unsafe
            {
                fixed(byte *pbRawData = rawData)
                {
                    CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pbRawData);

                    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.
                            SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext);
                        }
                        else
                        {
                            // Found our first cert that has a private key. Set him 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)
                        {
                            pCertContext = pEnumContext.Duplicate(); // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key.
                        }
                    }
                }

                if (pCertContext.IsInvalid)
                {
                    // For compat, setting "hr" to ERROR_INVALID_PARAMETER even though ERROR_INVALID_PARAMETER is not actually an HRESULT.
                    throw ErrorCode.ERROR_INVALID_PARAMETER.ToCryptographicException();
                }

                return(pCertContext);
            }
            finally
            {
                hStore.Dispose();
            }
        }
        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 deleteKeyContainer             = false;

            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 = Interop.CPError.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);

                        // 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 |
                            // begin: gost
                            X509KeyStorageFlags.CspNoPersistKeySet;
                        // end gost

                        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();
                }
            }
        }
예제 #12
0
 public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, String szPassword, PfxCertStoreFlags dwFlags);
예제 #13
0
        private static SafeCertContextHandle FilterPFXStore(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            PfxCertStoreFlags pfxCertStoreFlags)
        {
            SafeCertStoreHandle hStore;

            unsafe
            {
                fixed(byte *pbRawData = rawData)
                {
                    CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pbRawData);

                    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();
            }
        }
예제 #14
0
        private static StorePal FromBlobOrFile(byte[] rawData, String fileName, String password, X509KeyStorageFlags keyStorageFlags)
        {
            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 new CryptographicException(Marshal.GetLastWin32Error());
                        }

                        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 new CryptographicException(Marshal.GetLastWin32Error());
                                }
                            }
                        }


                        if (!persistKeySet)
                        {
                            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_DELETE_KEYSET_PROP_ID, CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, &nullBlob))
                                {
                                    throw new CryptographicException(Marshal.GetLastWin32Error());
                                }
                            }
                        }

                        return(new StorePal(certStore));
                    }
                }
            }
        }
예제 #15
0
 public static partial SafeCertStoreHandle PFXImportCertStore(ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);
예제 #16
0
        private static SafeCertContextHandle FilterPFXStore(byte[] rawData, string password, PfxCertStoreFlags pfxCertStoreFlags)
        {
            SafeCertStoreHandle hStore;
            unsafe
            {
                fixed (byte* pbRawData = rawData)
                {
                    CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pbRawData);
                    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.
                            SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext);
                        }
                        else
                        {
                            // Found our first cert that has a private key. Set him 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)
                            pCertContext = pEnumContext.Duplicate(); // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key.
                    }
                }

                if (pCertContext.IsInvalid)
                {
                    // For compat, setting "hr" to ERROR_INVALID_PARAMETER even though ERROR_INVALID_PARAMETER is not actually an HRESULT.
                    throw ErrorCode.ERROR_INVALID_PARAMETER.ToCryptographicException();
                }

                return pCertContext;
            }
            finally
            {
                hStore.Dispose();
            }
        }
예제 #17
0
 internal static partial SafeCertStoreHandle PFXImportCertStore(ref DATA_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);