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); } } }
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); } } }