Imported Upstream version 4.8.0.309

Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-11-10 13:04:39 +00:00
parent ee1447783b
commit 94b2861243
4912 changed files with 390737 additions and 49310 deletions

View File

@@ -186,6 +186,8 @@ namespace Microsoft.Win32.SafeHandles {
#pragma warning restore 618
#endif
internal sealed class SafeCapiHashHandle : SafeCapiHandleBase {
private static volatile SafeCapiHashHandle s_invalidHandle;
#if FEATURE_CORESYSTEM
[System.Security.SecurityCritical]
#endif
@@ -197,9 +199,17 @@ namespace Microsoft.Win32.SafeHandles {
/// </summary>
public static SafeCapiHashHandle InvalidHandle {
get {
SafeCapiHashHandle handle = new SafeCapiHashHandle();
handle.SetHandle(IntPtr.Zero);
return handle;
if (s_invalidHandle == null) {
// More than one of these might get created in parallel, but that's okay.
// Saving one to the field saves on GC tracking, but by SuppressingFinalize on
// any instance returned there's already less finalization pressure.
SafeCapiHashHandle handle = new SafeCapiHashHandle();
handle.SetHandle(IntPtr.Zero);
GC.SuppressFinalize(handle);
s_invalidHandle = handle;
}
return s_invalidHandle;
}
}
@@ -233,6 +243,8 @@ namespace Microsoft.Win32.SafeHandles {
#pragma warning restore 618
#endif
internal sealed class SafeCapiKeyHandle : SafeCapiHandleBase {
private static volatile SafeCapiKeyHandle s_invalidHandle;
#if FEATURE_CORESYSTEM
[System.Security.SecurityCritical]
#endif
@@ -245,9 +257,17 @@ namespace Microsoft.Win32.SafeHandles {
internal static SafeCapiKeyHandle InvalidHandle {
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
get {
SafeCapiKeyHandle handle = new SafeCapiKeyHandle();
handle.SetHandle(IntPtr.Zero);
return handle;
if (s_invalidHandle == null) {
// More than one of these might get created in parallel, but that's okay.
// Saving one to the field saves on GC tracking, but by SuppressingFinalize on
// any instance returned there's already less finalization pressure.
SafeCapiKeyHandle handle = new SafeCapiKeyHandle();
handle.SetHandle(IntPtr.Zero);
GC.SuppressFinalize(handle);
s_invalidHandle = handle;
}
return s_invalidHandle;
}
}

View File

@@ -38,6 +38,35 @@ namespace System.Security.Cryptography {
/// </summary>
Pss = 8 // BCRYPT_PAD_PSS
}
#if !MONO
[StructLayout(LayoutKind.Sequential)]
internal struct BCRYPT_DSA_KEY_BLOB_V2
{
public BCryptNative.KeyBlobMagicNumber dwMagic; // BCRYPT_DSA_PUBLIC_MAGIC_V2 or BCRYPT_DSA_PRIVATE_MAGIC_V2
public int cbKey; // key lengths in BYTES (e.g. for a 3072-bit key, cbKey = 3072/8 = 384)
public HASHALGORITHM_ENUM hashAlgorithm;
public DSAFIPSVERSION_ENUM standardVersion;
public int cbSeedLength; // size (in bytes) of the seed value
public int cbGroupSize; // size (in bytes) of the Q value
public byte Count3; // # of iterations used to generate Q. In big-endian format.
public byte Count2;
public byte Count1;
public byte Count0;
}
#endif
internal enum HASHALGORITHM_ENUM : int
{
DSA_HASH_ALGORITHM_SHA1 = 0,
DSA_HASH_ALGORITHM_SHA256 = 1,
DSA_HASH_ALGORITHM_SHA512 = 2,
}
internal enum DSAFIPSVERSION_ENUM : int
{
DSA_FIPS186_2 = 0,
DSA_FIPS186_3 = 1,
}
/// <summary>
/// Native interop with CNG's BCrypt layer. Native definitions can be found in bcrypt.h
/// </summary>
@@ -102,6 +131,10 @@ namespace System.Security.Cryptography {
/// Magic numbers identifying blob types
/// </summary>
internal enum KeyBlobMagicNumber {
DsaPublic = 0x42505344, // BCRYPT_DSA_PUBLIC_MAGIC for key lengths <= 1024 bits
DsaPublicV2 = 0x32425044, // BCRYPT_DSA_PUBLIC_MAGIC_V2 for key lengths > 1024 bits
DsaPrivate = 0x56505344, // BCRYPT_DSA_PRIVATE_MAGIC for key lengths <= 1024 bits
DsaPrivateV2 = 0x32565044, // BCRYPT_DSA_PRIVATE_MAGIC_V2 for key lengths > 1024 bits
ECDHPublicP256 = 0x314B4345, // BCRYPT_ECDH_PUBLIC_P256_MAGIC
ECDHPublicP384 = 0x334B4345, // BCRYPT_ECDH_PUBLIC_P384_MAGIC
ECDHPublicP521 = 0x354B4345, // BCRYPT_ECDH_PUBLIC_P521_MAGIC

View File

@@ -168,6 +168,14 @@ namespace System.Security.Cryptography {
public IntPtr pbData;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_DSS_PARAMETERS
{
public CRYPTOAPI_BLOB p;
public CRYPTOAPI_BLOB q;
public CRYPTOAPI_BLOB g;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct PROV_ENUMALGS {
public AlgorithmId aiAlgId;
@@ -187,6 +195,8 @@ namespace System.Security.Cryptography {
internal const uint CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY);
internal const uint CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY);
internal const uint CNG_RSA_PUBLIC_KEY_BLOB = 72;
internal const uint X509_DSS_PUBLICKEY = 38;
internal const uint X509_DSS_PARAMETERS = 39;
internal const uint X509_ASN_ENCODING = 0x00000001;
internal const uint PKCS_7_ASN_ENCODING = 0x00010000;

View File

@@ -447,6 +447,9 @@ namespace System.Security.Cryptography {
buffer.Length);
}
else {
if (!LocalAppContextSwitches.AesCryptoServiceProviderDontCorrectlyResetDecryptor) {
resetSize = buffer.Length;
}
CapiNative.UnsafeNativeMethods.CryptDecrypt(m_key,
SafeCapiHashHandle.InvalidHandle,
true,

View File

@@ -46,6 +46,101 @@ namespace System.Security.Cryptography {
//
public abstract ECDiffieHellmanPublicKey PublicKey { get; }
public abstract byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey);
// This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
public virtual byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
{
throw DerivedClassMustOverride();
}
/// <summary>
/// Derive key material using the formula HASH(x) where x is the computed result of the EC Diffie-Hellman algorithm.
/// </summary>
/// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
/// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
/// <returns>A hashed output suitable for key material</returns>
/// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
public byte[] DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm)
{
return DeriveKeyFromHash(otherPartyPublicKey, hashAlgorithm, null, null);
}
/// <summary>
/// Derive key material using the formula HASH(secretPrepend || x || secretAppend) where x is the computed
/// result of the EC Diffie-Hellman algorithm.
/// </summary>
/// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
/// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
/// <param name="secretPrepend">A value to prepend to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
/// <param name="secretAppend">A value to append to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
/// <returns>A hashed output suitable for key material</returns>
/// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
public virtual byte[] DeriveKeyFromHash(
ECDiffieHellmanPublicKey otherPartyPublicKey,
HashAlgorithmName hashAlgorithm,
byte[] secretPrepend,
byte[] secretAppend)
{
throw DerivedClassMustOverride();
}
/// <summary>
/// Derive key material using the formula HMAC(hmacKey, x) where x is the computed
/// result of the EC Diffie-Hellman algorithm.
/// </summary>
/// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
/// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
/// <param name="hmacKey">The key to use in the HMAC. A <c>null</c> value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key.</param>
/// <returns>A hashed output suitable for key material</returns>
/// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
public byte[] DeriveKeyFromHmac(
ECDiffieHellmanPublicKey otherPartyPublicKey,
HashAlgorithmName hashAlgorithm,
byte[] hmacKey)
{
return DeriveKeyFromHmac(otherPartyPublicKey, hashAlgorithm, hmacKey, null, null);
}
/// <summary>
/// Derive key material using the formula HMAC(hmacKey, secretPrepend || x || secretAppend) where x is the computed
/// result of the EC Diffie-Hellman algorithm.
/// </summary>
/// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
/// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
/// <param name="hmacKey">The key to use in the HMAC. A <c>null</c> value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key.</param>
/// <param name="secretPrepend">A value to prepend to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
/// <param name="secretAppend">A value to append to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
/// <returns>A hashed output suitable for key material</returns>
/// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
public virtual byte[] DeriveKeyFromHmac(
ECDiffieHellmanPublicKey otherPartyPublicKey,
HashAlgorithmName hashAlgorithm,
byte[] hmacKey,
byte[] secretPrepend,
byte[] secretAppend)
{
throw DerivedClassMustOverride();
}
/// <summary>
/// Derive key material using the TLS pseudo-random function (PRF) derivation algorithm.
/// </summary>
/// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
/// <param name="prfLabel">The ASCII encoded PRF label.</param>
/// <param name="prfSeed">The 64-byte PRF seed.</param>
/// <returns>A 48-byte output of the TLS pseudo-random function.</returns>
/// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
/// <exception cref="ArgumentNullException"><paramref name="prfLabel"/> is null</exception>
/// <exception cref="ArgumentNullException"><paramref name="prfSeed"/> is null</exception>
/// <exception cref="CryptographicException"><paramref name="prfSeed"/> is not exactly 64 bytes in length</exception>
public virtual byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
{
throw DerivedClassMustOverride();
}
private static Exception DerivedClassMustOverride()
{
return new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride));
}
}
}

View File

@@ -93,7 +93,21 @@ namespace System.Security.Cryptography {
}
CodeAccessPermission.RevertAssert();
KeySize = m_key.KeySize;
// Our LegalKeySizes value stores the values that we encoded as being the correct
// legal key size limitations for this algorithm, as documented on MSDN.
//
// But on a new OS version we might not question if our limit is accurate, or MSDN
// could have been innacurate to start with.
//
// Since the key is already loaded, we know that Windows thought it to be valid;
// therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
// check.
//
// For RSA there are known cases where this change matters. RSACryptoServiceProvider can
// create a 384-bit RSA key, which we consider too small to be legal. It can also create
// a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
// alignment requirement. (In both cases Windows loads it just fine)
KeySizeValue = m_key.KeySize;
}
/// <summary>
@@ -247,7 +261,22 @@ namespace System.Security.Cryptography {
//
m_key = value;
KeySize = m_key.KeySize;
// Our LegalKeySizes value stores the values that we encoded as being the correct
// legal key size limitations for this algorithm, as documented on MSDN.
//
// But on a new OS version we might not question if our limit is accurate, or MSDN
// could have been innacurate to start with.
//
// Since the key is already loaded, we know that Windows thought it to be valid;
// therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
// check.
//
// For RSA there are known cases where this change matters. RSACryptoServiceProvider can
// create a 384-bit RSA key, which we consider too small to be legal. It can also create
// a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
// alignment requirement. (In both cases Windows loads it just fine)
KeySizeValue = m_key.KeySize;
}
}
@@ -369,6 +398,84 @@ namespace System.Security.Cryptography {
}
}
[SecuritySafeCritical]
public override byte[] DeriveKeyFromHash(
ECDiffieHellmanPublicKey otherPartyPublicKey,
HashAlgorithmName hashAlgorithm,
byte[] secretPrepend,
byte[] secretAppend)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
if (otherPartyPublicKey == null)
throw new ArgumentNullException("otherPartyPublicKey");
if (string.IsNullOrEmpty(hashAlgorithm.Name))
throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");
using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
{
return NCryptNative.DeriveKeyMaterialHash(
secretAgreement,
hashAlgorithm.Name,
secretPrepend,
secretAppend,
NCryptNative.SecretAgreementFlags.None);
}
}
[SecuritySafeCritical]
public override byte[] DeriveKeyFromHmac(
ECDiffieHellmanPublicKey otherPartyPublicKey,
HashAlgorithmName hashAlgorithm,
byte[] hmacKey,
byte[] secretPrepend,
byte[] secretAppend)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
if (otherPartyPublicKey == null)
throw new ArgumentNullException("otherPartyPublicKey");
if (string.IsNullOrEmpty(hashAlgorithm.Name))
throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");
using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
{
NCryptNative.SecretAgreementFlags flags = hmacKey == null ?
NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey :
NCryptNative.SecretAgreementFlags.None;
return NCryptNative.DeriveKeyMaterialHmac(
secretAgreement,
hashAlgorithm.Name,
hmacKey,
secretPrepend,
secretAppend,
flags);
}
}
[SecuritySafeCritical]
public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
if (otherPartyPublicKey == null)
throw new ArgumentNullException("otherPartyPublicKey");
if (prfLabel == null)
throw new ArgumentNullException("prfLabel");
if (prfSeed == null)
throw new ArgumentNullException("prfSeed");
using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
{
return NCryptNative.DeriveKeyMaterialTls(
secretAgreement,
prfLabel,
prfSeed,
NCryptNative.SecretAgreementFlags.None);
}
}
/// <summary>
/// Get a handle to the secret agreement generated between two parties
/// </summary>

