private static Exception TryGetKeySpecForCertificate(X509Certificate2 cert, out CryptKeySpec keySpec)
        {
            using (SafeCertContextHandle hCertContext = cert.CreateCertContextHandle())
            {
                int cbSize = 0;
                if (!Interop.Crypt32.CertGetCertificateContextProperty(hCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cbSize))
                {
                    ErrorCode errorCode = (ErrorCode)(Marshal.GetLastWin32Error());
                    keySpec = default(CryptKeySpec);
                    return(errorCode.ToCryptographicException());
                }

                byte[] pData = new byte[cbSize];
                unsafe
                {
                    fixed(byte *pvData = pData)
                    {
                        if (!Interop.Crypt32.CertGetCertificateContextProperty(hCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, pData, ref cbSize))
                        {
                            ErrorCode errorCode = (ErrorCode)(Marshal.GetLastWin32Error());
                            keySpec = default(CryptKeySpec);
                            return(errorCode.ToCryptographicException());
                        }

                        CRYPT_KEY_PROV_INFO *pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)pvData;

                        keySpec = pCryptKeyProvInfo->dwKeySpec;
                        return(null);
                    }
                }
            }
        }
        public static void DeleteKeyContainer(SafeCertContextHandle pCertContext)
        {
            if (pCertContext.IsInvalid)
            {
                return;
            }

            int  cb = 0;
            bool containsPrivateKey = Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cb);

            if (!containsPrivateKey)
            {
                return;
            }

            byte[] provInfoAsBytes = new byte[cb];
            if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, provInfoAsBytes, ref cb))
            {
                return;
            }

            unsafe
            {
                fixed(byte *pProvInfoAsBytes = provInfoAsBytes)
                {
                    CRYPT_KEY_PROV_INFO *pProvInfo = (CRYPT_KEY_PROV_INFO *)pProvInfoAsBytes;

                    string providerName     = pwszToString((IntPtr)(pProvInfo->pwszProvName));
                    string keyContainerName = pwszToString((IntPtr)(pProvInfo->pwszContainerName));

                    if (pProvInfo->dwProvType == 0)
                    {
                        // dwProvType being 0 indicates that the key is stored in CNG.
                        // dwProvType being non-zero indicates that the key is stored in CAPI.
                        try
                        {
                            using (CngKey cngKey = CngKey.Open(keyContainerName, new CngProvider(providerName)))
                            {
                                cngKey.Delete();
                            }
                        }
                        catch (CryptographicException)
                        {
                            // While leaving the file on disk is undesirable, an inability to perform this cleanup
                            // should not manifest itself to a user.
                        }
                    }
                    else
                    {
                        CryptAcquireContextFlags flags = (pProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | CryptAcquireContextFlags.CRYPT_DELETEKEYSET;
                        IntPtr hProv;
                        bool   success = Interop.cryptoapi.CryptAcquireContext(out hProv, keyContainerName, providerName, pProvInfo->dwProvType, flags);

                        // Called CryptAcquireContext solely for the side effect of deleting the key containers. When called with these flags, no actual
                        // hProv is returned (so there's nothing to clean up.)
                        Debug.Assert(hProv == IntPtr.Zero);
                    }
                }
            }
        }
예제 #3
0
        public static void DeleteKeyContainer(SafeCertContextHandle pCertContext)
        {
            if (pCertContext.IsInvalid)
            {
                return;
            }

            int  cb = 0;
            bool containsPrivateKey = Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cb);

            if (!containsPrivateKey)
            {
                return;
            }

            byte[] provInfoAsBytes = new byte[cb];
            if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, provInfoAsBytes, ref cb))
            {
                return;
            }

            unsafe
            {
                fixed(byte *pProvInfoAsBytes = provInfoAsBytes)
                {
                    CRYPT_KEY_PROV_INFO *pProvInfo = (CRYPT_KEY_PROV_INFO *)pProvInfoAsBytes;

                    // For UWP the key was opened in a CNG-only context, so it can/should be deleted via CngKey.Delete.
                    // In all other contexts, the key was loaded into CAPI, so deleting it via CryptAcquireContext is
                    // the correct action.
#if NETNATIVE
                    string providerName     = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszProvName));
                    string keyContainerName = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszContainerName));

                    try
                    {
                        using (CngKey cngKey = CngKey.Open(keyContainerName, new CngProvider(providerName)))
                        {
                            cngKey.Delete();
                        }
                    }
                    catch (CryptographicException)
                    {
                        // While leaving the file on disk is undesirable, an inability to perform this cleanup
                        // should not manifest itself to a user.
                    }
