public static SafeNCryptKeyHandle AcquireCngPrivateKey(
            SafeCertContextHandle certificateContext)
        {
            var freeKey = true;
            SafeNCryptKeyHandle privateKey = null;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                if (!NativeMethods.Crypt32.CryptAcquireCertificatePrivateKey(
                        certificateContext,
                        NativeMethods.Crypt32.AcquireCertificateKeyOptions.AcquireOnlyNCryptKeys,
                        IntPtr.Zero,
                        out privateKey,
                        out _,
                        out freeKey))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                return(privateKey);
            }
            finally
            {
                // If we're not supposed to release they key handle, then we need to
                // bump the reference count on the safe handle to correspond to the
                // reference that Windows is holding on to.

                // This will prevent the CLR from freeing the object handle.
                //
                // This is certainly not the ideal way to solve this problem - it
                // would be better for SafeNCryptKeyHandle to maintain an internal
                // bool field that we could toggle here and have that suppress the
                // release when the CLR calls the ReleaseHandle override.
                // However, that field does not currently exist, so we'll use this
                // hack instead.
                if (privateKey != null
                    &&
                    !freeKey)
                {
                    var addedRef = false;
                    privateKey.DangerousAddRef(ref addedRef);
                }
            }
        }
        private static SafeNCryptKeyHandle TryAcquireCngPrivateKey(SafeCertContextHandle certificateContext)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid,
                         "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            bool freeKey = true;
            SafeNCryptKeyHandle privateKey = null;

            try
            {
                int keySpec = 0;
                if (!Interop.crypt32.CryptAcquireCertificatePrivateKey(
                        certificateContext,
                        CryptAcquireFlags.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
                        IntPtr.Zero,
                        out privateKey,
                        out keySpec,
                        out freeKey))
                {
                    int dwErrorCode = Marshal.GetLastWin32Error();
                    return(null);
                }

                return(privateKey);
            }
            finally
            {
                // If we're not supposed to release the key handle, then we need to bump the reference count
                // on the safe handle to correspond to the reference that Windows is holding on to.  This will
                // prevent the CLR from freeing the object handle.
                //
                // This is certainly not the ideal way to solve this problem - it would be better for
                // SafeNCryptKeyHandle to maintain an internal bool field that we could toggle here and
                // have that suppress the release when the CLR calls the ReleaseHandle override.  However, that
                // field does not currently exist, so we'll use this hack instead.
                if (privateKey != null && !freeKey)
                {
                    bool addedRef = false;
                    privateKey.DangerousAddRef(ref addedRef);
                }
            }
        }
Beispiel #3
0
        internal static SafeNCryptKeyHandle AcquireCngPrivateKey(SafeCertContextHandle certificateContext)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid, "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            bool freeKey = true;
            SafeNCryptKeyHandle privateKey = null;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                int keySpec = 0;

                if (!UnsafeNativeMethods.CryptAcquireCertificatePrivateKey(certificateContext,
                                                                           AcquireCertificateKeyOptions.AcquireOnlyNCryptKeys,
                                                                           IntPtr.Zero,
                                                                           out privateKey,
                                                                           out keySpec,
                                                                           out freeKey))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                return(privateKey);
            }
            finally
            {
                // If we're not supposed to release they key handle, then we need to bump the reference count
                // on the safe handle to correspond to the reference that Windows is holding on to.  This will
                // prevent the CLR from freeing the object handle.
                //
                // This is certainly not the ideal way to solve this problem - it would be better for
                // SafeNCryptKeyHandle to maintain an internal bool field that we could toggle here and
                // have that suppress the release when the CLR calls the ReleaseHandle override.  However, that
                // field does not currently exist, so we'll use this hack instead.
                if (privateKey != null && !freeKey)
                {
                    bool addedRef = false;
                    privateKey.DangerousAddRef(ref addedRef);
                }
            }
        }