1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 // 5 // Presharp uses the c# pragma mechanism to supress its warnings. 6 // These are not recognised by the base compiler so we need to explictly 7 // disable the following warnings. See http://winweb/cse/Tools/PREsharp/userguide/default.asp 8 // for details. 9 // 10 #pragma warning disable 1634, 1691 // unknown message, unknown pragma 11 12 namespace System.IdentityModel.Selectors 13 { 14 using System; 15 using System.Runtime.InteropServices; 16 using System.Threading; 17 using System.Security; 18 using System.Runtime.ConstrainedExecution; 19 using System.Runtime.CompilerServices; 20 using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; 21 22 23 // 24 // For common & resources 25 // 26 using Microsoft.InfoCards; 27 28 // 29 // Summary: 30 // Wraps and manages the lifetime of a native crypto handle passed back from the native InfoCard API. 31 // 32 internal abstract class CryptoHandle : IDisposable 33 { 34 bool m_isDisposed; 35 InternalRefCountedHandle m_internalHandle; 36 37 // 38 // Summary: 39 // Creates a new CryptoHandle. ParamType has information as to what 40 // nativeParameters has to be marshaled into. 41 // CryptoHandle(InternalRefCountedHandle nativeHandle, DateTime expiration, IntPtr nativeParameters, Type paramType)42 protected CryptoHandle(InternalRefCountedHandle nativeHandle, DateTime expiration, IntPtr nativeParameters, Type paramType) 43 { 44 m_internalHandle = nativeHandle; 45 46 m_internalHandle.Initialize(expiration, Marshal.PtrToStructure(nativeParameters, paramType)); 47 } 48 49 // 50 // Summary: 51 // This constructor creates a new CryptoHandle instance with the same InternalRefCountedHandle and adds 52 // a ref count to that InternalRefCountedHandle. 53 // CryptoHandle(InternalRefCountedHandle internalHandle)54 protected CryptoHandle(InternalRefCountedHandle internalHandle) 55 { 56 m_internalHandle = internalHandle; 57 m_internalHandle.AddRef(); 58 } 59 60 public InternalRefCountedHandle InternalHandle 61 { 62 get 63 { 64 ThrowIfDisposed(); 65 return m_internalHandle; 66 } 67 } 68 69 70 71 public DateTime Expiration 72 { 73 get 74 { 75 ThrowIfDisposed(); 76 return m_internalHandle.Expiration; 77 } 78 } 79 80 public object Parameters 81 { 82 get 83 { 84 ThrowIfDisposed(); 85 return m_internalHandle.Parameters; 86 } 87 } 88 89 // 90 // Summary: 91 // Creates a new CryptoHandle with same InternalRefCountedCryptoHandle. 92 // Duplicate()93 public CryptoHandle Duplicate() 94 { 95 ThrowIfDisposed(); 96 return OnDuplicate(); 97 } 98 99 100 // 101 // Summary: 102 // Allows subclasses to create a duplicate of their particular class. 103 // OnDuplicate()104 protected abstract CryptoHandle OnDuplicate(); 105 ThrowIfDisposed()106 protected void ThrowIfDisposed() 107 { 108 if (m_isDisposed) 109 { 110 throw IDT.ThrowHelperError(new ObjectDisposedException(SR.GetString(SR.ClientCryptoSessionDisposed))); 111 } 112 } 113 Dispose()114 public void Dispose() 115 { 116 if (m_isDisposed) 117 { 118 return; 119 } 120 121 m_internalHandle.Release(); 122 m_internalHandle = null; 123 m_isDisposed = true; 124 } 125 126 // 127 // Summary: 128 // Given a pointer to a native cryptosession this method creates the appropriate CryptoHandle type. 129 // Create(InternalRefCountedHandle nativeHandle)130 static internal CryptoHandle Create(InternalRefCountedHandle nativeHandle) 131 { 132 CryptoHandle handle = null; 133 134 bool mustRelease = false; 135 RuntimeHelpers.PrepareConstrainedRegions(); 136 try 137 { 138 nativeHandle.DangerousAddRef(ref mustRelease); 139 RpcInfoCardCryptoHandle hCrypto = 140 (RpcInfoCardCryptoHandle)Marshal.PtrToStructure(nativeHandle.DangerousGetHandle(), 141 typeof(RpcInfoCardCryptoHandle)); 142 DateTime expiration = DateTime.FromFileTimeUtc(hCrypto.expiration); 143 144 switch (hCrypto.type) 145 { 146 case RpcInfoCardCryptoHandle.HandleType.Asymmetric: 147 handle = new AsymmetricCryptoHandle(nativeHandle, expiration, hCrypto.cryptoParameters); 148 break; 149 case RpcInfoCardCryptoHandle.HandleType.Symmetric: 150 handle = new SymmetricCryptoHandle(nativeHandle, expiration, hCrypto.cryptoParameters); 151 break; 152 case RpcInfoCardCryptoHandle.HandleType.Transform: 153 handle = new TransformCryptoHandle(nativeHandle, expiration, hCrypto.cryptoParameters); 154 break; 155 case RpcInfoCardCryptoHandle.HandleType.Hash: 156 handle = new HashCryptoHandle(nativeHandle, expiration, hCrypto.cryptoParameters); 157 break; 158 default: 159 IDT.DebugAssert(false, "Invalid crypto operation type"); 160 throw IDT.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.GeneralExceptionMessage))); 161 } 162 163 return handle; 164 165 } 166 finally 167 { 168 if (mustRelease) 169 { 170 nativeHandle.DangerousRelease(); 171 } 172 } 173 } 174 175 176 } 177 178 // 179 // Summary: 180 // This class manages the lifetime of a native crypto handle through ref counts. Any number of CryptoHandles 181 // may refer to a single InternalRefCountedHandle, but once they are all disposed this object will dispose 182 // itself as well. 183 // 184 internal class InternalRefCountedHandle : SafeHandle 185 { 186 int m_refcount = 0; 187 DateTime m_expiration; 188 object m_parameters = null; 189 190 [DllImport("infocardapi.dll", 191 EntryPoint = "CloseCryptoHandle", 192 CharSet = CharSet.Unicode, 193 CallingConvention = CallingConvention.StdCall, 194 ExactSpelling = true, 195 SetLastError = true)] 196 [SuppressUnmanagedCodeSecurity] 197 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] CloseCryptoHandle([In] IntPtr hKey)198 private static extern bool CloseCryptoHandle([In] IntPtr hKey); 199 InternalRefCountedHandle()200 private InternalRefCountedHandle() 201 : base(IntPtr.Zero, true) 202 { 203 m_refcount = 1; 204 205 } 206 Initialize(DateTime expiration, object parameters)207 public void Initialize(DateTime expiration, object parameters) 208 { 209 m_expiration = expiration; 210 m_parameters = parameters; 211 } 212 213 214 // 215 // Summary: 216 // The deserialized parameters specific to a particular type of CryptoHandle. 217 // 218 public object Parameters 219 { 220 get 221 { 222 ThrowIfInvalid(); 223 return m_parameters; 224 } 225 } 226 227 // 228 // Summary: 229 // The expiration of this CryptoHandle 230 // 231 public DateTime Expiration 232 { 233 get 234 { 235 ThrowIfInvalid(); 236 return m_expiration; 237 } 238 } 239 AddRef()240 public void AddRef() 241 { 242 ThrowIfInvalid(); 243 Interlocked.Increment(ref m_refcount); 244 } 245 Release()246 public void Release() 247 { 248 ThrowIfInvalid(); 249 int refcount = Interlocked.Decrement(ref m_refcount); 250 if (0 == refcount) 251 { 252 Dispose(); 253 } 254 } 255 ThrowIfInvalid()256 private void ThrowIfInvalid() 257 { 258 if (IsInvalid) 259 { 260 throw IDT.ThrowHelperError(new ObjectDisposedException("InternalRefCountedHandle")); 261 } 262 } 263 public override bool IsInvalid 264 { 265 get 266 { 267 return (IntPtr.Zero == base.handle); 268 } 269 } 270 271 ReleaseHandle()272 protected override bool ReleaseHandle() 273 { 274 #pragma warning suppress 56523 275 return CloseCryptoHandle(base.handle); 276 } 277 278 } 279 } 280