View File

@@ -40,6 +40,10 @@ namespace System.Security.Cryptography {
return m_keyBlob.Clone() as byte[];
}
public abstract string ToXmlString();
// This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
public virtual string ToXmlString()
{
throw new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride));
}
}
}

View File

@@ -82,12 +82,12 @@ namespace System.Security.Cryptography {
[SecuritySafeCritical]
public ECDsaCng(CngKey key) {
Contract.Ensures(LegalKeySizesValue != null);
Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
if (key == null) {
throw new ArgumentNullException("key");
}
if (key.AlgorithmGroup != CngAlgorithmGroup.ECDsa) {
if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) {
throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey), "key");
}
@@ -111,7 +111,21 @@ namespace System.Security.Cryptography {
}
CodeAccessPermission.RevertAssert();
KeySize = m_key.KeySize;
// Our LegalKeySizes value stores the values that we encoded as being the correct
// legal key size limitations for this algorithm, as documented on MSDN.
//
// But on a new OS version we might not question if our limit is accurate, or MSDN
// could have been innacurate to start with.
//
// Since the key is already loaded, we know that Windows thought it to be valid;
// therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
// check.
//
// For RSA there are known cases where this change matters. RSACryptoServiceProvider can
// create a 384-bit RSA key, which we consider too small to be legal. It can also create
// a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
// alignment requirement. (In both cases Windows loads it just fine)
KeySizeValue = m_key.KeySize;
}
/// <summary>
@@ -140,8 +154,8 @@ namespace System.Security.Cryptography {
public CngKey Key {
get {
Contract.Ensures(Contract.Result<CngKey>() != null);
Contract.Ensures(Contract.Result<CngKey>().AlgorithmGroup == CngAlgorithmGroup.ECDsa);
Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
Contract.Ensures(IsEccAlgorithmGroup(Contract.Result<CngKey>().AlgorithmGroup));
Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
// If the size of the key no longer matches our stored value, then we need to replace it with
// a new key of the correct size.
@@ -179,9 +193,9 @@ namespace System.Security.Cryptography {
private set {
Contract.Requires(value != null);
Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa);
Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup));
if (value.AlgorithmGroup != CngAlgorithmGroup.ECDsa) {
if (!IsEccAlgorithmGroup(value.AlgorithmGroup)) {
throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey));
}
@@ -196,7 +210,22 @@ namespace System.Security.Cryptography {
//
m_key = value;
KeySize = m_key.KeySize;
// Our LegalKeySizes value stores the values that we encoded as being the correct
// legal key size limitations for this algorithm, as documented on MSDN.
//
// But on a new OS version we might not question if our limit is accurate, or MSDN
// could have been innacurate to start with.
//
// Since the key is already loaded, we know that Windows thought it to be valid;
// therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
// check.
//
// For RSA there are known cases where this change matters. RSACryptoServiceProvider can
// create a 384-bit RSA key, which we consider too small to be legal. It can also create
// a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
// alignment requirement. (In both cases Windows loads it just fine)
KeySizeValue = m_key.KeySize;
}
}
@@ -444,6 +473,16 @@ namespace System.Security.Cryptography {
return hasher.HashFinal();
}
}
#endif
private static bool IsEccAlgorithmGroup(CngAlgorithmGroup algorithmGroup)
{
// Sometimes, when reading from certificates, ECDSA keys get identified as ECDH.
// Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA),
// so either value is acceptable for the ECDSA wrapper object.
//
// It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG.
return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman;
}
#endif
}
}

