Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.IdentityModel / System / IdentityModel / CryptoApi.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.IdentityModel
6 {
7     using Microsoft.Win32.SafeHandles;
8     using System.ComponentModel;
9     using System.Diagnostics;
10     using System.Runtime.InteropServices;
11     using System.Runtime.CompilerServices;
12     using System.Runtime.Versioning;
13     using System.Runtime.ConstrainedExecution;
14     using System.Security;
15     using System.Security.Cryptography;
16     using System.Security.Cryptography.X509Certificates;
17
18     using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
19
20     [SuppressUnmanagedCodeSecurity]
21     static class CAPI
22     {
23         internal const string CRYPT32 = "crypt32.dll";
24         internal const string BCRYPT = "bcrypt.dll";
25         internal const string SubjectKeyIdentifierOid = "2.5.29.14";
26
27         internal const int S_OK = 0;
28         internal const int S_FALSE = 1;
29
30         internal const string szOID_CRL_DIST_POINTS = "2.5.29.31";
31         internal const string szOID_AUTHORITY_INFO_ACCESS = "1.3.6.1.5.5.7.1.1";
32
33         //internal const uint CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001;
34         //internal const uint CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002;
35         //internal const uint CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004;
36         //internal const uint CERT_STORE_DELETE_FLAG = 0x00000010;
37         //internal const uint CERT_STORE_SHARE_STORE_FLAG = 0x00000040;
38         //internal const uint CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080;
39         //internal const uint CERT_STORE_MANIFOLD_FLAG = 0x00000100;
40         internal const uint CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200;
41         //internal const uint CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400;
42         //internal const uint CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800;
43         internal const uint CERT_STORE_READONLY_FLAG = 0x00008000;
44         internal const uint CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000;
45         internal const uint CERT_STORE_CREATE_NEW_FLAG = 0x00002000;
46         internal const uint CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000;
47
48         internal const uint CERT_STORE_ADD_ALWAYS = 4;
49         internal const uint CERT_CHAIN_POLICY_BASE = 1;
50         internal const uint CERT_CHAIN_POLICY_NT_AUTH = 6;
51
52         internal const uint X509_ASN_ENCODING = 0x00000001;
53         internal const uint PKCS_7_ASN_ENCODING = 0x00010000;
54         internal const uint CERT_STORE_PROV_MEMORY = 2;
55         internal const uint CERT_STORE_PROV_SYSTEM = 10;
56         internal const uint CERT_SYSTEM_STORE_CURRENT_USER_ID = 1;
57         internal const uint CERT_SYSTEM_STORE_LOCAL_MACHINE_ID = 2;
58         internal const uint CERT_SYSTEM_STORE_LOCATION_SHIFT = 16;
59
60         internal const uint CERT_SYSTEM_STORE_CURRENT_USER = ((int)CERT_SYSTEM_STORE_CURRENT_USER_ID << (int)CERT_SYSTEM_STORE_LOCATION_SHIFT);
61         internal const uint CERT_SYSTEM_STORE_LOCAL_MACHINE = ((int)CERT_SYSTEM_STORE_LOCAL_MACHINE_ID << (int)CERT_SYSTEM_STORE_LOCATION_SHIFT);
62
63         //internal const uint CERT_INFO_VERSION_FLAG = 1;
64         //internal const uint CERT_INFO_SERIAL_NUMBER_FLAG = 2;
65         //internal const uint CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3;
66         internal const uint CERT_INFO_ISSUER_FLAG = 4;
67         //internal const uint CERT_INFO_NOT_BEFORE_FLAG = 5;
68         //internal const uint CERT_INFO_NOT_AFTER_FLAG = 6;
69         internal const uint CERT_INFO_SUBJECT_FLAG = 7;
70         //internal const uint CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8;
71         //internal const uint CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9;
72         //internal const uint CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10;
73         //internal const uint CERT_INFO_EXTENSION_FLAG = 11;
74
75         //internal const uint CERT_COMPARE_MASK = 0xFFFF;
76         internal const uint CERT_COMPARE_SHIFT = 16;
77         internal const uint CERT_COMPARE_ANY = 0;
78         internal const uint CERT_COMPARE_SHA1_HASH = 1;
79         //internal const uint CERT_COMPARE_NAME = 2;
80         //internal const uint CERT_COMPARE_ATTR = 3;
81         //internal const uint CERT_COMPARE_MD5_HASH = 4;
82         //internal const uint CERT_COMPARE_PROPERTY = 5;
83         //internal const uint CERT_COMPARE_PUBLIC_KEY = 6;
84         //internal const uint CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH;
85         internal const uint CERT_COMPARE_NAME_STR_A = 7;
86         internal const uint CERT_COMPARE_NAME_STR_W = 8;
87         //internal const uint CERT_COMPARE_KEY_SPEC = 9;
88         //internal const uint CERT_COMPARE_ENHKEY_USAGE = 10;
89         //internal const uint CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE;
90         //internal const uint CERT_COMPARE_SUBJECT_CERT = 11;
91         //internal const uint CERT_COMPARE_ISSUER_OF = 12;
92         //internal const uint CERT_COMPARE_EXISTING = 13;
93         //internal const uint CERT_COMPARE_SIGNATURE_HASH = 14;
94         //internal const uint CERT_COMPARE_KEY_IDENTIFIER = 15;
95         //internal const uint CERT_COMPARE_CERT_ID = 16;
96         //internal const uint CERT_COMPARE_CROSS_CERT_DIST_POINTS = 17;
97         //internal const uint CERT_COMPARE_PUBKEY_MD5_HASH = 18;
98
99         internal const uint CERT_FIND_ANY = ((int)CERT_COMPARE_ANY << (int)CERT_COMPARE_SHIFT);
100         internal const uint CERT_FIND_SHA1_HASH = ((int)CERT_COMPARE_SHA1_HASH << (int)CERT_COMPARE_SHIFT);
101         //internal const uint CERT_FIND_MD5_HASH = ((int)CERT_COMPARE_MD5_HASH << (int)CERT_COMPARE_SHIFT);
102         //internal const uint CERT_FIND_SIGNATURE_HASH = ((int)CERT_COMPARE_SIGNATURE_HASH << (int)CERT_COMPARE_SHIFT);
103         //internal const uint CERT_FIND_KEY_IDENTIFIER = ((int)CERT_COMPARE_KEY_IDENTIFIER << (int)CERT_COMPARE_SHIFT);
104         internal const uint CERT_FIND_HASH = CERT_FIND_SHA1_HASH;
105         //internal const uint CERT_FIND_PROPERTY = ((int)CERT_COMPARE_PROPERTY << (int)CERT_COMPARE_SHIFT);
106         //internal const uint CERT_FIND_PUBLIC_KEY = ((int)CERT_COMPARE_PUBLIC_KEY << (int)CERT_COMPARE_SHIFT);
107         //internal const uint CERT_FIND_SUBJECT_NAME = ((int)CERT_COMPARE_NAME << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_SUBJECT_FLAG);
108         //internal const uint CERT_FIND_SUBJECT_ATTR = ((int)CERT_COMPARE_ATTR << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_SUBJECT_FLAG);
109         //internal const uint CERT_FIND_ISSUER_NAME = ((int)CERT_COMPARE_NAME << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_ISSUER_FLAG);
110         //internal const uint CERT_FIND_ISSUER_ATTR = ((int)CERT_COMPARE_ATTR << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_ISSUER_FLAG);
111         internal const uint CERT_FIND_SUBJECT_STR_A = ((int)CERT_COMPARE_NAME_STR_A << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_SUBJECT_FLAG);
112         internal const uint CERT_FIND_SUBJECT_STR_W = ((int)CERT_COMPARE_NAME_STR_W << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_SUBJECT_FLAG);
113         internal const uint CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W;
114         internal const uint CERT_FIND_ISSUER_STR_A = ((int)CERT_COMPARE_NAME_STR_A << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_ISSUER_FLAG);
115         internal const uint CERT_FIND_ISSUER_STR_W = ((int)CERT_COMPARE_NAME_STR_W << (int)CERT_COMPARE_SHIFT | (int)CERT_INFO_ISSUER_FLAG);
116         internal const uint CERT_FIND_ISSUER_STR = CERT_FIND_ISSUER_STR_W;
117         //internal const uint CERT_FIND_KEY_SPEC = ((int)CERT_COMPARE_KEY_SPEC << (int)CERT_COMPARE_SHIFT);
118         //internal const uint CERT_FIND_ENHKEY_USAGE = ((int)CERT_COMPARE_ENHKEY_USAGE << (int)CERT_COMPARE_SHIFT);
119         //internal const uint CERT_FIND_CTL_USAGE = CERT_FIND_ENHKEY_USAGE;
120         //internal const uint CERT_FIND_SUBJECT_CERT = ((int)CERT_COMPARE_SUBJECT_CERT << (int)CERT_COMPARE_SHIFT);
121         //internal const uint CERT_FIND_ISSUER_OF = ((int)CERT_COMPARE_ISSUER_OF << (int)CERT_COMPARE_SHIFT);
122         //internal const uint CERT_FIND_EXISTING = ((int)CERT_COMPARE_EXISTING << (int)CERT_COMPARE_SHIFT);
123         //internal const uint CERT_FIND_CERT_ID = ((int)CERT_COMPARE_CERT_ID << (int)CERT_COMPARE_SHIFT);
124         //internal const uint CERT_FIND_CROSS_CERT_DIST_POINTS = ((int)CERT_COMPARE_CROSS_CERT_DIST_POINTS << (int)CERT_COMPARE_SHIFT);
125         //internal const uint CERT_FIND_PUBKEY_MD5_HASH = ((int)CERT_COMPARE_PUBKEY_MD5_HASH << (int)CERT_COMPARE_SHIFT);
126
127         // Common chain policy flags.
128         internal const uint CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000;
129         internal const uint CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000;
130         internal const uint CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x40000000;
131         internal const uint CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY = 0x80000000;
132         internal const uint CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT = 0x08000000;
133
134         // Chain verification flag (not available in X509VerificationFlags).
135         internal const uint CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG = 0x00001000;
136
137
138         // Default usage match type is AND with value zero
139         internal const uint USAGE_MATCH_TYPE_AND = 0x00000000;
140         internal const uint USAGE_MATCH_TYPE_OR = 0x00000001;
141
142         // CertGetCertificateChain chain engine handles.
143         internal const uint HCCE_CURRENT_USER = 0x0;
144         internal const uint HCCE_LOCAL_MACHINE = 0x1;
145
146         // Vista Peer Trust
147         internal const uint CERT_TRUST_IS_PEER_TRUSTED = 0x00000800;
148
149         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
150         internal struct CERT_CONTEXT
151         {
152             internal uint dwCertEncodingType;
153             internal IntPtr pbCertEncoded;
154             internal uint cbCertEncoded;
155             internal IntPtr pCertInfo;
156             internal IntPtr hCertStore;
157         };
158
159
160         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
161         internal struct CRYPTOAPI_BLOB
162         {
163             internal uint cbData;
164             internal IntPtr pbData;
165
166             static internal int Size = Marshal.SizeOf(typeof(CRYPTOAPI_BLOB));
167         }
168
169         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
170         internal struct CERT_ENHKEY_USAGE
171         {
172             internal uint cUsageIdentifier;
173             internal IntPtr rgpszUsageIdentifier; // LPSTR*
174         }
175
176         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
177         internal struct CERT_USAGE_MATCH
178         {
179             internal uint dwType;
180             internal CERT_ENHKEY_USAGE Usage;
181         }
182
183         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
184         internal struct CERT_CHAIN_PARA
185         {
186             internal uint cbSize;
187             internal CERT_USAGE_MATCH RequestedUsage;
188             internal CERT_USAGE_MATCH RequestedIssuancePolicy;
189             internal uint dwUrlRetrievalTimeout; // milliseconds
190             internal bool fCheckRevocationFreshnessTime;
191             internal uint dwRevocationFreshnessTime;
192         }
193
194         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
195         internal struct CERT_CHAIN_POLICY_PARA
196         {
197             internal CERT_CHAIN_POLICY_PARA(int size)
198             {
199                 cbSize = (uint)size;
200                 dwFlags = 0;
201                 pvExtraPolicyPara = IntPtr.Zero;
202             }
203             internal uint cbSize;
204             internal uint dwFlags;
205             internal IntPtr pvExtraPolicyPara;
206         }
207
208         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
209         internal struct CERT_CHAIN_POLICY_STATUS
210         {
211             internal CERT_CHAIN_POLICY_STATUS(int size)
212             {
213                 cbSize = (uint)size;
214                 dwError = 0;
215                 lChainIndex = IntPtr.Zero;
216                 lElementIndex = IntPtr.Zero;
217                 pvExtraPolicyStatus = IntPtr.Zero;
218             }
219             internal uint cbSize;
220             internal uint dwError;
221             internal IntPtr lChainIndex;
222             internal IntPtr lElementIndex;
223             internal IntPtr pvExtraPolicyStatus;
224         }
225
226         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
227         internal struct CERT_CHAIN_CONTEXT
228         {
229             internal CERT_CHAIN_CONTEXT(int size)
230             {
231                 cbSize = (uint)size;
232                 dwErrorStatus = 0;
233                 dwInfoStatus = 0;
234                 cChain = 0;
235                 rgpChain = IntPtr.Zero;
236                 cLowerQualityChainContext = 0;
237                 rgpLowerQualityChainContext = IntPtr.Zero;
238                 fHasRevocationFreshnessTime = 0;
239                 dwRevocationFreshnessTime = 0;
240             }
241             internal uint cbSize;
242             internal uint dwErrorStatus;   // serialized CERT_TRUST_STATUS
243             internal uint dwInfoStatus;    // serialized CERT_TRUST_STATUS
244             internal uint cChain;
245             internal IntPtr rgpChain;                    // PCERT_SIMPLE_CHAIN*
246             internal uint cLowerQualityChainContext;
247             internal IntPtr rgpLowerQualityChainContext; // PCCERT_CHAIN_CONTEXT*
248             internal uint fHasRevocationFreshnessTime; // Note that we declare the field as a uint here since we are manipulating 
249             // the structure manually and a bool is only 1 byte in the managed world.
250             internal uint dwRevocationFreshnessTime;   // seconds
251         }
252
253         [DllImport(CAPI.CRYPT32, CharSet = CharSet.Unicode, SetLastError = true)]
254         internal static extern SafeCertContextHandle CertCreateCertificateContext(
255             [In] uint dwCertEncodingType,
256             [In] IntPtr pbCertEncoded,
257             [In] uint cbCertEncoded
258             );
259
260         // A new store is created if one did not exist. The function fails if the store already exists if dwFlags is set to CERT_STORE_CREATE_NEW_FLAG .
261         
262         [DllImport(CAPI.CRYPT32, CharSet = CharSet.Unicode, SetLastError = true)]
263         [ResourceExposure(ResourceScope.None)]
264         internal static extern SafeCertStoreHandle CertOpenStore(
265             [In] IntPtr lpszStoreProvider,
266             [In] uint dwMsgAndCertEncodingType,
267             [In] IntPtr hCryptProv,
268             [In] uint dwFlags,
269             [In] string pvPara // we want this always as a Unicode string.
270             );
271
272         [DllImport(CAPI.CRYPT32, SetLastError = true)]
273         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
274         [ResourceExposure(ResourceScope.None)]
275         internal static extern bool CertCloseStore(
276             [In] IntPtr hCertStore,
277             [In] uint dwFlags
278             );
279
280         [DllImport(CAPI.CRYPT32, SetLastError = true)]
281         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
282         [ResourceExposure( ResourceScope.None )]
283         internal static extern bool CertFreeCertificateContext(
284             [In] IntPtr pCertContext
285             );
286
287         [DllImport(CAPI.CRYPT32, SetLastError = true)]
288         [ResourceExposure( ResourceScope.None )]
289         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
290         internal static extern SafeCertContextHandle CertFindCertificateInStore(
291             [In] SafeCertStoreHandle hCertStore,
292             [In] uint dwCertEncodingType,
293             [In] uint dwFindFlags,
294             [In] uint dwFindType,
295             [In] SafeHGlobalHandle pvFindPara,
296             [In] SafeCertContextHandle pPrevCertContext
297             );
298
299         [DllImport(CRYPT32, CharSet = CharSet.Auto, SetLastError = true)]
300         [ResourceConsumption( ResourceScope.Machine, ResourceScope.Machine)]
301         [ResourceExposure( ResourceScope.None )]
302         internal extern static bool CertAddCertificateLinkToStore(
303             [In] SafeCertStoreHandle hCertStore,
304             [In] IntPtr pCertContext,
305             [In] uint dwAddDisposition,
306             [In, Out] SafeCertContextHandle ppStoreContext
307             );
308
309         [DllImport(CRYPT32, CharSet = CharSet.Auto, SetLastError = true)]
310         [ResourceExposure( ResourceScope.None )]
311         [ResourceConsumption( ResourceScope.Machine, ResourceScope.Machine )]
312         internal static extern bool CertGetCertificateChain(
313             [In] IntPtr hChainEngine,
314             [In] IntPtr pCertContext,
315             [In] ref FILETIME pTime,
316             [In] SafeCertStoreHandle hAdditionalStore,
317             [In] ref CERT_CHAIN_PARA pChainPara,
318             [In] uint dwFlags,
319             [In] IntPtr pvReserved,
320             [Out] out SafeCertChainHandle ppChainContext
321             );
322
323         [DllImport(CRYPT32, CharSet = CharSet.Auto, SetLastError = true)]
324         [ResourceExposure( ResourceScope.None )]
325         internal extern static bool CertVerifyCertificateChainPolicy(
326             [In] IntPtr pszPolicyOID,
327             [In] SafeCertChainHandle pChainContext,
328             [In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
329             [In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus);
330
331         [DllImport(CRYPT32, SetLastError = true)]
332         [ResourceExposure( ResourceScope.None )]
333         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
334         internal extern static void CertFreeCertificateChain(IntPtr handle);
335
336         // On Vista and higher, check the value of the machine FIPS policy
337         [DllImport(BCRYPT, SetLastError = true)]
338         [ResourceExposure( ResourceScope.None )]
339         internal static extern int BCryptGetFipsAlgorithmMode(
340             [MarshalAs(UnmanagedType.U1), Out] out bool pfEnabled
341             );
342
343     }
344
345 #pragma warning disable 618 // have not moved to the v4 security model yet
346     [SecurityCritical(SecurityCriticalScope.Everything)]
347 #pragma warning restore 618
348     class SafeCertStoreHandle : SafeHandleZeroOrMinusOneIsInvalid
349     {
350         SafeCertStoreHandle() : base(true) { }
351
352         // 0 is an Invalid Handle
353         SafeCertStoreHandle(IntPtr handle)
354             : base(true)
355         {
356             SetHandle(handle);
357         }
358
359         public static SafeCertStoreHandle InvalidHandle
360         {
361             get { return new SafeCertStoreHandle(IntPtr.Zero); }
362         }
363
364         protected override bool ReleaseHandle()
365         {
366             // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call. 
367 #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails.
368             return CAPI.CertCloseStore(handle, 0);
369         }
370     }
371
372 #pragma warning disable 618 // have not moved to the v4 security model yet
373     [SecurityCritical(SecurityCriticalScope.Everything)]
374 #pragma warning restore 618
375     class SafeCertContextHandle : SafeHandleZeroOrMinusOneIsInvalid
376     {
377         SafeCertContextHandle() : base(true) { }
378
379         // 0 is an Invalid Handle
380         SafeCertContextHandle(IntPtr handle)
381             : base(true)
382         {
383             SetHandle(handle);
384         }
385
386         internal static SafeCertContextHandle InvalidHandle
387         {
388             get { return new SafeCertContextHandle(IntPtr.Zero); }
389         }
390
391         protected override bool ReleaseHandle()
392         {
393             // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call. 
394 #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails.
395             return CAPI.CertFreeCertificateContext(handle);
396         }
397     }
398
399 #pragma warning disable 618 // have not moved to the v4 security model yet
400     [SecurityCritical(SecurityCriticalScope.Everything)]
401 #pragma warning restore 618
402     class SafeCertChainHandle : SafeHandleZeroOrMinusOneIsInvalid
403     {
404         SafeCertChainHandle() : base(true) { }
405
406         SafeCertChainHandle(IntPtr handle)
407             : base(true)
408         {
409             SetHandle(handle);
410         }
411
412         internal static SafeCertChainHandle InvalidHandle
413         {
414             get { return new SafeCertChainHandle(IntPtr.Zero); }
415         }
416
417         protected override bool ReleaseHandle()
418         {
419             // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call. 
420 #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails.
421             CAPI.CertFreeCertificateChain(handle);
422             return true;
423         }
424     }
425 }