Enable System.Runtime.Remoting tests on Windows
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / utils.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>[....]</OWNER>
7 // 
8
9 //
10 // Utils.cs
11 //
12 // 05/01/2002
13 //
14
15 namespace System.Security.Cryptography
16 {
17     using Microsoft.Win32;
18     using System.IO;
19     using System.Reflection;
20     using System.Globalization;
21     using System.Runtime.CompilerServices;
22     using System.Runtime.InteropServices;
23 #if FEATURE_MACL
24     using System.Security.AccessControl;
25 #endif // FEATURE_MACL
26     using System.Security.Cryptography.X509Certificates;
27     using System.Security.Permissions;
28 #if FEATURE_IMPERSONATION
29     using System.Security.Principal;
30 #endif // FEATURE_IMPERSONATION
31     using System.Text;
32     using System.Threading;
33     using System.Diagnostics.Contracts;
34     using System.Runtime.Versioning;
35
36 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
37     [Serializable]
38     internal enum CspAlgorithmType {
39         Rsa = 0,
40         Dss = 1
41     }
42 #elif SILVERLIGHT
43     internal enum CspAlgorithmType {
44         Rsa = 0,
45         Dss = 1
46     }
47 #endif
48
49     internal static class Constants {
50 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
51         internal const int S_OK                   = 0;
52         internal const int NTE_FILENOTFOUND       = unchecked((int) 0x80070002); // The system cannot find the file specified.
53         internal const int NTE_NO_KEY             = unchecked((int) 0x8009000D); // Key does not exist.
54         internal const int NTE_BAD_KEYSET         = unchecked((int) 0x80090016); // Keyset does not exist.
55         internal const int NTE_KEYSET_NOT_DEF     = unchecked((int) 0x80090019); // The keyset is not defined.
56
57         internal const int KP_IV                  = 1;
58         internal const int KP_MODE                = 4;
59         internal const int KP_MODE_BITS           = 5;
60         internal const int KP_EFFECTIVE_KEYLEN    = 19;
61
62         internal const int ALG_CLASS_SIGNATURE    = (1 << 13);
63         internal const int ALG_CLASS_DATA_ENCRYPT = (3 << 13);
64         internal const int ALG_CLASS_HASH         = (4 << 13);
65         internal const int ALG_CLASS_KEY_EXCHANGE = (5 << 13);
66
67         internal const int ALG_TYPE_DSS           = (1 << 9);
68         internal const int ALG_TYPE_RSA           = (2 << 9);
69         internal const int ALG_TYPE_BLOCK         = (3 << 9);
70         internal const int ALG_TYPE_STREAM        = (4 << 9);
71         internal const int ALG_TYPE_ANY           = (0);
72
73         internal const int CALG_MD5               = (ALG_CLASS_HASH | ALG_TYPE_ANY | 3);
74         internal const int CALG_SHA1              = (ALG_CLASS_HASH | ALG_TYPE_ANY | 4);
75         internal const int CALG_SHA_256           = (ALG_CLASS_HASH | ALG_TYPE_ANY | 12);
76         internal const int CALG_SHA_384           = (ALG_CLASS_HASH | ALG_TYPE_ANY | 13);
77         internal const int CALG_SHA_512           = (ALG_CLASS_HASH | ALG_TYPE_ANY | 14);
78         internal const int CALG_RSA_KEYX          = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | 0); 
79         internal const int CALG_RSA_SIGN          = (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | 0);
80         internal const int CALG_DSS_SIGN          = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | 0);
81         internal const int CALG_DES               = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 1);
82         internal const int CALG_RC2               = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 2);
83         internal const int CALG_3DES              = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 3);
84         internal const int CALG_3DES_112          = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 9);
85         internal const int CALG_AES_128           = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 14);
86         internal const int CALG_AES_192           = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 15);
87         internal const int CALG_AES_256           = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 16);
88         internal const int CALG_RC4               = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | 1);
89 #endif // FEATURE_CRYPTO
90
91         internal const int PROV_RSA_FULL          = 1;
92         internal const int PROV_DSS_DH            = 13;
93         internal const int PROV_RSA_AES           = 24;
94
95 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
96         internal const int AT_KEYEXCHANGE         = 1;
97 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
98         internal const int AT_SIGNATURE           = 2;
99 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
100         internal const int PUBLICKEYBLOB          = 0x6;
101         internal const int PRIVATEKEYBLOB         = 0x7;
102         internal const int CRYPT_OAEP             = 0x40;
103
104
105         internal const uint CRYPT_VERIFYCONTEXT    = 0xF0000000;
106         internal const uint CRYPT_NEWKEYSET        = 0x00000008;
107         internal const uint CRYPT_DELETEKEYSET     = 0x00000010;
108         internal const uint CRYPT_MACHINE_KEYSET   = 0x00000020;
109         internal const uint CRYPT_SILENT           = 0x00000040;
110         internal const uint CRYPT_EXPORTABLE       = 0x00000001;
111
112         internal const uint CLR_KEYLEN            = 1;
113         internal const uint CLR_PUBLICKEYONLY     = 2;
114         internal const uint CLR_EXPORTABLE        = 3;
115         internal const uint CLR_REMOVABLE         = 4;
116         internal const uint CLR_HARDWARE          = 5;
117         internal const uint CLR_ACCESSIBLE        = 6;
118         internal const uint CLR_PROTECTED         = 7;
119         internal const uint CLR_UNIQUE_CONTAINER  = 8;
120         internal const uint CLR_ALGID             = 9;
121         internal const uint CLR_PP_CLIENT_HWND    = 10;
122         internal const uint CLR_PP_PIN            = 11;
123
124         internal const string OID_RSA_SMIMEalgCMS3DESwrap   = "1.2.840.113549.1.9.16.3.6";
125         internal const string OID_RSA_MD5                   = "1.2.840.113549.2.5";
126         internal const string OID_RSA_RC2CBC                = "1.2.840.113549.3.2";
127         internal const string OID_RSA_DES_EDE3_CBC          = "1.2.840.113549.3.7";
128         internal const string OID_OIWSEC_desCBC             = "1.3.14.3.2.7";
129         internal const string OID_OIWSEC_SHA1               = "1.3.14.3.2.26";
130         internal const string OID_OIWSEC_SHA256             = "2.16.840.1.101.3.4.2.1";
131         internal const string OID_OIWSEC_SHA384             = "2.16.840.1.101.3.4.2.2";
132         internal const string OID_OIWSEC_SHA512             = "2.16.840.1.101.3.4.2.3";
133         internal const string OID_OIWSEC_RIPEMD160          = "1.3.36.3.2.1";
134 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
135     }
136
137     internal static class Utils {
138
139 #if !FEATURE_PAL && FEATURE_CRYPTO
140         [SecuritySafeCritical]
141 #endif
142         static Utils()
143         {
144         }
145
146 #if MONO
147         // The default provider value must remain '1' for Mono, otherwise we won't be able
148         // to locate keypairs that were serialized by Mono versions 4.0 and lower.
149         // (The ProviderType property in the CspParameters class affects serialization)
150         internal const int DefaultRsaProviderType = 1;
151 #else
152         // Provider type to use by default for RSA operations. We want to use RSA-AES CSP
153         // since it enables access to SHA-2 operations. All currently supported OSes support RSA-AES.
154         internal const int DefaultRsaProviderType = Constants.PROV_RSA_AES;
155 #endif
156
157 #if !MONO
158 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
159         // Private object for locking instead of locking on a public type for SQL reliability work.
160         private static Object s_InternalSyncObject = new Object();
161
162         private static Object InternalSyncObject {
163             get { return s_InternalSyncObject; }
164         }
165
166         [System.Security.SecurityCritical] // auto-generated
167         private static volatile SafeProvHandle _safeProvHandle;
168         internal static SafeProvHandle StaticProvHandle {
169             [System.Security.SecurityCritical]  // auto-generated
170             get {
171                 if (_safeProvHandle == null) {
172                     lock (InternalSyncObject) {
173                         if (_safeProvHandle == null) {
174                             _safeProvHandle = AcquireProvHandle(new CspParameters(DefaultRsaProviderType));
175                         }
176                     }
177                 }
178                 return _safeProvHandle;
179             }
180         }
181
182         [System.Security.SecurityCritical] // auto-generated
183         private static volatile SafeProvHandle _safeDssProvHandle;
184         internal static SafeProvHandle StaticDssProvHandle {
185             [System.Security.SecurityCritical]  // auto-generated
186             get {
187                 if (_safeDssProvHandle == null) {
188                     lock (InternalSyncObject) {
189                         if (_safeDssProvHandle == null) {
190                             _safeDssProvHandle = CreateProvHandle(new CspParameters(Constants.PROV_DSS_DH), true);
191                         }
192                     }
193                 }
194                 return _safeDssProvHandle;
195             }
196         }
197
198 #if !FEATURE_PAL
199         [System.Security.SecurityCritical]  // auto-generated
200         [ResourceExposure(ResourceScope.None)]
201         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
202         internal static SafeProvHandle AcquireProvHandle (CspParameters parameters) {
203             if (parameters == null)
204                 parameters = new CspParameters(DefaultRsaProviderType);
205
206             SafeProvHandle safeProvHandle = SafeProvHandle.InvalidHandle;
207             Utils._AcquireCSP(parameters, ref safeProvHandle);
208             return safeProvHandle;
209         }
210
211         [System.Security.SecurityCritical]  // auto-generated
212         [ResourceExposure(ResourceScope.None)]
213         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
214         internal static SafeProvHandle CreateProvHandle (CspParameters parameters, bool randomKeyContainer) {
215             SafeProvHandle safeProvHandle = SafeProvHandle.InvalidHandle;
216             int hr = Utils._OpenCSP(parameters, 0, ref safeProvHandle);
217             KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
218             if (hr != Constants.S_OK) {
219                 // If UseExistingKey flag is used and the key container does not exist
220                 // throw an exception without attempting to create the container.
221                 if ((parameters.Flags & CspProviderFlags.UseExistingKey) != 0 || (hr != Constants.NTE_KEYSET_NOT_DEF && hr != Constants.NTE_BAD_KEYSET && hr != Constants.NTE_FILENOTFOUND))
222                     throw new CryptographicException(hr);
223                 if (!randomKeyContainer) {
224                     if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
225                         KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Create);
226                         kp.AccessEntries.Add(entry);
227                         kp.Demand();
228                     }
229                 }
230                 Utils._CreateCSP(parameters, randomKeyContainer, ref safeProvHandle);
231             } else {
232                 if (!randomKeyContainer) {
233                     if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
234                         KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open);
235                         kp.AccessEntries.Add(entry);
236                         kp.Demand();
237                     }
238                 }
239             }
240             return safeProvHandle;
241         }
242 #endif // !FEATURE_PAL
243
244 #if FEATURE_MACL
245         [System.Security.SecurityCritical]  // auto-generated
246         internal static CryptoKeySecurity GetKeySetSecurityInfo (SafeProvHandle hProv, AccessControlSections accessControlSections) {
247             SecurityInfos securityInfo = 0;
248             Privilege privilege = null;
249
250             if ((accessControlSections & AccessControlSections.Owner) != 0)
251                 securityInfo |= SecurityInfos.Owner;
252             if ((accessControlSections & AccessControlSections.Group) != 0)
253                 securityInfo |= SecurityInfos.Group;
254             if ((accessControlSections & AccessControlSections.Access) != 0)
255                 securityInfo |= SecurityInfos.DiscretionaryAcl;
256
257             byte[] rawSecurityDescriptor = null;
258             int error;
259
260             RuntimeHelpers.PrepareConstrainedRegions();
261             try {
262                 if ((accessControlSections & AccessControlSections.Audit) != 0) {
263                     securityInfo |= SecurityInfos.SystemAcl;
264                     privilege = new Privilege("SeSecurityPrivilege");
265                     privilege.Enable();
266                 }
267                 rawSecurityDescriptor = _GetKeySetSecurityInfo(hProv, securityInfo, out error);
268             }
269             finally {
270                 if (privilege != null)
271                     privilege.Revert();
272             }
273
274             // This means that the object doesn't have a security descriptor. And thus we throw
275             // a specific exception for the caller to catch and handle properly.
276             if (error == Win32Native.ERROR_SUCCESS && (rawSecurityDescriptor == null || rawSecurityDescriptor.Length == 0))
277                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoSecurityDescriptor"));
278             if (error == Win32Native.ERROR_NOT_ENOUGH_MEMORY)
279                 throw new OutOfMemoryException();
280             if (error == Win32Native.ERROR_ACCESS_DENIED)
281                 throw new UnauthorizedAccessException();
282             if (error == Win32Native.ERROR_PRIVILEGE_NOT_HELD)
283                 throw new PrivilegeNotHeldException( "SeSecurityPrivilege" );
284             if (error != Win32Native.ERROR_SUCCESS)
285                 throw new CryptographicException(error);
286
287             CommonSecurityDescriptor sd = new CommonSecurityDescriptor(false /* isContainer */,
288                                                                        false /* isDS */,
289                                                                        new RawSecurityDescriptor(rawSecurityDescriptor, 0),
290                                                                        true);
291             return new CryptoKeySecurity(sd);
292         }
293
294         [System.Security.SecurityCritical]  // auto-generated
295         internal static void SetKeySetSecurityInfo (SafeProvHandle hProv, CryptoKeySecurity cryptoKeySecurity, AccessControlSections accessControlSections) {
296             SecurityInfos securityInfo = 0;
297             Privilege privilege = null;
298
299             if ((accessControlSections & AccessControlSections.Owner) != 0 && cryptoKeySecurity._securityDescriptor.Owner != null)
300                 securityInfo |= SecurityInfos.Owner;
301             if ((accessControlSections & AccessControlSections.Group) != 0 && cryptoKeySecurity._securityDescriptor.Group != null)
302                 securityInfo |= SecurityInfos.Group;
303             if ((accessControlSections & AccessControlSections.Audit) != 0)
304                 securityInfo |= SecurityInfos.SystemAcl;
305             if ((accessControlSections & AccessControlSections.Access) != 0 && cryptoKeySecurity._securityDescriptor.IsDiscretionaryAclPresent)
306                 securityInfo |= SecurityInfos.DiscretionaryAcl;
307
308             if (securityInfo == 0) {
309                 // Nothing to persist
310                 return;
311             }
312
313             int error = 0;
314
315             RuntimeHelpers.PrepareConstrainedRegions();
316             try {
317                 if ((securityInfo & SecurityInfos.SystemAcl) != 0) {
318                     privilege = new Privilege("SeSecurityPrivilege");
319                     privilege.Enable();
320                 }
321
322                 byte[] sd = cryptoKeySecurity.GetSecurityDescriptorBinaryForm();
323                 if (sd != null && sd.Length > 0)
324                     error = SetKeySetSecurityInfo (hProv, securityInfo, sd);
325             }
326             finally {
327                 if (privilege != null)
328                     privilege.Revert();
329             }
330
331             if (error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_INVALID_OWNER || error == Win32Native.ERROR_INVALID_PRIMARY_GROUP)
332                 throw new UnauthorizedAccessException();
333             else if (error == Win32Native.ERROR_PRIVILEGE_NOT_HELD)
334                 throw new PrivilegeNotHeldException("SeSecurityPrivilege");
335             else if (error == Win32Native.ERROR_INVALID_HANDLE)
336                 throw new NotSupportedException(Environment.GetResourceString("AccessControl_InvalidHandle"));
337             else if (error != Win32Native.ERROR_SUCCESS)
338                 throw new CryptographicException(error);
339         }
340 #endif //FEATURE_MACL
341
342         [System.Security.SecurityCritical]  // auto-generated
343         internal static byte[] ExportCspBlobHelper (bool includePrivateParameters, CspParameters parameters, SafeKeyHandle safeKeyHandle) {
344             if (includePrivateParameters) {
345                 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
346                     KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
347                     KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Export);
348                     kp.AccessEntries.Add(entry);
349                     kp.Demand();
350                 }
351             }
352             byte[] blob = null;
353             Utils.ExportCspBlob(safeKeyHandle, includePrivateParameters ? Constants.PRIVATEKEYBLOB : Constants.PUBLICKEYBLOB, JitHelpers.GetObjectHandleOnStack(ref blob));
354             return blob;
355         }
356
357         [System.Security.SecuritySafeCritical]  // auto-generated
358         [ResourceExposure(ResourceScope.None)]
359         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
360         internal static void GetKeyPairHelper (CspAlgorithmType keyType, CspParameters parameters, bool randomKeyContainer, int dwKeySize, ref SafeProvHandle safeProvHandle, ref SafeKeyHandle safeKeyHandle) {
361             SafeProvHandle TempFetchedProvHandle = Utils.CreateProvHandle(parameters, randomKeyContainer);
362
363 #if FEATURE_MACL
364             // If the user wanted to set the security descriptor on the provider context, apply it now.
365             if (parameters.CryptoKeySecurity != null) {
366                 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
367                 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.ChangeAcl);
368                 kp.AccessEntries.Add(entry);
369                 kp.Demand();
370                 SetKeySetSecurityInfo(TempFetchedProvHandle, parameters.CryptoKeySecurity, parameters.CryptoKeySecurity.ChangedAccessControlSections);
371             }
372 #endif //FEATURE_MACL
373
374 #if FEATURE_X509_SECURESTRINGS
375             // If the user wanted to specify a PIN or HWND for a smart card CSP, apply those settings now.
376             if (parameters.ParentWindowHandle != IntPtr.Zero)
377                 SetProviderParameter(TempFetchedProvHandle, parameters.KeyNumber, Constants.CLR_PP_CLIENT_HWND, parameters.ParentWindowHandle);
378             else if (parameters.KeyPassword != null) {
379                 IntPtr szPassword = Marshal.SecureStringToCoTaskMemAnsi(parameters.KeyPassword);
380                 try {
381                     SetProviderParameter(TempFetchedProvHandle, parameters.KeyNumber, Constants.CLR_PP_PIN, szPassword);
382                 }
383                 finally {
384                     if (szPassword != IntPtr.Zero)
385                         Marshal.ZeroFreeCoTaskMemAnsi(szPassword);
386                 }
387             }
388 #endif //FEATURE_X509_SECURESTRINGS
389
390             safeProvHandle = TempFetchedProvHandle;
391
392             // If the key already exists, use it, else generate a new one
393             SafeKeyHandle TempFetchedKeyHandle = SafeKeyHandle.InvalidHandle;
394             int hr = Utils._GetUserKey(safeProvHandle, parameters.KeyNumber, ref TempFetchedKeyHandle);
395             if (hr != Constants.S_OK) {
396                 if ((parameters.Flags & CspProviderFlags.UseExistingKey) != 0 || hr != Constants.NTE_NO_KEY)
397                     throw new CryptographicException(hr);
398                 // _GenerateKey will check for failures and throw an exception
399                 Utils._GenerateKey(safeProvHandle, parameters.KeyNumber, parameters.Flags, dwKeySize, ref TempFetchedKeyHandle);
400             }
401
402             // check that this is indeed an RSA/DSS key.
403             byte[] algid = (byte[]) Utils._GetKeyParameter(TempFetchedKeyHandle, Constants.CLR_ALGID);
404             int dwAlgId = (algid[0] | (algid[1] << 8) | (algid[2] << 16) | (algid[3] << 24));
405             if ((keyType == CspAlgorithmType.Rsa && dwAlgId != Constants.CALG_RSA_KEYX && dwAlgId != Constants.CALG_RSA_SIGN) ||
406                     (keyType == CspAlgorithmType.Dss && dwAlgId != Constants.CALG_DSS_SIGN)) {
407                 TempFetchedKeyHandle.Dispose();
408                 throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_WrongKeySpec"));
409             }
410
411             safeKeyHandle = TempFetchedKeyHandle;
412         }
413
414         [System.Security.SecurityCritical]  // auto-generated
415         internal static void ImportCspBlobHelper (CspAlgorithmType keyType, byte[] keyBlob, bool publicOnly, ref CspParameters parameters, bool randomKeyContainer, ref SafeProvHandle safeProvHandle, ref SafeKeyHandle safeKeyHandle) {
416             // Free the current key handle
417             if (safeKeyHandle != null && !safeKeyHandle.IsClosed)
418                 safeKeyHandle.Dispose();
419             safeKeyHandle = SafeKeyHandle.InvalidHandle;
420
421             if (publicOnly) {
422                 parameters.KeyNumber = Utils._ImportCspBlob(keyBlob, keyType == CspAlgorithmType.Dss ? Utils.StaticDssProvHandle : Utils.StaticProvHandle, (CspProviderFlags) 0, ref safeKeyHandle);
423             } else {
424                 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
425                     KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
426                     KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Import);
427                     kp.AccessEntries.Add(entry);
428                     kp.Demand();
429                 }
430                 if (safeProvHandle == null)
431                     safeProvHandle = Utils.CreateProvHandle(parameters, randomKeyContainer);
432                 parameters.KeyNumber = Utils._ImportCspBlob(keyBlob, safeProvHandle, parameters.Flags, ref safeKeyHandle);
433             }
434         }
435 #endif // FEATURE_CRYPTO
436
437 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
438         [System.Security.SecurityCritical]  // auto-generated
439         [ResourceExposure(ResourceScope.None)]
440         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
441         internal static CspParameters SaveCspParameters (CspAlgorithmType keyType, CspParameters userParameters, CspProviderFlags defaultFlags, ref bool randomKeyContainer) {
442
443             CspParameters parameters;
444             if (userParameters == null) {
445                 parameters = new CspParameters(keyType == CspAlgorithmType.Dss ? Constants.PROV_DSS_DH : DefaultRsaProviderType, null, null, defaultFlags);
446             } else {
447                 ValidateCspFlags(userParameters.Flags);
448                 parameters = new CspParameters(userParameters);
449             }
450
451             if (parameters.KeyNumber == -1)
452                 parameters.KeyNumber = keyType == CspAlgorithmType.Dss ? Constants.AT_SIGNATURE : Constants.AT_KEYEXCHANGE;
453             else if (parameters.KeyNumber == Constants.CALG_DSS_SIGN || parameters.KeyNumber == Constants.CALG_RSA_SIGN)
454                 parameters.KeyNumber = Constants.AT_SIGNATURE;
455             else if (parameters.KeyNumber == Constants.CALG_RSA_KEYX)
456                 parameters.KeyNumber = Constants.AT_KEYEXCHANGE;
457
458             // If no key container was specified and UseDefaultKeyContainer is not used, then use CRYPT_VERIFYCONTEXT
459             // to generate an ephemeral key
460             randomKeyContainer = (parameters.Flags & CspProviderFlags.CreateEphemeralKey) == CspProviderFlags.CreateEphemeralKey;
461             if (parameters.KeyContainerName == null && (parameters.Flags & CspProviderFlags.UseDefaultKeyContainer) == 0) {
462                 parameters.Flags |= CspProviderFlags.CreateEphemeralKey;
463                 randomKeyContainer = true;
464             }
465
466             return parameters;
467         }
468
469         [System.Security.SecurityCritical]  // auto-generated
470         private static void ValidateCspFlags (CspProviderFlags flags) {
471             // check that the flags are consistent.
472             if ((flags & CspProviderFlags.UseExistingKey) != 0) {
473                 CspProviderFlags keyFlags = (CspProviderFlags.UseNonExportableKey | CspProviderFlags.UseArchivableKey | CspProviderFlags.UseUserProtectedKey);
474                 if ((flags & keyFlags) != CspProviderFlags.NoFlags)
475                     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"));
476             }
477
478             // make sure we are allowed to display the key protection UI if a user protected key is requested.
479             if ((flags & CspProviderFlags.UseUserProtectedKey) != 0) {
480                 // UI only allowed in interactive session.
481                 if (!System.Environment.UserInteractive)
482                     throw new InvalidOperationException(Environment.GetResourceString("Cryptography_NotInteractive"));
483
484                 // we need to demand UI permission here.
485                 UIPermission uiPermission = new UIPermission(UIPermissionWindow.SafeTopLevelWindows);
486                 uiPermission.Demand();
487             }
488         }
489 #endif // FEATURE_CRYPTO
490
491 #endif
492         private static volatile RNGCryptoServiceProvider _rng;
493         internal static RNGCryptoServiceProvider StaticRandomNumberGenerator {
494             get {
495                 if (_rng == null)
496                     _rng = new RNGCryptoServiceProvider();
497                 return _rng;
498             }
499         }
500
501         //
502         // internal static methods
503         //
504
505         internal static byte[] GenerateRandom (int keySize) {
506             byte[] key = new byte[keySize];
507             StaticRandomNumberGenerator.GetBytes(key);
508             return key;
509         }
510 #if !MONO
511 #if FEATURE_CRYPTO
512         /// <summary>
513         ///     Read the FIPS policy from the pre-Vista registry key
514         /// </summary>
515         /// <returns>
516         ///     True if the FIPS policy is enabled, false otherwise.  An error reading the policy key is
517         ///     interpreted as if the policy is enabled, and a missing key is interpreted as the policy being
518         ///     disabled.
519         /// </returns>
520         [System.Security.SecurityCritical]  // auto-generated
521         [RegistryPermissionAttribute(SecurityAction.Assert, Read="HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Lsa")]
522         internal static bool ReadLegacyFipsPolicy()
523         {
524             Contract.Assert(Environment.OSVersion.Version.Major < 6, "CryptGetFIPSAlgorithmMode should be used on Vista+");
525
526             try
527             {
528                 using (RegistryKey fipsAlgorithmPolicyKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Lsa", false))
529                 {
530                     if (fipsAlgorithmPolicyKey == null)
531                         return false;
532
533                     object data = fipsAlgorithmPolicyKey.GetValue("FIPSAlgorithmPolicy");
534
535                     if (data == null)
536                     {
537                         return false;
538                     }
539                     else if (fipsAlgorithmPolicyKey.GetValueKind("FIPSAlgorithmPolicy") != RegistryValueKind.DWord)
540                     {
541                         return true;
542                     }
543                     else
544                     {
545                         return ((int)data != 0);
546                     }
547                 }
548             }
549             catch (SecurityException)
550             {
551                 // If we could not open the registry key, we'll assume the setting is to enforce FIPS policy.
552                 return true;
553             }
554         }
555 #endif //FEATURE_CRYPTO
556 #endif
557 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
558         // dwKeySize = 0 means the default key size
559         [System.Security.SecurityCritical]  // auto-generated
560         internal static bool HasAlgorithm (int dwCalg, int dwKeySize) {
561 #if MONO
562             return true;
563 #else
564             bool r = false;
565             // We need to take a lock here since we are querying the provider handle in a loop.
566             // If multiple threads are racing in this code, not all algorithms/key sizes combinations
567             // will be examined; which may lead to a situation where false is wrongfully returned.
568             lock (InternalSyncObject) {
569                 r = SearchForAlgorithm(StaticProvHandle, dwCalg, dwKeySize);
570             }
571             return r;
572 #endif
573         }
574 #if !MONO
575         internal static int ObjToAlgId(object hashAlg, OidGroup group) {
576             if (hashAlg == null)
577                 throw new ArgumentNullException("hashAlg");
578             Contract.EndContractBlock();
579
580             string oidValue = null;
581             string hashAlgString = hashAlg as string;
582             if (hashAlgString != null) {
583                 oidValue = CryptoConfig.MapNameToOID(hashAlgString, group);
584                 if (oidValue == null)
585                     oidValue = hashAlgString; // maybe we were passed the OID value
586             }
587             else if (hashAlg is HashAlgorithm) {
588                 oidValue = CryptoConfig.MapNameToOID(hashAlg.GetType().ToString(), group);
589             }
590             else if (hashAlg is Type) {
591                 oidValue = CryptoConfig.MapNameToOID(hashAlg.ToString(), group);
592             }
593
594             if (oidValue == null)
595                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
596
597             return X509Utils.GetAlgIdFromOid(oidValue, group);
598         }
599
600         internal static HashAlgorithm ObjToHashAlgorithm (Object hashAlg) {
601             if (hashAlg == null)
602                 throw new ArgumentNullException("hashAlg");
603             Contract.EndContractBlock();
604
605             HashAlgorithm hash = null;
606             if (hashAlg is String) {
607                 hash = (HashAlgorithm) CryptoConfig.CreateFromName((string) hashAlg);
608                 if (hash == null) {
609                     string oidFriendlyName = X509Utils.GetFriendlyNameFromOid((string) hashAlg, OidGroup.HashAlgorithm);
610                     if (oidFriendlyName != null)
611                         hash = (HashAlgorithm) CryptoConfig.CreateFromName(oidFriendlyName);
612                 }
613             }
614             else if (hashAlg is HashAlgorithm) {
615                 hash = (HashAlgorithm) hashAlg;
616             }
617             else if (hashAlg is Type) {
618                 hash = (HashAlgorithm) CryptoConfig.CreateFromName(hashAlg.ToString());
619             }
620
621             if (hash == null)
622                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
623
624             return hash;
625         }
626 #endif
627         internal static String DiscardWhiteSpaces (string inputBuffer) {
628             return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length);
629         }
630
631         internal static String DiscardWhiteSpaces (string inputBuffer, int inputOffset, int inputCount) {
632             int i, iCount = 0;
633             for (i=0; i<inputCount; i++)
634                 if (Char.IsWhiteSpace(inputBuffer[inputOffset + i])) iCount++;
635             char[] output = new char[inputCount - iCount];
636             iCount = 0;
637             for (i=0; i<inputCount; i++) {
638                 if (!Char.IsWhiteSpace(inputBuffer[inputOffset + i]))
639                     output[iCount++] = inputBuffer[inputOffset + i];
640             }
641             return new String(output);
642         }
643
644         internal static int ConvertByteArrayToInt (byte[] input) {
645             // Input to this routine is always big endian
646             int dwOutput = 0;
647             for (int i = 0; i < input.Length; i++) {
648                 dwOutput *= 256;
649                 dwOutput += input[i];
650             }
651             return(dwOutput);
652         }
653
654         // output of this routine is always big endian
655         internal static byte[] ConvertIntToByteArray (int dwInput) {
656             byte[] temp = new byte[8]; // int can never be greater than Int64
657             int t1;  // t1 is remaining value to account for
658             int t2;  // t2 is t1 % 256
659             int i = 0;
660
661             if (dwInput == 0) return new byte[1]; 
662             t1 = dwInput; 
663             while (t1 > 0) {
664                 Contract.Assert(i < 8, "Got too big an int here!");
665                 t2 = t1 % 256;
666                 temp[i] = (byte) t2;
667                 t1 = (t1 - t2)/256;
668                 i++;
669             }
670
671             // Now, copy only the non-zero part of temp and reverse
672             byte[] output = new byte[i];
673             // copy and reverse in one pass
674             for (int j = 0; j < i; j++) {
675                 output[j] = temp[i-j-1];
676             }
677             return output;
678         }
679
680         // output is little endian
681         internal static void ConvertIntToByteArray (uint dwInput, ref byte[] counter) {
682             uint t1 = dwInput;  // t1 is remaining value to account for
683             uint t2;  // t2 is t1 % 256
684             int i = 0;
685
686             // clear the array first
687             Array.Clear(counter, 0, counter.Length);
688             if (dwInput == 0) return;
689             while (t1 > 0) {
690                 Contract.Assert(i < 4, "Got too big an int here!");
691                 t2 = t1 % 256;
692                 counter[3 - i] = (byte) t2;
693                 t1 = (t1 - t2)/256;
694                 i++;
695             }
696         }
697
698         internal static byte[] FixupKeyParity (byte[] key) {
699             byte[] oddParityKey = new byte[key.Length];
700             for (int index=0; index < key.Length; index++) {
701                 // Get the bits we are interested in
702                 oddParityKey[index] = (byte) (key[index] & 0xfe);
703                 // Get the parity of the sum of the previous bits
704                 byte tmp1 = (byte)((oddParityKey[index] & 0xF) ^ (oddParityKey[index] >> 4));
705                 byte tmp2 = (byte)((tmp1 & 0x3) ^ (tmp1 >> 2));
706                 byte sumBitsMod2 = (byte)((tmp2 & 0x1) ^ (tmp2 >> 1));
707                 // We need to set the last bit in oddParityKey[index] to the negation
708                 // of the last bit in sumBitsMod2
709                 if (sumBitsMod2 == 0)
710                     oddParityKey[index] |= 1;
711             }
712             return oddParityKey;
713         }
714
715         // digits == number of DWORDs
716         [System.Security.SecurityCritical]  // auto-generated
717         internal unsafe static void DWORDFromLittleEndian (uint* x, int digits, byte* block) {
718             int i;
719             int j;
720
721             for (i = 0, j = 0; i < digits; i++, j += 4)
722                 x[i] =  (uint) (block[j] | (block[j+1] << 8) | (block[j+2] << 16) | (block[j+3] << 24));
723         }
724
725         // encodes x (DWORD) into block (unsigned char), least significant byte first. 
726         // digits == number of DWORDs
727         internal static void DWORDToLittleEndian (byte[] block, uint[] x, int digits) {
728             int i;
729             int j;
730
731             for (i = 0, j = 0; i < digits; i++, j += 4) {
732                 block[j]   = (byte)(x[i] & 0xff);
733                 block[j+1] = (byte)((x[i] >> 8) & 0xff);
734                 block[j+2] = (byte)((x[i] >> 16) & 0xff);
735                 block[j+3] = (byte)((x[i] >> 24) & 0xff);
736             }
737         }
738 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
739
740         // digits == number of DWORDs
741         [System.Security.SecurityCritical]  // auto-generated
742         internal unsafe static void DWORDFromBigEndian (uint* x, int digits, byte* block) {
743             int i;
744             int j;
745
746             for (i = 0, j = 0; i < digits; i++, j += 4)
747                 x[i] = (uint)((block[j] << 24) | (block[j + 1] << 16) | (block[j + 2] << 8) | block[j + 3]);
748         }
749
750         // encodes x (DWORD) into block (unsigned char), most significant byte first. 
751         // digits == number of DWORDs
752         internal static void DWORDToBigEndian (byte[] block, uint[] x, int digits) {
753             int i;
754             int j;
755
756             for (i = 0, j = 0; i < digits; i++, j += 4) {
757                 block[j] = (byte)((x[i] >> 24) & 0xff);
758                 block[j+1] = (byte)((x[i] >> 16) & 0xff);
759                 block[j+2] = (byte)((x[i] >> 8) & 0xff);
760                 block[j+3] = (byte)(x[i] & 0xff);
761             }
762         }
763
764 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
765         // digits == number of QWORDs
766         [System.Security.SecurityCritical]  // auto-generated
767         internal unsafe static void QuadWordFromBigEndian (UInt64* x, int digits, byte* block) {
768             int i;
769             int j;
770
771             for (i = 0, j = 0; i < digits; i++, j += 8)
772                 x[i] =  (
773                          (((UInt64)block[j]) << 56) | (((UInt64)block[j+1]) << 48) |
774                          (((UInt64)block[j+2]) << 40) | (((UInt64)block[j+3]) << 32) |
775                          (((UInt64)block[j+4]) << 24) | (((UInt64)block[j+5]) << 16) |
776                          (((UInt64)block[j+6]) << 8) | ((UInt64)block[j+7])
777                         );
778         }
779
780         // encodes x (DWORD) into block (unsigned char), most significant byte first.
781         // digits = number of QWORDS
782         internal static void QuadWordToBigEndian (byte[] block, UInt64[] x, int digits) {
783             int i;
784             int j;
785
786             for (i = 0, j = 0; i < digits; i++, j += 8) {
787                 block[j] = (byte)((x[i] >> 56) & 0xff);
788                 block[j+1] = (byte)((x[i] >> 48) & 0xff);
789                 block[j+2] = (byte)((x[i] >> 40) & 0xff);
790                 block[j+3] = (byte)((x[i] >> 32) & 0xff);
791                 block[j+4] = (byte)((x[i] >> 24) & 0xff);
792                 block[j+5] = (byte)((x[i] >> 16) & 0xff);
793                 block[j+6] = (byte)((x[i] >> 8) & 0xff);
794                 block[j+7] = (byte)(x[i] & 0xff);
795             }
796         }
797 #endif // FEATURE_CRYPTO
798
799         // encodes the integer i into a 4-byte array, in big endian.
800         internal static byte[] Int(uint i) {
801             return unchecked(new byte[] { (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i });
802         }
803
804 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
805         [System.Security.SecurityCritical]  // auto-generated
806         internal static byte[] RsaOaepEncrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) {
807 #if MONO
808             // It looks like .net managed implementation is buggy. It returns quite different
809             // result compare to old mono code, even PSLength calculation is quite different
810             return Mono.Security.Cryptography.PKCS1.Encrypt_OAEP (rsa, hash, rng, data);
811 #else
812             int cb = rsa.KeySize / 8;
813
814             //  1. Hash the parameters to get PHash
815             int cbHash = hash.HashSize / 8;
816             if ((data.Length + 2 + 2*cbHash) > cb)
817                 throw new CryptographicException(String.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), cb-2-2*cbHash));
818             hash.ComputeHash(EmptyArray<Byte>.Value); // Use an empty octet string
819
820             //  2.  Create DB object
821             byte[] DB = new byte[cb - cbHash + 1];
822
823             //  Structure is as follows:
824             //      pHash || PS || 01 || M
825             //      PS consists of all zeros
826
827             Buffer.InternalBlockCopy(hash.Hash, 0, DB, 0, cbHash);
828             DB[DB.Length - data.Length - 1] = 1;
829             Buffer.InternalBlockCopy(data, 0, DB, DB.Length-data.Length, data.Length);
830
831             // 3. Create a random value of size hLen
832             byte[] seed = new byte[cbHash];
833             rng.GetBytes(seed);
834
835             // 4.  Compute the mask value
836             byte[] mask = mgf.GenerateMask(seed, DB.Length);
837
838             // 5.  Xor maskDB into DB
839             for (int i=0; i < DB.Length; i++) {
840                 DB[i] = (byte) (DB[i] ^ mask[i]);
841             }
842
843             // 6.  Compute seed mask value
844             mask = mgf.GenerateMask(DB, cbHash);
845
846             // 7.  Xor mask into seed
847             for (int i=0; i < seed.Length; i++) {
848                 seed[i] ^= mask[i];
849             }
850
851             // 8. Concatenate seed and DB to form value to encrypt
852             byte[] pad = new byte[cb];
853             Buffer.InternalBlockCopy(seed, 0, pad, 0, seed.Length);
854             Buffer.InternalBlockCopy(DB, 0, pad, seed.Length, DB.Length);
855
856             return rsa.EncryptValue(pad);
857 #endif
858         }
859
860         [System.Security.SecurityCritical]  // auto-generated
861         internal static byte[] RsaOaepDecrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) {
862 #if MONO
863             var result = Mono.Security.Cryptography.PKCS1.Decrypt_OAEP (rsa, hash, encryptedData);
864             if (result == null)
865                 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
866             return result;
867 #else
868             int cb = rsa.KeySize / 8;
869
870             // 1. Decode the input data
871             // It is important that the Integer to Octet String conversion errors be indistinguishable from the other decoding
872             // errors to protect against chosen cipher text attacks
873             // A lecture given by James Manger during Crypto 2001 explains the issue in details
874             byte[] data = null;
875             try {
876                 data = rsa.DecryptValue(encryptedData);
877             }
878             catch (CryptographicException) {
879                 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
880             }
881
882             // 2. Create the hash object so we can get its size info.
883             int cbHash = hash.HashSize / 8;
884
885             //  3.  Let maskedSeed be the first hLen octects and maskedDB
886             //      be the remaining bytes.
887             int zeros = cb - data.Length;
888             if (zeros < 0 || zeros >= cbHash)
889                 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
890
891             const int leading_zeros = 0;
892             byte[] seed = new byte[cbHash];
893             Buffer.InternalBlockCopy(data, leading_zeros, seed, zeros, seed.Length - zeros);
894
895             byte[] DB = new byte[data.Length - seed.Length + zeros - leading_zeros];
896             Buffer.InternalBlockCopy(data, seed.Length - zeros + leading_zeros, DB, 0, DB.Length);
897
898             //  4.  seedMask = MGF(maskedDB, hLen);
899             byte[] mask = mgf.GenerateMask(DB, seed.Length);
900
901             //  5.  seed = seedMask XOR maskedSeed
902             int i = 0;
903             for (i=0; i < seed.Length; i++) {
904                 seed[i] ^= mask[i];
905             }
906
907             //  6.  dbMask = MGF(seed, |EM| - hLen);
908             mask = mgf.GenerateMask(seed, DB.Length);
909
910             //  7.  DB = maskedDB xor dbMask
911             for (i=0; i < DB.Length; i++) {
912                 DB[i] = (byte) (DB[i] ^ mask[i]);
913             }
914
915             //  8.  pHash = HASH(P)
916             hash.ComputeHash(EmptyArray<Byte>.Value);
917
918             //  9.  DB = pHash' || PS || 01 || M
919             //  10.  Check that pHash = pHash'
920
921             byte[] hashValue = hash.Hash;
922             for (i=0; i < cbHash; i++) {
923                 if (DB[i] != hashValue[i])
924                     throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
925             }
926
927             //  Check that PS is all zeros
928             for (; i<DB.Length; i++) {
929                 if (DB[i] == 1)
930                     break;
931                 else if (DB[i] != 0)
932                     throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
933             }
934
935             if (i == DB.Length)
936                 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
937
938             i++; // skip over the one
939
940             //  11. Output M.
941             byte[] output = new byte[DB.Length - i];
942             Buffer.InternalBlockCopy(DB, i, output, 0, output.Length);
943             return output;
944  #endif
945         }
946
947         [System.Security.SecurityCritical]  // auto-generated
948         internal static byte[] RsaPkcs1Padding (RSA rsa, byte[] oid, byte[] hash) {
949             int cb = rsa.KeySize/8;
950             byte[] pad = new byte[cb];
951
952             //
953             //  We want to pad this to the following format:
954             //
955             //  00 || 01 || FF ... FF || 00 || prefix || Data
956             //
957             // We want basically to ASN 1 encode the OID + hash:
958             // STRUCTURE {
959             //  STRUCTURE {
960             //    OID <hash algorithm OID>
961             //    NULL (0x05 0x00)  // this is actually an ANY and contains the parameters of the algorithm specified by the OID, I think
962             //  }
963             //  OCTET STRING <hashvalue>
964             // }
965             //
966
967             // Get the correct prefix
968             byte[] data = new byte[oid.Length + 8 + hash.Length];
969             data[0] = 0x30; // a structure follows
970             int tmp = data.Length - 2;
971             data[1] = (byte) tmp;
972             data[2] = 0x30;
973             tmp = oid.Length + 2;
974             data[3] = (byte) tmp;
975             Buffer.InternalBlockCopy(oid, 0, data, 4, oid.Length);
976             data[4 + oid.Length] = 0x05;
977             data[4 + oid.Length + 1] = 0x00;
978             data[4 + oid.Length + 2] = 0x04; // an octet string follows
979             data[4 + oid.Length + 3] = (byte) hash.Length;
980             Buffer.InternalBlockCopy(hash, 0, data, oid.Length + 8, hash.Length);
981
982             // Construct the whole array
983             int cb1 = cb - data.Length;
984             if (cb1 <= 2)
985                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_InvalidOID"));
986
987             pad[0] = 0;
988             pad[1] = 1;
989             for (int i=2; i<cb1-1; i++) {
990                 pad[i] = 0xff;
991             }
992             pad[cb1-1] = 0;
993             Buffer.InternalBlockCopy(data, 0, pad, cb1, data.Length);
994             return pad;
995         }
996
997         // This routine compares 2 big ints; ignoring any leading zeros
998         internal static bool CompareBigIntArrays (byte[] lhs, byte[] rhs) {
999             if (lhs == null)
1000                 return (rhs == null);
1001
1002             int i = 0, j = 0;
1003             while (i < lhs.Length && lhs[i] == 0) i++;
1004             while (j < rhs.Length && rhs[j] == 0) j++;
1005
1006             int count = (lhs.Length - i);
1007             if ((rhs.Length - j) != count)
1008                 return false;
1009
1010             for (int k = 0; k < count; k++) {
1011                 if (lhs[i + k] != rhs[j + k])
1012                     return false;
1013             }
1014             return true;
1015         }
1016 #if !MONO
1017         [System.Security.SecurityCritical]  // auto-generated
1018         [ResourceExposure(ResourceScope.None)]  // Creates a process resource, but it can't be scoped.
1019         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1020         internal static extern SafeHashHandle CreateHash(SafeProvHandle hProv, int algid);
1021 #endif
1022         internal static HashAlgorithmName OidToHashAlgorithmName(string oid)
1023         {
1024             switch (oid)
1025             {
1026                 case Constants.OID_OIWSEC_SHA1:
1027                     return HashAlgorithmName.SHA1;
1028
1029                 case Constants.OID_OIWSEC_SHA256:
1030                     return HashAlgorithmName.SHA256;
1031
1032                 case Constants.OID_OIWSEC_SHA384:
1033                     return HashAlgorithmName.SHA384;
1034
1035                 case Constants.OID_OIWSEC_SHA512:
1036                     return HashAlgorithmName.SHA512;
1037
1038                 default:
1039                     throw new NotSupportedException();
1040             }
1041         }
1042
1043         //
1044         // Backward-compat hack for third-party RSA-derived classes:
1045         // 
1046         // Because the SignHash()/VerifyHash()/Encrypt()/Decrypt() methods are new on RSA, we may 
1047         // encounter older third-party RSA-derived classes that don't override them
1048         // (and if they don't override them, these methods will throw since they are effectively abstract methods that had to declared non-abstract
1049         // for backward compat reasons.)
1050         //
1051         internal static bool DoesRsaKeyOverride(RSA rsaKey, string methodName, Type[] parameterTypes)
1052         {
1053             // A fast-path check for the common cases where we know we implemented the overrides.
1054             Type t = rsaKey.GetType();
1055             if (rsaKey is RSACryptoServiceProvider)
1056             {
1057 #if DEBUG
1058                 // On checked builds, do the slow-path check anyway so it gets exercised.
1059                 bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
1060                 BCLDebug.Assert(foundOverride, "RSACryptoServiceProvider expected to override " + methodName);
1061 #endif
1062                 return true;
1063             }
1064
1065             string fullName = t.FullName;
1066             if (fullName == "System.Security.Cryptography.RSACng")
1067             {
1068 #if DEBUG
1069                 // On checked builds, do the slow-path check anyway so it gets exercised.
1070                 bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
1071                 BCLDebug.Assert(foundOverride, "RSACng expected to override " + methodName);
1072 #endif
1073                 return true;
1074             }
1075             return DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes);
1076         }
1077
1078         private static bool DoesRsaKeyOverrideSlowPath(Type t, string methodName, Type[] parameterTypes)
1079         {
1080             MethodInfo method = t.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null);
1081             BCLDebug.Assert(method != null, "method != null"); 
1082             Type declaringType = method.DeclaringType;
1083             if (declaringType == typeof(RSA))
1084                 return false;
1085
1086             return true;
1087         }
1088 #if !MONO
1089         [System.Security.SecurityCritical]  // auto-generated
1090         [ResourceExposure(ResourceScope.None)]
1091         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1092         private static extern void EndHash(SafeHashHandle hHash, ObjectHandleOnStack retHash);
1093
1094         [System.Security.SecurityCritical]  // auto-generated
1095         internal static byte[] EndHash(SafeHashHandle hHash)
1096         {
1097             byte[] hash = null;
1098             EndHash(hHash, JitHelpers.GetObjectHandleOnStack(ref hash));
1099             return hash;
1100         }
1101
1102         [System.Security.SecurityCritical]  // auto-generated
1103         [ResourceExposure(ResourceScope.None)]
1104         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1105         private static extern void ExportCspBlob(SafeKeyHandle hKey, int blobType, ObjectHandleOnStack retBlob);
1106
1107         [System.Security.SecurityCritical]  // auto-generated
1108         [ResourceExposure(ResourceScope.None)]
1109         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1110         internal static extern bool GetPersistKeyInCsp(SafeProvHandle hProv);
1111
1112         [System.Security.SecurityCritical]  // auto-generated
1113         [ResourceExposure(ResourceScope.None)]
1114         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1115         private static extern void HashData(SafeHashHandle hHash, byte[] data, int cbData, int ibStart, int cbSize);
1116
1117         [System.Security.SecurityCritical]  // auto-generated
1118         internal static void HashData(SafeHashHandle hHash, byte[] data, int ibStart, int cbSize)
1119         {
1120             HashData(hHash, data, data.Length, ibStart, cbSize);
1121         }
1122
1123         [System.Security.SecurityCritical]  // auto-generated
1124         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1125         [ResourceExposure(ResourceScope.None)]
1126         private static extern bool SearchForAlgorithm(SafeProvHandle hProv, int algID, int keyLength);
1127
1128         [System.Security.SecurityCritical]  // auto-generated
1129         [ResourceExposure(ResourceScope.None)]
1130         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1131         internal static extern void SetKeyParamDw(SafeKeyHandle hKey, int param, int dwValue);
1132
1133         [System.Security.SecurityCritical]  // auto-generated
1134         [ResourceExposure(ResourceScope.None)]
1135         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1136         internal static extern void SetKeyParamRgb(SafeKeyHandle hKey, int param, byte[] value, int cbValue);
1137
1138 #if FEATURE_MACL
1139         [System.Security.SecurityCritical]  // auto-generated
1140         [ResourceExposure(ResourceScope.None)]
1141         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1142         private static extern int SetKeySetSecurityInfo(SafeProvHandle hProv, SecurityInfos securityInfo, byte[] sd);
1143 #endif //FEATURE_MACL
1144         [System.Security.SecurityCritical]  // auto-generated
1145         [ResourceExposure(ResourceScope.None)]
1146         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1147         internal static extern void SetPersistKeyInCsp(SafeProvHandle hProv, bool fPersistKeyInCsp);
1148
1149         [System.Security.SecurityCritical]  // auto-generated
1150         [ResourceExposure(ResourceScope.None)]
1151         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1152         internal static extern void SetProviderParameter(SafeProvHandle hProv, int keyNumber, uint paramID, IntPtr pbData);
1153
1154         [System.Security.SecurityCritical]  // auto-generated
1155         [ResourceExposure(ResourceScope.None)]
1156         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1157         private static extern void SignValue(SafeKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash, int cbHash, ObjectHandleOnStack retSignature);
1158
1159         [System.Security.SecurityCritical]  // auto-generated
1160         internal static byte[] SignValue(SafeKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash)
1161         {
1162             byte[] signature = null;
1163             SignValue(hKey, keyNumber, calgKey, calgHash, hash, hash.Length, JitHelpers.GetObjectHandleOnStack(ref signature));
1164             return signature;
1165         }
1166
1167         [System.Security.SecurityCritical]  // auto-generated
1168         [ResourceExposure(ResourceScope.None)]
1169         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1170         private static extern bool VerifySign(SafeKeyHandle hKey, int calgKey, int calgHash, byte[] hash, int cbHash, byte[] signature, int cbSignature);
1171
1172         [System.Security.SecurityCritical]  // auto-generated
1173         internal static bool VerifySign(SafeKeyHandle hKey, int calgKey, int calgHash, byte[] hash, byte[] signature)
1174         {
1175             return VerifySign(hKey, calgKey, calgHash, hash, hash.Length, signature, signature.Length);
1176         }
1177
1178         [System.Security.SecurityCritical]  // auto-generated
1179         [ResourceExposure(ResourceScope.Machine)]
1180         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1181         internal static extern void _CreateCSP(CspParameters param, bool randomKeyContainer, ref SafeProvHandle hProv);
1182         [System.Security.SecurityCritical]  // auto-generated
1183         [ResourceExposure(ResourceScope.None)]
1184         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1185         internal static extern int _DecryptData(SafeKeyHandle hKey, byte[] data, int ib, int cb, ref byte[] outputBuffer, int outputOffset, PaddingMode PaddingMode, bool fDone);
1186         [System.Security.SecurityCritical]  // auto-generated
1187         [ResourceExposure(ResourceScope.None)]
1188         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1189         internal static extern int _EncryptData(SafeKeyHandle hKey, byte[] data, int ib, int cb, ref byte[] outputBuffer, int outputOffset, PaddingMode PaddingMode, bool fDone);
1190         [System.Security.SecurityCritical]  // auto-generated
1191         [ResourceExposure(ResourceScope.None)]
1192         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1193         internal static extern void _ExportKey(SafeKeyHandle hKey, int blobType, object cspObject);
1194         [System.Security.SecurityCritical]  // auto-generated
1195         [ResourceExposure(ResourceScope.None)]
1196         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1197         internal static extern void _GenerateKey(SafeProvHandle hProv, int algid, CspProviderFlags flags, int keySize, ref SafeKeyHandle hKey);
1198 #endif
1199 #endif // FEATURE_CRYPTO
1200 #if !MONO
1201         [System.Security.SecurityCritical]  // auto-generated
1202         [ResourceExposure(ResourceScope.None)]
1203         [MethodImpl(MethodImplOptions.InternalCall)]
1204         internal static extern bool _GetEnforceFipsPolicySetting();
1205 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
1206         [System.Security.SecurityCritical]  // auto-generated
1207         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1208         internal static extern byte[] _GetKeyParameter(SafeKeyHandle hKey, uint paramID);
1209 #if FEATURE_MACL
1210         [System.Security.SecurityCritical]  // auto-generated
1211         [ResourceExposure(ResourceScope.None)]
1212         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1213         internal static extern byte[] _GetKeySetSecurityInfo(SafeProvHandle hProv, SecurityInfos securityInfo, out int error);
1214 #endif //FEATURE_MACL
1215         [System.Security.SecurityCritical]  // auto-generated
1216         [ResourceExposure(ResourceScope.None)]
1217         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1218         internal static extern object _GetProviderParameter(SafeProvHandle hProv, int keyNumber, uint paramID);
1219         [System.Security.SecurityCritical]  // auto-generated
1220         [ResourceExposure(ResourceScope.None)]
1221         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1222         internal static extern int _GetUserKey(SafeProvHandle hProv, int keyNumber, ref SafeKeyHandle hKey);
1223         [System.Security.SecurityCritical]  // auto-generated
1224         [ResourceExposure(ResourceScope.None)]
1225         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1226         internal static extern void _ImportBulkKey(SafeProvHandle hProv, int algid, bool useSalt, byte[] key, ref SafeKeyHandle hKey);
1227         [System.Security.SecurityCritical]  // auto-generated
1228         [ResourceExposure(ResourceScope.None)]
1229         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1230         internal static extern int _ImportCspBlob(byte[] keyBlob, SafeProvHandle hProv, CspProviderFlags flags, ref SafeKeyHandle hKey);
1231         [System.Security.SecurityCritical]  // auto-generated
1232         [ResourceExposure(ResourceScope.None)]
1233         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1234         internal static extern void _ImportKey(SafeProvHandle hCSP, int keyNumber, CspProviderFlags flags, object cspObject, ref SafeKeyHandle hKey);
1235         [System.Security.SecurityCritical]  // auto-generated
1236         [ResourceExposure(ResourceScope.None)]
1237         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1238         internal static extern bool _ProduceLegacyHmacValues();
1239 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
1240         [System.Security.SecurityCritical]  // auto-generated
1241         [ResourceExposure(ResourceScope.Machine)]
1242         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1243         internal static extern int _OpenCSP(CspParameters param, uint flags, ref SafeProvHandle hProv);
1244         [System.Security.SecurityCritical]  // auto-generated
1245         [ResourceExposure(ResourceScope.Machine)]
1246         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1247         internal static extern void _AcquireCSP(CspParameters param, ref SafeProvHandle hProv);
1248
1249 #else
1250         internal static bool _ProduceLegacyHmacValues()
1251         {
1252 #if FULL_AOT_RUNTIME
1253             return false;
1254 #else
1255             return Environment.GetEnvironmentVariable ("legacyHMACMode") == "1";
1256 #endif
1257         }
1258 #endif
1259     }
1260 }
1261