View File

@@ -796,10 +796,6 @@ namespace System.Security.Cryptography {
signature,
signature.Length,
paddingMode);
if (error != ErrorCode.Success && error != ErrorCode.BadSignature) {
throw new CryptographicException((int)error);
}
return error == ErrorCode.Success;
}
@@ -1694,6 +1690,55 @@ namespace System.Security.Cryptography {
return signature;
}
/// <summary>
/// Sign a hash using no padding
/// </summary>
[System.Security.SecurityCritical]
internal static byte[] SignHash(SafeNCryptKeyHandle key, byte[] hash, int expectedSize)
{
Contract.Requires(key != null);
Contract.Requires(hash != null);
Contract.Ensures(Contract.Result<byte[]>() != null);
#if DEBUG
expectedSize = 1;
#endif
// Figure out how big the signature is
byte[] signature = new byte[expectedSize];
int signatureSize = 0;
ErrorCode error = UnsafeNativeMethods.NCryptSignHash(key,
IntPtr.Zero,
hash,
hash.Length,
signature,
signature.Length,
out signatureSize,
0);
if (error == ErrorCode.BufferTooSmall)
{
signature = new byte[signatureSize];
error = UnsafeNativeMethods.NCryptSignHash(key,
IntPtr.Zero,
hash,
hash.Length,
signature,
signature.Length,
out signatureSize,
0);
}
if (error != ErrorCode.Success)
{
throw new CryptographicException((int)error);
}
Array.Resize(ref signature, signatureSize);
return signature;
}
/// <summary>
/// Unpack a key blob in ECC public blob format into its X and Y parameters
///
@@ -1736,10 +1781,6 @@ namespace System.Security.Cryptography {
signature.Length,
0);
if (error != ErrorCode.Success && error != ErrorCode.BadSignature) {
throw new CryptographicException((int)error);
}
return error == ErrorCode.Success;
}
}