#else
                    CryptAcquireContextFlags flags = (pProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | CryptAcquireContextFlags.CRYPT_DELETEKEYSET;
                    IntPtr hProv;
                    bool   success = Interop.advapi32.CryptAcquireContext(out hProv, pProvInfo->pwszContainerName, pProvInfo->pwszProvName, pProvInfo->dwProvType, flags);

                    // Called CryptAcquireContext solely for the side effect of deleting the key containers. When called with these flags, no actual
                    // hProv is returned (so there's nothing to clean up.)
                    Debug.Assert(hProv == IntPtr.Zero);
#endif
                }
            }
        }
예제 #4
0
        //
        // Returns the private key referenced by a store certificate. Note that despite the return type being declared "CspParameters",
        // the key can actually be a CNG key. To distinguish, examine the ProviderType property. If it is 0, this key is a CNG key with
        // the various properties of CspParameters being "repurposed" into storing CNG info.
        //
        // This is a behavior this method inherits directly from the Crypt32 CRYPT_KEY_PROV_INFO semantics.
        //
        // It would have been nice not to let this ugliness escape out of this helper method. But X509Certificate2.ToString() calls this
        // method too so we cannot just change it without breaking its output.
        //
        private CspParameters GetPrivateKeyCsp()
        {
            int cbData = 0;

            if (!Interop.crypt32.CertGetCertificateContextProperty(_certContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cbData))
            {
                int dwErrorCode = Marshal.GetLastWin32Error();
                if (dwErrorCode == ErrorCode.CRYPT_E_NOT_FOUND)
                {
                    return(null);
                }
                throw dwErrorCode.ToCryptographicException();
            }

            unsafe
            {
                byte[] privateKey = new byte[cbData];
                fixed(byte *pPrivateKey = privateKey)
                {
                    if (!Interop.crypt32.CertGetCertificateContextProperty(_certContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, privateKey, ref cbData))
                    {
                        throw Marshal.GetLastWin32Error().ToCryptographicException();
                    }
                    CRYPT_KEY_PROV_INFO *pKeyProvInfo = (CRYPT_KEY_PROV_INFO *)pPrivateKey;

                    CspParameters cspParameters = new CspParameters();

                    cspParameters.ProviderName     = Marshal.PtrToStringUni((IntPtr)(pKeyProvInfo->pwszProvName));
                    cspParameters.KeyContainerName = Marshal.PtrToStringUni((IntPtr)(pKeyProvInfo->pwszContainerName));
                    cspParameters.ProviderType     = pKeyProvInfo->dwProvType;
                    cspParameters.KeyNumber        = pKeyProvInfo->dwKeySpec;
                    cspParameters.Flags            = (CspProviderFlags)((pKeyProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) == CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET ? CspProviderFlags.UseMachineKeyStore : 0);
                    return(cspParameters);
                }
            }
        }
예제 #5
0
        public static void DeleteKeyContainer(SafeCertContextHandle pCertContext)
        {
            if (pCertContext.IsInvalid)
            {
                return;
            }

            int  cb = 0;
            bool containsPrivateKey = Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cb);

            if (!containsPrivateKey)
            {
                return;
            }

            byte[] provInfoAsBytes = new byte[cb];
            if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, provInfoAsBytes, ref cb))
            {
                return;
            }

            unsafe
            {
                fixed(byte *pProvInfoAsBytes = provInfoAsBytes)
                {
                    CRYPT_KEY_PROV_INFO *    pProvInfo = (CRYPT_KEY_PROV_INFO *)pProvInfoAsBytes;
                    CryptAcquireContextFlags flags     = (pProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | CryptAcquireContextFlags.CRYPT_DELETEKEYSET;
                    IntPtr hProv;
                    bool   success = Interop.advapi32.CryptAcquireContext(out hProv, pProvInfo->pwszContainerName, pProvInfo->pwszProvName, pProvInfo->dwProvType, flags);

                    // Called CryptAcquireContext solely for the side effect of deleting the key containers. When called with these flags, no actual
                    // hProv is returned (so there's nothing to clean up.)
                    Debug.Assert(hProv == IntPtr.Zero);
                }
            }
        }
예제 #6
0
 internal static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, CRYPT_KEY_PROV_INFO *pvData);
예제 #7
0
 public static extern unsafe bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, [In] CRYPT_KEY_PROV_INFO *pvData);