You've already forked linux-packaging-mono
Imported Upstream version 4.8.0.309
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
parent
ee1447783b
commit
94b2861243
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user