View File

@@ -129,7 +129,11 @@ namespace System.Security.Cryptography
// If we don't have a key yet, we need to generate a random one now
if (_key == null)
{
CngKeyCreationParameters creationParameters = new CngKeyCreationParameters();
CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport,
};
CngProperty keySizeProperty = new CngProperty(NCryptNative.KeyPropertyName.Length,
BitConverter.GetBytes(KeySize),
CngPropertyOptions.None);
@@ -154,7 +158,22 @@ namespace System.Security.Cryptography
}
_key = value;
KeySize = _key.KeySize;
// Our LegalKeySizes value stores the values that we encoded as being the correct
// legal key size limitations for this algorithm, as documented on MSDN.
//
// But on a new OS version we might not question if our limit is accurate, or MSDN
// could have been innacurate to start with.
//
// Since the key is already loaded, we know that Windows thought it to be valid;
// therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
// check.
//
// For RSA there are known cases where this change matters. RSACryptoServiceProvider can
// create a 384-bit RSA key, which we consider too small to be legal. It can also create
// a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
// alignment requirement. (In both cases Windows loads it just fine)
KeySizeValue = _key.KeySize;
}
}
@@ -544,6 +563,25 @@ namespace System.Security.Cryptography
throw new CryptographicException(SR.GetString(SR.Cryptography_UnsupportedPaddingMode));
}
}
/*
* The members
* DecryptValue
* EncryptValue
* get_KeyExchangeAlgorithm
* get_SignatureAlgorithm
* are all implemented on RSA as of net46.
*
* But in servicing situations, System.Core.dll can get patched onto a machine which has mscorlib < net46, meaning
* these abstract members have no implementation.
*
* To keep servicing simple, we'll redefine the overrides here. Since this type is sealed it only affects reflection,
* as there are no derived types to mis-target base.-invocations.
*/
public override byte[] DecryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); }
public override byte[] EncryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); }
public override string KeyExchangeAlgorithm { get { return "RSA"; } }
public override string SignatureAlgorithm { get { return "RSA"; } }
#endif
}
}

