Exemple #1
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();
            }
        }
        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();
            }
        }