3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>[....]</OWNER>
15 namespace System.Security.Cryptography
17 using Microsoft.Win32;
19 using System.Globalization;
20 using System.Runtime.CompilerServices;
21 using System.Runtime.InteropServices;
23 using System.Security.AccessControl;
24 #endif // FEATURE_MACL
25 using System.Security.Cryptography.X509Certificates;
26 using System.Security.Permissions;
27 #if FEATURE_IMPERSONATION
28 using System.Security.Principal;
29 #endif // FEATURE_IMPERSONATION
31 using System.Threading;
32 using System.Diagnostics.Contracts;
33 using System.Runtime.Versioning;
35 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
37 internal enum CspAlgorithmType {
42 internal enum CspAlgorithmType {
48 internal static class Constants {
49 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
50 internal const int S_OK = 0;
51 internal const int NTE_FILENOTFOUND = unchecked((int) 0x80070002); // The system cannot find the file specified.
52 internal const int NTE_NO_KEY = unchecked((int) 0x8009000D); // Key does not exist.
53 internal const int NTE_BAD_KEYSET = unchecked((int) 0x80090016); // Keyset does not exist.
54 internal const int NTE_KEYSET_NOT_DEF = unchecked((int) 0x80090019); // The keyset is not defined.
56 internal const int KP_IV = 1;
57 internal const int KP_MODE = 4;
58 internal const int KP_MODE_BITS = 5;
59 internal const int KP_EFFECTIVE_KEYLEN = 19;
61 internal const int ALG_CLASS_SIGNATURE = (1 << 13);
62 internal const int ALG_CLASS_DATA_ENCRYPT = (3 << 13);
63 internal const int ALG_CLASS_HASH = (4 << 13);
64 internal const int ALG_CLASS_KEY_EXCHANGE = (5 << 13);
66 internal const int ALG_TYPE_DSS = (1 << 9);
67 internal const int ALG_TYPE_RSA = (2 << 9);
68 internal const int ALG_TYPE_BLOCK = (3 << 9);
69 internal const int ALG_TYPE_STREAM = (4 << 9);
70 internal const int ALG_TYPE_ANY = (0);
72 internal const int CALG_MD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | 3);
73 internal const int CALG_SHA1 = (ALG_CLASS_HASH | ALG_TYPE_ANY | 4);
74 internal const int CALG_SHA_256 = (ALG_CLASS_HASH | ALG_TYPE_ANY | 12);
75 internal const int CALG_SHA_384 = (ALG_CLASS_HASH | ALG_TYPE_ANY | 13);
76 internal const int CALG_SHA_512 = (ALG_CLASS_HASH | ALG_TYPE_ANY | 14);
77 internal const int CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | 0);
78 internal const int CALG_RSA_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | 0);
79 internal const int CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | 0);
80 internal const int CALG_DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 1);
81 internal const int CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 2);
82 internal const int CALG_3DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 3);
83 internal const int CALG_3DES_112 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 9);
84 internal const int CALG_AES_128 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 14);
85 internal const int CALG_AES_192 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 15);
86 internal const int CALG_AES_256 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 16);
87 internal const int CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | 1);
88 #endif // FEATURE_CRYPTO
90 internal const int PROV_RSA_FULL = 1;
91 internal const int PROV_DSS_DH = 13;
92 internal const int PROV_RSA_AES = 24;
94 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
95 internal const int AT_KEYEXCHANGE = 1;
96 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
97 internal const int AT_SIGNATURE = 2;
98 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
99 internal const int PUBLICKEYBLOB = 0x6;
100 internal const int PRIVATEKEYBLOB = 0x7;
101 internal const int CRYPT_OAEP = 0x40;
104 internal const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
105 internal const uint CRYPT_NEWKEYSET = 0x00000008;
106 internal const uint CRYPT_DELETEKEYSET = 0x00000010;
107 internal const uint CRYPT_MACHINE_KEYSET = 0x00000020;
108 internal const uint CRYPT_SILENT = 0x00000040;
109 internal const uint CRYPT_EXPORTABLE = 0x00000001;
111 internal const uint CLR_KEYLEN = 1;
112 internal const uint CLR_PUBLICKEYONLY = 2;
113 internal const uint CLR_EXPORTABLE = 3;
114 internal const uint CLR_REMOVABLE = 4;
115 internal const uint CLR_HARDWARE = 5;
116 internal const uint CLR_ACCESSIBLE = 6;
117 internal const uint CLR_PROTECTED = 7;
118 internal const uint CLR_UNIQUE_CONTAINER = 8;
119 internal const uint CLR_ALGID = 9;
120 internal const uint CLR_PP_CLIENT_HWND = 10;
121 internal const uint CLR_PP_PIN = 11;
123 internal const string OID_RSA_SMIMEalgCMS3DESwrap = "1.2.840.113549.1.9.16.3.6";
124 internal const string OID_RSA_MD5 = "1.2.840.113549.2.5";
125 internal const string OID_RSA_RC2CBC = "1.2.840.113549.3.2";
126 internal const string OID_RSA_DES_EDE3_CBC = "1.2.840.113549.3.7";
127 internal const string OID_OIWSEC_desCBC = "1.3.14.3.2.7";
128 internal const string OID_OIWSEC_SHA1 = "1.3.14.3.2.26";
129 internal const string OID_OIWSEC_SHA256 = "2.16.840.1.101.3.4.2.1";
130 internal const string OID_OIWSEC_SHA384 = "2.16.840.1.101.3.4.2.2";
131 internal const string OID_OIWSEC_SHA512 = "2.16.840.1.101.3.4.2.3";
132 internal const string OID_OIWSEC_RIPEMD160 = "1.3.36.3.2.1";
133 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
136 internal static class Utils {
138 #if !FEATURE_PAL && FEATURE_CRYPTO
139 [SecuritySafeCritical]
145 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
146 // Private object for locking instead of locking on a public type for SQL reliability work.
147 private static Object s_InternalSyncObject = new Object();
149 private static Object InternalSyncObject {
150 get { return s_InternalSyncObject; }
152 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
154 // Provider type to use by default for RSA operations. On systems which support the RSA-AES CSP, we
155 // want to use that since it enables access to SHA-2 operations, downlevel we fall back to the
157 private static volatile int _defaultRsaProviderType;
158 private static volatile bool _haveDefaultRsaProviderType;
159 internal static int DefaultRsaProviderType
162 if (!_haveDefaultRsaProviderType)
164 // The AES CSP is only supported on WinXP and higher
166 bool osSupportsAesCsp = true;
168 bool osSupportsAesCsp = Environment.OSVersion.Platform == PlatformID.Win32NT &&
169 (Environment.OSVersion.Version.Major > 5 ||
170 (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1));
172 _defaultRsaProviderType = osSupportsAesCsp ? Constants.PROV_RSA_AES : Constants.PROV_RSA_FULL;
173 _haveDefaultRsaProviderType = true;
176 return _defaultRsaProviderType;
180 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
182 [System.Security.SecurityCritical] // auto-generated
183 private static volatile SafeProvHandle _safeProvHandle;
184 internal static SafeProvHandle StaticProvHandle {
185 [System.Security.SecurityCritical] // auto-generated
187 if (_safeProvHandle == null) {
188 lock (InternalSyncObject) {
189 if (_safeProvHandle == null) {
190 SafeProvHandle safeProvHandle = AcquireProvHandle(new CspParameters(DefaultRsaProviderType));
191 Thread.MemoryBarrier();
192 _safeProvHandle = safeProvHandle;
196 return _safeProvHandle;
199 #endif // !FEATURE_PAL
201 [System.Security.SecurityCritical] // auto-generated
202 private static volatile SafeProvHandle _safeDssProvHandle;
203 internal static SafeProvHandle StaticDssProvHandle {
204 [System.Security.SecurityCritical] // auto-generated
206 if (_safeDssProvHandle == null) {
207 lock (InternalSyncObject) {
208 if (_safeDssProvHandle == null) {
209 SafeProvHandle safeProvHandle = CreateProvHandle(new CspParameters(Constants.PROV_DSS_DH), true);
210 Thread.MemoryBarrier();
211 _safeDssProvHandle = safeProvHandle;
215 return _safeDssProvHandle;
220 [System.Security.SecurityCritical] // auto-generated
221 [ResourceExposure(ResourceScope.None)]
222 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
223 internal static SafeProvHandle AcquireProvHandle (CspParameters parameters) {
224 if (parameters == null)
225 parameters = new CspParameters(DefaultRsaProviderType);
227 SafeProvHandle safeProvHandle = SafeProvHandle.InvalidHandle;
228 Utils._AcquireCSP(parameters, ref safeProvHandle);
229 return safeProvHandle;
232 [System.Security.SecurityCritical] // auto-generated
233 [ResourceExposure(ResourceScope.None)]
234 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
235 internal static SafeProvHandle CreateProvHandle (CspParameters parameters, bool randomKeyContainer) {
236 SafeProvHandle safeProvHandle = SafeProvHandle.InvalidHandle;
237 int hr = Utils._OpenCSP(parameters, 0, ref safeProvHandle);
238 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
239 if (hr != Constants.S_OK) {
240 // If UseExistingKey flag is used and the key container does not exist
241 // throw an exception without attempting to create the container.
242 if ((parameters.Flags & CspProviderFlags.UseExistingKey) != 0 || (hr != Constants.NTE_KEYSET_NOT_DEF && hr != Constants.NTE_BAD_KEYSET && hr != Constants.NTE_FILENOTFOUND))
243 throw new CryptographicException(hr);
244 if (!randomKeyContainer) {
245 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
246 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Create);
247 kp.AccessEntries.Add(entry);
251 Utils._CreateCSP(parameters, randomKeyContainer, ref safeProvHandle);
253 if (!randomKeyContainer) {
254 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
255 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open);
256 kp.AccessEntries.Add(entry);
261 return safeProvHandle;
263 #endif // !FEATURE_PAL
266 [System.Security.SecurityCritical] // auto-generated
267 internal static CryptoKeySecurity GetKeySetSecurityInfo (SafeProvHandle hProv, AccessControlSections accessControlSections) {
268 SecurityInfos securityInfo = 0;
269 Privilege privilege = null;
271 if ((accessControlSections & AccessControlSections.Owner) != 0)
272 securityInfo |= SecurityInfos.Owner;
273 if ((accessControlSections & AccessControlSections.Group) != 0)
274 securityInfo |= SecurityInfos.Group;
275 if ((accessControlSections & AccessControlSections.Access) != 0)
276 securityInfo |= SecurityInfos.DiscretionaryAcl;
278 byte[] rawSecurityDescriptor = null;
281 RuntimeHelpers.PrepareConstrainedRegions();
283 if ((accessControlSections & AccessControlSections.Audit) != 0) {
284 securityInfo |= SecurityInfos.SystemAcl;
285 privilege = new Privilege("SeSecurityPrivilege");
288 rawSecurityDescriptor = _GetKeySetSecurityInfo(hProv, securityInfo, out error);
291 if (privilege != null)
295 // This means that the object doesn't have a security descriptor. And thus we throw
296 // a specific exception for the caller to catch and handle properly.
297 if (error == Win32Native.ERROR_SUCCESS && (rawSecurityDescriptor == null || rawSecurityDescriptor.Length == 0))
298 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoSecurityDescriptor"));
299 if (error == Win32Native.ERROR_NOT_ENOUGH_MEMORY)
300 throw new OutOfMemoryException();
301 if (error == Win32Native.ERROR_ACCESS_DENIED)
302 throw new UnauthorizedAccessException();
303 if (error == Win32Native.ERROR_PRIVILEGE_NOT_HELD)
304 throw new PrivilegeNotHeldException( "SeSecurityPrivilege" );
305 if (error != Win32Native.ERROR_SUCCESS)
306 throw new CryptographicException(error);
308 CommonSecurityDescriptor sd = new CommonSecurityDescriptor(false /* isContainer */,
310 new RawSecurityDescriptor(rawSecurityDescriptor, 0),
312 return new CryptoKeySecurity(sd);
315 [System.Security.SecurityCritical] // auto-generated
316 internal static void SetKeySetSecurityInfo (SafeProvHandle hProv, CryptoKeySecurity cryptoKeySecurity, AccessControlSections accessControlSections) {
317 SecurityInfos securityInfo = 0;
318 Privilege privilege = null;
320 if ((accessControlSections & AccessControlSections.Owner) != 0 && cryptoKeySecurity._securityDescriptor.Owner != null)
321 securityInfo |= SecurityInfos.Owner;
322 if ((accessControlSections & AccessControlSections.Group) != 0 && cryptoKeySecurity._securityDescriptor.Group != null)
323 securityInfo |= SecurityInfos.Group;
324 if ((accessControlSections & AccessControlSections.Audit) != 0)
325 securityInfo |= SecurityInfos.SystemAcl;
326 if ((accessControlSections & AccessControlSections.Access) != 0 && cryptoKeySecurity._securityDescriptor.IsDiscretionaryAclPresent)
327 securityInfo |= SecurityInfos.DiscretionaryAcl;
329 if (securityInfo == 0) {
330 // Nothing to persist
336 RuntimeHelpers.PrepareConstrainedRegions();
338 if ((securityInfo & SecurityInfos.SystemAcl) != 0) {
339 privilege = new Privilege("SeSecurityPrivilege");
343 byte[] sd = cryptoKeySecurity.GetSecurityDescriptorBinaryForm();
344 if (sd != null && sd.Length > 0)
345 error = SetKeySetSecurityInfo (hProv, securityInfo, sd);
348 if (privilege != null)
352 if (error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_INVALID_OWNER || error == Win32Native.ERROR_INVALID_PRIMARY_GROUP)
353 throw new UnauthorizedAccessException();
354 else if (error == Win32Native.ERROR_PRIVILEGE_NOT_HELD)
355 throw new PrivilegeNotHeldException("SeSecurityPrivilege");
356 else if (error == Win32Native.ERROR_INVALID_HANDLE)
357 throw new NotSupportedException(Environment.GetResourceString("AccessControl_InvalidHandle"));
358 else if (error != Win32Native.ERROR_SUCCESS)
359 throw new CryptographicException(error);
361 #endif //FEATURE_MACL
363 [System.Security.SecurityCritical] // auto-generated
364 internal static byte[] ExportCspBlobHelper (bool includePrivateParameters, CspParameters parameters, SafeKeyHandle safeKeyHandle) {
365 if (includePrivateParameters) {
366 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
367 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
368 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Export);
369 kp.AccessEntries.Add(entry);
374 Utils.ExportCspBlob(safeKeyHandle, includePrivateParameters ? Constants.PRIVATEKEYBLOB : Constants.PUBLICKEYBLOB, JitHelpers.GetObjectHandleOnStack(ref blob));
378 [System.Security.SecuritySafeCritical] // auto-generated
379 [ResourceExposure(ResourceScope.None)]
380 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
381 internal static void GetKeyPairHelper (CspAlgorithmType keyType, CspParameters parameters, bool randomKeyContainer, int dwKeySize, ref SafeProvHandle safeProvHandle, ref SafeKeyHandle safeKeyHandle) {
382 SafeProvHandle TempFetchedProvHandle = Utils.CreateProvHandle(parameters, randomKeyContainer);
385 // If the user wanted to set the security descriptor on the provider context, apply it now.
386 if (parameters.CryptoKeySecurity != null) {
387 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
388 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.ChangeAcl);
389 kp.AccessEntries.Add(entry);
391 SetKeySetSecurityInfo(TempFetchedProvHandle, parameters.CryptoKeySecurity, parameters.CryptoKeySecurity.ChangedAccessControlSections);
393 #endif //FEATURE_MACL
395 #if FEATURE_X509_SECURESTRINGS
396 // If the user wanted to specify a PIN or HWND for a smart card CSP, apply those settings now.
397 if (parameters.ParentWindowHandle != IntPtr.Zero)
398 SetProviderParameter(TempFetchedProvHandle, parameters.KeyNumber, Constants.CLR_PP_CLIENT_HWND, parameters.ParentWindowHandle);
399 else if (parameters.KeyPassword != null) {
400 IntPtr szPassword = Marshal.SecureStringToCoTaskMemAnsi(parameters.KeyPassword);
402 SetProviderParameter(TempFetchedProvHandle, parameters.KeyNumber, Constants.CLR_PP_PIN, szPassword);
405 if (szPassword != IntPtr.Zero)
406 Marshal.ZeroFreeCoTaskMemAnsi(szPassword);
409 #endif //FEATURE_X509_SECURESTRINGS
411 safeProvHandle = TempFetchedProvHandle;
413 // If the key already exists, use it, else generate a new one
414 SafeKeyHandle TempFetchedKeyHandle = SafeKeyHandle.InvalidHandle;
415 int hr = Utils._GetUserKey(safeProvHandle, parameters.KeyNumber, ref TempFetchedKeyHandle);
416 if (hr != Constants.S_OK) {
417 if ((parameters.Flags & CspProviderFlags.UseExistingKey) != 0 || hr != Constants.NTE_NO_KEY)
418 throw new CryptographicException(hr);
419 // _GenerateKey will check for failures and throw an exception
420 Utils._GenerateKey(safeProvHandle, parameters.KeyNumber, parameters.Flags, dwKeySize, ref TempFetchedKeyHandle);
423 // check that this is indeed an RSA/DSS key.
424 byte[] algid = (byte[]) Utils._GetKeyParameter(TempFetchedKeyHandle, Constants.CLR_ALGID);
425 int dwAlgId = (algid[0] | (algid[1] << 8) | (algid[2] << 16) | (algid[3] << 24));
426 if ((keyType == CspAlgorithmType.Rsa && dwAlgId != Constants.CALG_RSA_KEYX && dwAlgId != Constants.CALG_RSA_SIGN) ||
427 (keyType == CspAlgorithmType.Dss && dwAlgId != Constants.CALG_DSS_SIGN)) {
428 TempFetchedKeyHandle.Dispose();
429 throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_WrongKeySpec"));
432 safeKeyHandle = TempFetchedKeyHandle;
435 [System.Security.SecurityCritical] // auto-generated
436 internal static void ImportCspBlobHelper (CspAlgorithmType keyType, byte[] keyBlob, bool publicOnly, ref CspParameters parameters, bool randomKeyContainer, ref SafeProvHandle safeProvHandle, ref SafeKeyHandle safeKeyHandle) {
437 // Free the current key handle
438 if (safeKeyHandle != null && !safeKeyHandle.IsClosed)
439 safeKeyHandle.Dispose();
440 safeKeyHandle = SafeKeyHandle.InvalidHandle;
443 parameters.KeyNumber = Utils._ImportCspBlob(keyBlob, keyType == CspAlgorithmType.Dss ? Utils.StaticDssProvHandle : Utils.StaticProvHandle, (CspProviderFlags) 0, ref safeKeyHandle);
445 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
446 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
447 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Import);
448 kp.AccessEntries.Add(entry);
451 if (safeProvHandle == null)
452 safeProvHandle = Utils.CreateProvHandle(parameters, randomKeyContainer);
453 parameters.KeyNumber = Utils._ImportCspBlob(keyBlob, safeProvHandle, parameters.Flags, ref safeKeyHandle);
456 #endif // FEATURE_CRYPTO
458 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
459 [System.Security.SecurityCritical] // auto-generated
460 [ResourceExposure(ResourceScope.None)]
461 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
462 internal static CspParameters SaveCspParameters (CspAlgorithmType keyType, CspParameters userParameters, CspProviderFlags defaultFlags, ref bool randomKeyContainer) {
464 CspParameters parameters;
465 if (userParameters == null) {
466 parameters = new CspParameters(keyType == CspAlgorithmType.Dss ? Constants.PROV_DSS_DH : DefaultRsaProviderType, null, null, defaultFlags);
468 ValidateCspFlags(userParameters.Flags);
469 parameters = new CspParameters(userParameters);
472 if (parameters.KeyNumber == -1)
473 parameters.KeyNumber = keyType == CspAlgorithmType.Dss ? Constants.AT_SIGNATURE : Constants.AT_KEYEXCHANGE;
474 else if (parameters.KeyNumber == Constants.CALG_DSS_SIGN || parameters.KeyNumber == Constants.CALG_RSA_SIGN)
475 parameters.KeyNumber = Constants.AT_SIGNATURE;
476 else if (parameters.KeyNumber == Constants.CALG_RSA_KEYX)
477 parameters.KeyNumber = Constants.AT_KEYEXCHANGE;
479 // If no key container was specified and UseDefaultKeyContainer is not used, then use CRYPT_VERIFYCONTEXT
480 // to generate an ephemeral key
481 randomKeyContainer = (parameters.Flags & CspProviderFlags.CreateEphemeralKey) == CspProviderFlags.CreateEphemeralKey;
482 if (parameters.KeyContainerName == null && (parameters.Flags & CspProviderFlags.UseDefaultKeyContainer) == 0) {
483 parameters.Flags |= CspProviderFlags.CreateEphemeralKey;
484 randomKeyContainer = true;
490 [System.Security.SecurityCritical] // auto-generated
491 private static void ValidateCspFlags (CspProviderFlags flags) {
492 // check that the flags are consistent.
493 if ((flags & CspProviderFlags.UseExistingKey) != 0) {
494 CspProviderFlags keyFlags = (CspProviderFlags.UseNonExportableKey | CspProviderFlags.UseArchivableKey | CspProviderFlags.UseUserProtectedKey);
495 if ((flags & keyFlags) != CspProviderFlags.NoFlags)
496 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"));
499 // make sure we are allowed to display the key protection UI if a user protected key is requested.
500 if ((flags & CspProviderFlags.UseUserProtectedKey) != 0) {
501 // UI only allowed in interactive session.
502 if (!System.Environment.UserInteractive)
503 throw new InvalidOperationException(Environment.GetResourceString("Cryptography_NotInteractive"));
505 // we need to demand UI permission here.
506 UIPermission uiPermission = new UIPermission(UIPermissionWindow.SafeTopLevelWindows);
507 uiPermission.Demand();
510 #endif // FEATURE_CRYPTO
512 private static volatile RNGCryptoServiceProvider _rng = null;
513 internal static RNGCryptoServiceProvider StaticRandomNumberGenerator {
516 _rng = new RNGCryptoServiceProvider();
522 // internal static methods
525 internal static byte[] GenerateRandom (int keySize) {
526 byte[] key = new byte[keySize];
527 StaticRandomNumberGenerator.GetBytes(key);
533 /// Read the FIPS policy from the pre-Vista registry key
536 /// True if the FIPS policy is enabled, false otherwise. An error reading the policy key is
537 /// interpreted as if the policy is enabled, and a missing key is interpreted as the policy being
540 [System.Security.SecurityCritical] // auto-generated
541 [RegistryPermissionAttribute(SecurityAction.Assert, Read="HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Lsa")]
542 internal static bool ReadLegacyFipsPolicy()
544 Contract.Assert(Environment.OSVersion.Version.Major < 6, "CryptGetFIPSAlgorithmMode should be used on Vista+");
548 using (RegistryKey fipsAlgorithmPolicyKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Lsa", false))
550 if (fipsAlgorithmPolicyKey == null)
553 object data = fipsAlgorithmPolicyKey.GetValue("FIPSAlgorithmPolicy");
559 else if (fipsAlgorithmPolicyKey.GetValueKind("FIPSAlgorithmPolicy") != RegistryValueKind.DWord)
565 return ((int)data != 0);
569 catch (SecurityException)
571 // If we could not open the registry key, we'll assume the setting is to enforce FIPS policy.
575 #endif //FEATURE_CRYPTO
577 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
578 // dwKeySize = 0 means the default key size
579 [System.Security.SecurityCritical] // auto-generated
580 internal static bool HasAlgorithm (int dwCalg, int dwKeySize) {
585 // We need to take a lock here since we are querying the provider handle in a loop.
586 // If multiple threads are racing in this code, not all algorithms/key sizes combinations
587 // will be examined; which may lead to a situation where false is wrongfully returned.
588 lock (InternalSyncObject) {
589 r = SearchForAlgorithm(StaticProvHandle, dwCalg, dwKeySize);
595 internal static int ObjToAlgId(object hashAlg, OidGroup group) {
597 throw new ArgumentNullException("hashAlg");
598 Contract.EndContractBlock();
600 string oidValue = null;
601 string hashAlgString = hashAlg as string;
602 if (hashAlgString != null) {
603 oidValue = CryptoConfig.MapNameToOID(hashAlgString, group);
604 if (oidValue == null)
605 oidValue = hashAlgString; // maybe we were passed the OID value
607 else if (hashAlg is HashAlgorithm) {
608 oidValue = CryptoConfig.MapNameToOID(hashAlg.GetType().ToString(), group);
610 else if (hashAlg is Type) {
611 oidValue = CryptoConfig.MapNameToOID(hashAlg.ToString(), group);
614 if (oidValue == null)
615 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
617 return X509Utils.GetAlgIdFromOid(oidValue, group);
620 internal static HashAlgorithm ObjToHashAlgorithm (Object hashAlg) {
622 throw new ArgumentNullException("hashAlg");
623 Contract.EndContractBlock();
625 HashAlgorithm hash = null;
626 if (hashAlg is String) {
627 hash = (HashAlgorithm) CryptoConfig.CreateFromName((string) hashAlg);
629 string oidFriendlyName = X509Utils.GetFriendlyNameFromOid((string) hashAlg, OidGroup.HashAlgorithm);
630 if (oidFriendlyName != null)
631 hash = (HashAlgorithm) CryptoConfig.CreateFromName(oidFriendlyName);
634 else if (hashAlg is HashAlgorithm) {
635 hash = (HashAlgorithm) hashAlg;
637 else if (hashAlg is Type) {
638 hash = (HashAlgorithm) CryptoConfig.CreateFromName(hashAlg.ToString());
642 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
647 internal static String DiscardWhiteSpaces (string inputBuffer) {
648 return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length);
651 internal static String DiscardWhiteSpaces (string inputBuffer, int inputOffset, int inputCount) {
653 for (i=0; i<inputCount; i++)
654 if (Char.IsWhiteSpace(inputBuffer[inputOffset + i])) iCount++;
655 char[] output = new char[inputCount - iCount];
657 for (i=0; i<inputCount; i++) {
658 if (!Char.IsWhiteSpace(inputBuffer[inputOffset + i]))
659 output[iCount++] = inputBuffer[inputOffset + i];
661 return new String(output);
664 internal static int ConvertByteArrayToInt (byte[] input) {
665 // Input to this routine is always big endian
667 for (int i = 0; i < input.Length; i++) {
669 dwOutput += input[i];
674 // output of this routine is always big endian
675 internal static byte[] ConvertIntToByteArray (int dwInput) {
676 byte[] temp = new byte[8]; // int can never be greater than Int64
677 int t1; // t1 is remaining value to account for
678 int t2; // t2 is t1 % 256
681 if (dwInput == 0) return new byte[1];
684 Contract.Assert(i < 8, "Got too big an int here!");
691 // Now, copy only the non-zero part of temp and reverse
692 byte[] output = new byte[i];
693 // copy and reverse in one pass
694 for (int j = 0; j < i; j++) {
695 output[j] = temp[i-j-1];
700 // output is little endian
701 internal static void ConvertIntToByteArray (uint dwInput, ref byte[] counter) {
702 uint t1 = dwInput; // t1 is remaining value to account for
703 uint t2; // t2 is t1 % 256
706 // clear the array first
707 Array.Clear(counter, 0, counter.Length);
708 if (dwInput == 0) return;
710 Contract.Assert(i < 4, "Got too big an int here!");
712 counter[3 - i] = (byte) t2;
718 internal static byte[] FixupKeyParity (byte[] key) {
719 byte[] oddParityKey = new byte[key.Length];
720 for (int index=0; index < key.Length; index++) {
721 // Get the bits we are interested in
722 oddParityKey[index] = (byte) (key[index] & 0xfe);
723 // Get the parity of the sum of the previous bits
724 byte tmp1 = (byte)((oddParityKey[index] & 0xF) ^ (oddParityKey[index] >> 4));
725 byte tmp2 = (byte)((tmp1 & 0x3) ^ (tmp1 >> 2));
726 byte sumBitsMod2 = (byte)((tmp2 & 0x1) ^ (tmp2 >> 1));
727 // We need to set the last bit in oddParityKey[index] to the negation
728 // of the last bit in sumBitsMod2
729 if (sumBitsMod2 == 0)
730 oddParityKey[index] |= 1;
735 // digits == number of DWORDs
736 [System.Security.SecurityCritical] // auto-generated
737 internal unsafe static void DWORDFromLittleEndian (uint* x, int digits, byte* block) {
741 for (i = 0, j = 0; i < digits; i++, j += 4)
742 x[i] = (uint) (block[j] | (block[j+1] << 8) | (block[j+2] << 16) | (block[j+3] << 24));
745 // encodes x (DWORD) into block (unsigned char), least significant byte first.
746 // digits == number of DWORDs
747 internal static void DWORDToLittleEndian (byte[] block, uint[] x, int digits) {
751 for (i = 0, j = 0; i < digits; i++, j += 4) {
752 block[j] = (byte)(x[i] & 0xff);
753 block[j+1] = (byte)((x[i] >> 8) & 0xff);
754 block[j+2] = (byte)((x[i] >> 16) & 0xff);
755 block[j+3] = (byte)((x[i] >> 24) & 0xff);
758 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
760 // digits == number of DWORDs
761 [System.Security.SecurityCritical] // auto-generated
762 internal unsafe static void DWORDFromBigEndian (uint* x, int digits, byte* block) {
766 for (i = 0, j = 0; i < digits; i++, j += 4)
767 x[i] = (uint)((block[j] << 24) | (block[j + 1] << 16) | (block[j + 2] << 8) | block[j + 3]);
770 // encodes x (DWORD) into block (unsigned char), most significant byte first.
771 // digits == number of DWORDs
772 internal static void DWORDToBigEndian (byte[] block, uint[] x, int digits) {
776 for (i = 0, j = 0; i < digits; i++, j += 4) {
777 block[j] = (byte)((x[i] >> 24) & 0xff);
778 block[j+1] = (byte)((x[i] >> 16) & 0xff);
779 block[j+2] = (byte)((x[i] >> 8) & 0xff);
780 block[j+3] = (byte)(x[i] & 0xff);
784 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
785 // digits == number of QWORDs
786 [System.Security.SecurityCritical] // auto-generated
787 internal unsafe static void QuadWordFromBigEndian (UInt64* x, int digits, byte* block) {
791 for (i = 0, j = 0; i < digits; i++, j += 8)
793 (((UInt64)block[j]) << 56) | (((UInt64)block[j+1]) << 48) |
794 (((UInt64)block[j+2]) << 40) | (((UInt64)block[j+3]) << 32) |
795 (((UInt64)block[j+4]) << 24) | (((UInt64)block[j+5]) << 16) |
796 (((UInt64)block[j+6]) << 8) | ((UInt64)block[j+7])
800 // encodes x (DWORD) into block (unsigned char), most significant byte first.
801 // digits = number of QWORDS
802 internal static void QuadWordToBigEndian (byte[] block, UInt64[] x, int digits) {
806 for (i = 0, j = 0; i < digits; i++, j += 8) {
807 block[j] = (byte)((x[i] >> 56) & 0xff);
808 block[j+1] = (byte)((x[i] >> 48) & 0xff);
809 block[j+2] = (byte)((x[i] >> 40) & 0xff);
810 block[j+3] = (byte)((x[i] >> 32) & 0xff);
811 block[j+4] = (byte)((x[i] >> 24) & 0xff);
812 block[j+5] = (byte)((x[i] >> 16) & 0xff);
813 block[j+6] = (byte)((x[i] >> 8) & 0xff);
814 block[j+7] = (byte)(x[i] & 0xff);
817 #endif // FEATURE_CRYPTO
819 // encodes the integer i into a 4-byte array, in big endian.
820 internal static byte[] Int(uint i) {
821 return unchecked(new byte[] { (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i });
825 // PKCS #1 v.2.1, Section 4.2
826 // OS2IP converts an octet string to a nonnegative integer.
827 static byte[] OS2IP (byte[] x)
830 while ((x [i++] == 0x00) && (i < x.Length)) {
831 // confuse compiler into reporting a warning with {}
835 byte[] result = new byte [x.Length - i];
836 Buffer.BlockCopy (x, i, result, 0, result.Length);
843 static byte[] I2OSP (int x, int size)
845 byte[] array = Mono.Security.BitConverterLE.GetBytes (x);
846 Array.Reverse (array, 0, array.Length);
847 return I2OSP (array, size);
850 static byte[] I2OSP (byte[] x, int size)
852 byte[] result = new byte [size];
853 Buffer.BlockCopy (x, 0, result, (result.Length - x.Length), x.Length);
857 // PKCS #1 v.2.1, Section 5.1.1
858 static byte[] RSAEP (RSA rsa, byte[] m)
861 return rsa.EncryptValue (m);
864 // PKCS #1 v.2.1, Section B.2.1
865 static byte[] MGF1 (HashAlgorithm hash, byte[] mgfSeed, int maskLen)
867 // 1. If maskLen > 2^32 hLen, output "mask too long" and stop.
868 // easy - this is impossible by using a int (31bits) as parameter ;-)
869 // BUT with a signed int we do have to check for negative values!
871 throw new OverflowException();
873 int mgfSeedLength = mgfSeed.Length;
874 int hLen = (hash.HashSize >> 3); // from bits to bytes
875 int iterations = (maskLen / hLen);
876 if (maskLen % hLen != 0)
878 // 2. Let T be the empty octet string.
879 byte[] T = new byte [iterations * hLen];
881 byte[] toBeHashed = new byte [mgfSeedLength + 4];
883 // 3. For counter from 0 to \ceil (maskLen / hLen) - 1, do the following:
884 for (int counter = 0; counter < iterations; counter++) {
885 // a. Convert counter to an octet string C of length 4 octets
886 byte[] C = I2OSP (counter, 4);
888 // b. Concatenate the hash of the seed mgfSeed and C to the octet string T:
889 // T = T || Hash (mgfSeed || C)
890 Buffer.BlockCopy (mgfSeed, 0, toBeHashed, 0, mgfSeedLength);
891 Buffer.BlockCopy (C, 0, toBeHashed, mgfSeedLength, 4);
892 byte[] output = hash.ComputeHash (toBeHashed);
893 Buffer.BlockCopy (output, 0, T, pos, hLen);
897 // 4. Output the leading maskLen octets of T as the octet string mask.
898 byte[] mask = new byte [maskLen];
899 Buffer.BlockCopy (T, 0, mask, 0, maskLen);
904 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
905 [System.Security.SecurityCritical] // auto-generated
906 internal static byte[] RsaOaepEncrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) {
908 // It looks like .net managed implementation is buggy. It returns quite different
909 // result compare to old mono code, even PSLength calculation is quite different
911 int size = rsa.KeySize / 8;
912 int hLen = hash.HashSize / 8;
913 if (data.Length > size - 2 * hLen - 2)
914 throw new CryptographicException(String.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), size-2-2*hLen));
915 // empty label L SHA1 hash
916 byte[] lHash = hash.ComputeHash (EmptyArray<Byte>.Value);
917 int PSLength = (size - data.Length - 2 * hLen - 2);
918 // DB = lHash || PS || 0x01 || M
919 byte[] DB = new byte [lHash.Length + PSLength + 1 + data.Length];
920 Buffer.BlockCopy (lHash, 0, DB, 0, lHash.Length);
921 DB [(lHash.Length + PSLength)] = 0x01;
922 Buffer.BlockCopy (data, 0, DB, (DB.Length - data.Length), data.Length);
924 byte[] seed = new byte [hLen];
927 byte[] dbMask = MGF1 (hash, seed, size - hLen - 1);
929 // 5. Xor maskDB into DB
930 byte[] maskedDB = new byte[DB.Length];
931 for (int i=0; i < DB.Length; i++) {
932 maskedDB[i] = (byte) (DB[i] ^ dbMask[i]);
935 byte[] seedMask = MGF1 (hash, maskedDB, hLen);
937 // 7. Xor mask into seed
938 byte[] maskedSeed = new byte[seed.Length];
939 for (int i=0; i < seed.Length; i++) {
940 maskedSeed[i] = (byte) (seed[i] ^ seedMask[i]);
943 // EM = 0x00 || maskedSeed || maskedDB
944 byte[] EM = new byte [maskedSeed.Length + maskedDB.Length + 1];
945 Buffer.BlockCopy (maskedSeed, 0, EM, 1, maskedSeed.Length);
946 Buffer.BlockCopy (maskedDB, 0, EM, maskedSeed.Length + 1, maskedDB.Length);
948 byte[] m = OS2IP (EM);
949 byte[] c = RSAEP (rsa, m);
950 return I2OSP (c, size);
952 int cb = rsa.KeySize / 8;
954 // 1. Hash the parameters to get PHash
955 int cbHash = hash.HashSize / 8;
956 if ((data.Length + 2 + 2*cbHash) > cb)
957 throw new CryptographicException(String.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), cb-2-2*cbHash));
958 hash.ComputeHash(EmptyArray<Byte>.Value); // Use an empty octet string
960 // 2. Create DB object
961 byte[] DB = new byte[cb - cbHash + 1];
963 // Structure is as follows:
964 // pHash || PS || 01 || M
965 // PS consists of all zeros
967 Buffer.InternalBlockCopy(hash.Hash, 0, DB, 0, cbHash);
968 DB[DB.Length - data.Length - 1] = 1;
969 Buffer.InternalBlockCopy(data, 0, DB, DB.Length-data.Length, data.Length);
971 // 3. Create a random value of size hLen
972 byte[] seed = new byte[cbHash];
975 // 4. Compute the mask value
976 byte[] mask = mgf.GenerateMask(seed, DB.Length);
978 // 5. Xor maskDB into DB
979 for (int i=0; i < DB.Length; i++) {
980 DB[i] = (byte) (DB[i] ^ mask[i]);
983 // 6. Compute seed mask value
984 mask = mgf.GenerateMask(DB, cbHash);
986 // 7. Xor mask into seed
987 for (int i=0; i < seed.Length; i++) {
991 // 8. Concatenate seed and DB to form value to encrypt
992 byte[] pad = new byte[cb];
993 Buffer.InternalBlockCopy(seed, 0, pad, 0, seed.Length);
994 Buffer.InternalBlockCopy(DB, 0, pad, seed.Length, DB.Length);
996 return rsa.EncryptValue(pad);
1000 [System.Security.SecurityCritical] // auto-generated
1001 internal static byte[] RsaOaepDecrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) {
1002 int cb = rsa.KeySize / 8;
1004 // 1. Decode the input data
1005 // It is important that the Integer to Octet String conversion errors be indistinguishable from the other decoding
1006 // errors to protect against chosen cipher text attacks
1007 // A lecture given by James Manger during Crypto 2001 explains the issue in details
1010 data = rsa.DecryptValue(encryptedData);
1012 catch (CryptographicException) {
1013 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
1016 // 2. Create the hash object so we can get its size info.
1017 int cbHash = hash.HashSize / 8;
1019 // 3. Let maskedSeed be the first hLen octects and maskedDB
1020 // be the remaining bytes.
1021 int zeros = cb - data.Length;
1022 if (zeros < 0 || zeros >= cbHash)
1023 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
1026 int leading_zeros = 0;
1027 for (leading_zeros = 0; data [leading_zeros] == 0 && leading_zeros < data.Length - 1; ++leading_zeros);
1029 const int leading_zeros = 0;
1031 byte[] seed = new byte[cbHash];
1032 Buffer.InternalBlockCopy(data, leading_zeros, seed, zeros, seed.Length - zeros);
1034 byte[] DB = new byte[data.Length - seed.Length + zeros - leading_zeros];
1035 Buffer.InternalBlockCopy(data, seed.Length - zeros + leading_zeros, DB, 0, DB.Length);
1037 // 4. seedMask = MGF(maskedDB, hLen);
1038 byte[] mask = mgf.GenerateMask(DB, seed.Length);
1040 // 5. seed = seedMask XOR maskedSeed
1042 for (i=0; i < seed.Length; i++) {
1046 // 6. dbMask = MGF(seed, |EM| - hLen);
1047 mask = mgf.GenerateMask(seed, DB.Length);
1049 // 7. DB = maskedDB xor dbMask
1050 for (i=0; i < DB.Length; i++) {
1051 DB[i] = (byte) (DB[i] ^ mask[i]);
1054 // 8. pHash = HASH(P)
1055 hash.ComputeHash(EmptyArray<Byte>.Value);
1057 // 9. DB = pHash' || PS || 01 || M
1058 // 10. Check that pHash = pHash'
1060 byte[] hashValue = hash.Hash;
1061 for (i=0; i < cbHash; i++) {
1062 if (DB[i] != hashValue[i])
1063 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
1066 // Check that PS is all zeros
1067 for (; i<DB.Length; i++) {
1070 else if (DB[i] != 0)
1071 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
1075 throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding"));
1077 i++; // skip over the one
1080 byte[] output = new byte[DB.Length - i];
1081 Buffer.InternalBlockCopy(DB, i, output, 0, output.Length);
1085 [System.Security.SecurityCritical] // auto-generated
1086 internal static byte[] RsaPkcs1Padding (RSA rsa, byte[] oid, byte[] hash) {
1087 int cb = rsa.KeySize/8;
1088 byte[] pad = new byte[cb];
1091 // We want to pad this to the following format:
1093 // 00 || 01 || FF ... FF || 00 || prefix || Data
1095 // We want basically to ASN 1 encode the OID + hash:
1098 // OID <hash algorithm OID>
1099 // NULL (0x05 0x00) // this is actually an ANY and contains the parameters of the algorithm specified by the OID, I think
1101 // OCTET STRING <hashvalue>
1105 // Get the correct prefix
1106 byte[] data = new byte[oid.Length + 8 + hash.Length];
1107 data[0] = 0x30; // a structure follows
1108 int tmp = data.Length - 2;
1109 data[1] = (byte) tmp;
1111 tmp = oid.Length + 2;
1112 data[3] = (byte) tmp;
1113 Buffer.InternalBlockCopy(oid, 0, data, 4, oid.Length);
1114 data[4 + oid.Length] = 0x05;
1115 data[4 + oid.Length + 1] = 0x00;
1116 data[4 + oid.Length + 2] = 0x04; // an octet string follows
1117 data[4 + oid.Length + 3] = (byte) hash.Length;
1118 Buffer.InternalBlockCopy(hash, 0, data, oid.Length + 8, hash.Length);
1120 // Construct the whole array
1121 int cb1 = cb - data.Length;
1123 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_InvalidOID"));
1127 for (int i=2; i<cb1-1; i++) {
1131 Buffer.InternalBlockCopy(data, 0, pad, cb1, data.Length);
1135 // This routine compares 2 big ints; ignoring any leading zeros
1136 internal static bool CompareBigIntArrays (byte[] lhs, byte[] rhs) {
1138 return (rhs == null);
1141 while (i < lhs.Length && lhs[i] == 0) i++;
1142 while (j < rhs.Length && rhs[j] == 0) j++;
1144 int count = (lhs.Length - i);
1145 if ((rhs.Length - j) != count)
1148 for (int k = 0; k < count; k++) {
1149 if (lhs[i + k] != rhs[j + k])
1155 [System.Security.SecurityCritical] // auto-generated
1156 [ResourceExposure(ResourceScope.None)] // Creates a process resource, but it can't be scoped.
1157 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1158 internal static extern SafeHashHandle CreateHash(SafeProvHandle hProv, int algid);
1160 [System.Security.SecurityCritical] // auto-generated
1161 [ResourceExposure(ResourceScope.None)]
1162 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1163 private static extern void EndHash(SafeHashHandle hHash, ObjectHandleOnStack retHash);
1165 [System.Security.SecurityCritical] // auto-generated
1166 internal static byte[] EndHash(SafeHashHandle hHash)
1169 EndHash(hHash, JitHelpers.GetObjectHandleOnStack(ref hash));
1173 [System.Security.SecurityCritical] // auto-generated
1174 [ResourceExposure(ResourceScope.None)]
1175 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1176 private static extern void ExportCspBlob(SafeKeyHandle hKey, int blobType, ObjectHandleOnStack retBlob);
1178 [System.Security.SecurityCritical] // auto-generated
1179 [ResourceExposure(ResourceScope.None)]
1180 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1181 internal static extern bool GetPersistKeyInCsp(SafeProvHandle hProv);
1183 [System.Security.SecurityCritical] // auto-generated
1184 [ResourceExposure(ResourceScope.None)]
1185 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1186 private static extern void HashData(SafeHashHandle hHash, byte[] data, int cbData, int ibStart, int cbSize);
1188 [System.Security.SecurityCritical] // auto-generated
1189 internal static void HashData(SafeHashHandle hHash, byte[] data, int ibStart, int cbSize)
1191 HashData(hHash, data, data.Length, ibStart, cbSize);
1194 [System.Security.SecurityCritical] // auto-generated
1195 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1196 [ResourceExposure(ResourceScope.None)]
1197 private static extern bool SearchForAlgorithm(SafeProvHandle hProv, int algID, int keyLength);
1199 [System.Security.SecurityCritical] // auto-generated
1200 [ResourceExposure(ResourceScope.None)]
1201 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1202 internal static extern void SetKeyParamDw(SafeKeyHandle hKey, int param, int dwValue);
1204 [System.Security.SecurityCritical] // auto-generated
1205 [ResourceExposure(ResourceScope.None)]
1206 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1207 internal static extern void SetKeyParamRgb(SafeKeyHandle hKey, int param, byte[] value, int cbValue);
1210 [System.Security.SecurityCritical] // auto-generated
1211 [ResourceExposure(ResourceScope.None)]
1212 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1213 private static extern int SetKeySetSecurityInfo(SafeProvHandle hProv, SecurityInfos securityInfo, byte[] sd);
1214 #endif //FEATURE_MACL
1215 [System.Security.SecurityCritical] // auto-generated
1216 [ResourceExposure(ResourceScope.None)]
1217 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1218 internal static extern void SetPersistKeyInCsp(SafeProvHandle hProv, bool fPersistKeyInCsp);
1220 [System.Security.SecurityCritical] // auto-generated
1221 [ResourceExposure(ResourceScope.None)]
1222 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1223 internal static extern void SetProviderParameter(SafeProvHandle hProv, int keyNumber, uint paramID, IntPtr pbData);
1225 [System.Security.SecurityCritical] // auto-generated
1226 [ResourceExposure(ResourceScope.None)]
1227 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1228 private static extern void SignValue(SafeKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash, int cbHash, ObjectHandleOnStack retSignature);
1230 [System.Security.SecurityCritical] // auto-generated
1231 internal static byte[] SignValue(SafeKeyHandle hKey, int keyNumber, int calgKey, int calgHash, byte[] hash)
1233 byte[] signature = null;
1234 SignValue(hKey, keyNumber, calgKey, calgHash, hash, hash.Length, JitHelpers.GetObjectHandleOnStack(ref signature));
1238 [System.Security.SecurityCritical] // auto-generated
1239 [ResourceExposure(ResourceScope.None)]
1240 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1241 private static extern bool VerifySign(SafeKeyHandle hKey, int calgKey, int calgHash, byte[] hash, int cbHash, byte[] signature, int cbSignature);
1243 [System.Security.SecurityCritical] // auto-generated
1244 internal static bool VerifySign(SafeKeyHandle hKey, int calgKey, int calgHash, byte[] hash, byte[] signature)
1246 return VerifySign(hKey, calgKey, calgHash, hash, hash.Length, signature, signature.Length);
1249 [System.Security.SecurityCritical] // auto-generated
1250 [ResourceExposure(ResourceScope.Machine)]
1251 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1252 internal static extern void _CreateCSP(CspParameters param, bool randomKeyContainer, ref SafeProvHandle hProv);
1253 [System.Security.SecurityCritical] // auto-generated
1254 [ResourceExposure(ResourceScope.None)]
1255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1256 internal static extern int _DecryptData(SafeKeyHandle hKey, byte[] data, int ib, int cb, ref byte[] outputBuffer, int outputOffset, PaddingMode PaddingMode, bool fDone);
1257 [System.Security.SecurityCritical] // auto-generated
1258 [ResourceExposure(ResourceScope.None)]
1259 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1260 internal static extern int _EncryptData(SafeKeyHandle hKey, byte[] data, int ib, int cb, ref byte[] outputBuffer, int outputOffset, PaddingMode PaddingMode, bool fDone);
1261 [System.Security.SecurityCritical] // auto-generated
1262 [ResourceExposure(ResourceScope.None)]
1263 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1264 internal static extern void _ExportKey(SafeKeyHandle hKey, int blobType, object cspObject);
1265 [System.Security.SecurityCritical] // auto-generated
1266 [ResourceExposure(ResourceScope.None)]
1267 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1268 internal static extern void _GenerateKey(SafeProvHandle hProv, int algid, CspProviderFlags flags, int keySize, ref SafeKeyHandle hKey);
1270 #endif // FEATURE_CRYPTO
1272 [System.Security.SecurityCritical] // auto-generated
1273 [ResourceExposure(ResourceScope.None)]
1274 [MethodImpl(MethodImplOptions.InternalCall)]
1275 internal static extern bool _GetEnforceFipsPolicySetting();
1276 #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
1277 [System.Security.SecurityCritical] // auto-generated
1278 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1279 internal static extern byte[] _GetKeyParameter(SafeKeyHandle hKey, uint paramID);
1281 [System.Security.SecurityCritical] // auto-generated
1282 [ResourceExposure(ResourceScope.None)]
1283 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1284 internal static extern byte[] _GetKeySetSecurityInfo(SafeProvHandle hProv, SecurityInfos securityInfo, out int error);
1285 #endif //FEATURE_MACL
1286 [System.Security.SecurityCritical] // auto-generated
1287 [ResourceExposure(ResourceScope.None)]
1288 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1289 internal static extern object _GetProviderParameter(SafeProvHandle hProv, int keyNumber, uint paramID);
1290 [System.Security.SecurityCritical] // auto-generated
1291 [ResourceExposure(ResourceScope.None)]
1292 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1293 internal static extern int _GetUserKey(SafeProvHandle hProv, int keyNumber, ref SafeKeyHandle hKey);
1294 [System.Security.SecurityCritical] // auto-generated
1295 [ResourceExposure(ResourceScope.None)]
1296 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1297 internal static extern void _ImportBulkKey(SafeProvHandle hProv, int algid, bool useSalt, byte[] key, ref SafeKeyHandle hKey);
1298 [System.Security.SecurityCritical] // auto-generated
1299 [ResourceExposure(ResourceScope.None)]
1300 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1301 internal static extern int _ImportCspBlob(byte[] keyBlob, SafeProvHandle hProv, CspProviderFlags flags, ref SafeKeyHandle hKey);
1302 [System.Security.SecurityCritical] // auto-generated
1303 [ResourceExposure(ResourceScope.None)]
1304 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1305 internal static extern void _ImportKey(SafeProvHandle hCSP, int keyNumber, CspProviderFlags flags, object cspObject, ref SafeKeyHandle hKey);
1306 [System.Security.SecurityCritical] // auto-generated
1307 [ResourceExposure(ResourceScope.None)]
1308 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1309 internal static extern bool _ProduceLegacyHmacValues();
1310 #endif // FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO
1311 [System.Security.SecurityCritical] // auto-generated
1312 [ResourceExposure(ResourceScope.Machine)]
1313 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1314 internal static extern int _OpenCSP(CspParameters param, uint flags, ref SafeProvHandle hProv);
1315 [System.Security.SecurityCritical] // auto-generated
1316 [ResourceExposure(ResourceScope.Machine)]
1317 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1318 internal static extern void _AcquireCSP(CspParameters param, ref SafeProvHandle hProv);
1321 internal static bool _ProduceLegacyHmacValues()
1323 #if FULL_AOT_RUNTIME
1326 return Environment.GetEnvironmentVariable ("legacyHMACMode") == "1";