1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 namespace System.IdentityModel 6 { 7 using System.ComponentModel; 8 using System.Runtime.InteropServices; 9 using System.Runtime.CompilerServices; 10 using System.Runtime.ConstrainedExecution; 11 using System.Security.Cryptography; 12 using System.ServiceModel.Diagnostics; 13 using Microsoft.Win32.SafeHandles; 14 15 class SafeProvHandle : SafeHandleZeroOrMinusOneIsInvalid 16 { SafeProvHandle()17 SafeProvHandle() : base(true) { } 18 19 // 0 is an Invalid Handle SafeProvHandle(IntPtr handle)20 SafeProvHandle(IntPtr handle) 21 : base(true) 22 { 23 DiagnosticUtility.DebugAssert(handle == IntPtr.Zero, "SafeProvHandle constructor can only be called with IntPtr.Zero."); 24 SetHandle(handle); 25 } 26 27 internal static SafeProvHandle InvalidHandle 28 { 29 get { return new SafeProvHandle(IntPtr.Zero); } 30 } 31 ReleaseHandle()32 protected override bool ReleaseHandle() 33 { 34 // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call. 35 #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails. 36 return NativeMethods.CryptReleaseContext(handle, 0); 37 } 38 } 39 40 class SafeKeyHandle : SafeHandleZeroOrMinusOneIsInvalid 41 { 42 SafeProvHandle provHandle = null; 43 SafeKeyHandle()44 SafeKeyHandle() : base(true) { } 45 46 // 0 is an Invalid Handle SafeKeyHandle(IntPtr handle)47 SafeKeyHandle(IntPtr handle) 48 : base(true) 49 { 50 DiagnosticUtility.DebugAssert(handle == IntPtr.Zero, "SafeKeyHandle constructor can only be called with IntPtr.Zero."); 51 SetHandle(handle); 52 } 53 54 internal static SafeKeyHandle InvalidHandle 55 { 56 get { return new SafeKeyHandle(IntPtr.Zero); } 57 } 58 ReleaseHandle()59 protected override bool ReleaseHandle() 60 { 61 // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call. 62 #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails. 63 bool ret = NativeMethods.CryptDestroyKey(handle); 64 if (this.provHandle != null) 65 { 66 this.provHandle.DangerousRelease(); 67 this.provHandle = null; 68 } 69 return ret; 70 } 71 SafeCryptImportKey(SafeProvHandle provHandle, void* pbDataPtr, int cbData)72 internal static unsafe SafeKeyHandle SafeCryptImportKey(SafeProvHandle provHandle, void* pbDataPtr, int cbData) 73 { 74 bool b = false; 75 int err = 0; 76 SafeKeyHandle keyHandle = null; 77 RuntimeHelpers.PrepareConstrainedRegions(); 78 try 79 { 80 provHandle.DangerousAddRef(ref b); 81 } 82 catch (Exception e) 83 { 84 if (System.Runtime.Fx.IsFatal(e)) 85 throw; 86 87 if (b) 88 { 89 provHandle.DangerousRelease(); 90 b = false; 91 } 92 if (!(e is ObjectDisposedException)) 93 throw; 94 } 95 finally 96 { 97 if (b) 98 { 99 b = NativeMethods.CryptImportKey(provHandle, pbDataPtr, (uint)cbData, IntPtr.Zero, 0, out keyHandle); 100 if (!b) 101 { 102 err = Marshal.GetLastWin32Error(); 103 provHandle.DangerousRelease(); 104 } 105 else 106 { 107 // Take ownership of AddRef. Will Release at Close. 108 keyHandle.provHandle = provHandle; 109 } 110 } 111 } 112 113 if (!b) 114 { 115 Utility.CloseInvalidOutSafeHandle(keyHandle); 116 string reason = (err != 0) ? new Win32Exception(err).Message : String.Empty; 117 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.AESCryptImportKeyFailed, reason))); 118 } 119 return keyHandle; 120 } 121 } 122 } 123