View File

@@ -71,8 +71,14 @@ namespace System.Security.Cryptography.X509Certificates
{
if (privateKeyHandle == null)
{
if (LocalAppContextSwitches.DontReliablyClonePrivateKey)
return (RSA)certificate.PrivateKey;
// fall back to CAPI if we cannot acquire the key using CNG.
return (RSA)certificate.PrivateKey;
RSACryptoServiceProvider rsaCsp = (RSACryptoServiceProvider)certificate.PrivateKey;
CspParameters cspParameters = DSACertificateExtensions.CopyCspParameters(rsaCsp);
RSACryptoServiceProvider clone = new RSACryptoServiceProvider(cspParameters);
return clone;
}
CngKey key = CngKey.Open(privateKeyHandle, CngKeyHandleOpenOptions.None);

View File

@@ -155,9 +155,7 @@ namespace System.Threading
lockID = Interlocked.Increment(ref s_nextLockID);
}
#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static bool IsRWEntryEmpty(ReaderWriterCount rwc)
{
if (rwc.lockID == 0)
@@ -181,9 +179,7 @@ namespace System.Threading
/// entry for this thread, but doesn't want to add one if an existing one
/// could not be found.
/// </summary>
#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private ReaderWriterCount GetThreadRWCount(bool dontAllocate)
{
ReaderWriterCount rwc = t_rwc;
@@ -1117,9 +1113,7 @@ namespace System.Threading
return owners & READER_MASK;
}
#if NET_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private void EnterMyLock()
{
if (Interlocked.CompareExchange(ref myLock, 1, 0) != 0)