diff --git a/crypto/src/crypto/tls/AbstractTlsAgreementCredentials.cs b/crypto/src/crypto/tls/AbstractTlsAgreementCredentials.cs
new file mode 100644
index 000000000..2d7af80e8
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsAgreementCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public abstract class AbstractTlsAgreementCredentials
+ : AbstractTlsCredentials, TlsAgreementCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ public abstract byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
+ }
+}
diff --git a/crypto/src/crypto/tls/AbstractTlsContext.cs b/crypto/src/crypto/tls/AbstractTlsContext.cs
new file mode 100644
index 000000000..7a7e636d2
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsContext.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Threading;
+
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ internal abstract class AbstractTlsContext
+ : TlsContext
+ {
+ private static long counter = Times.NanoTime();
+
+ private static long NextCounterValue()
+ {
+ return Interlocked.Increment(ref counter);
+ }
+
+ private readonly IRandomGenerator mNonceRandom;
+ private readonly SecureRandom mSecureRandom;
+ private readonly SecurityParameters mSecurityParameters;
+
+ private ProtocolVersion mClientVersion = null;
+ private ProtocolVersion mServerVersion = null;
+ private TlsSession mSession = null;
+ private object mUserObject = null;
+
+ internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
+ {
+ secureRandom.SetSeed(NextCounterValue());
+ secureRandom.SetSeed(Times.NanoTime());
+
+ this.mNonceRandom = new DigestRandomGenerator(TlsUtilities.CreateHash(HashAlgorithm.sha256));
+ this.mNonceRandom.AddSeedMaterial(secureRandom.GenerateSeed(32));
+
+ this.mSecureRandom = secureRandom;
+ this.mSecurityParameters = securityParameters;
+ }
+
+ public virtual IRandomGenerator NonceRandomGenerator
+ {
+ get { return mNonceRandom; }
+ }
+
+ public virtual SecureRandom SecureRandom
+ {
+ get { return mSecureRandom; }
+ }
+
+ public virtual SecurityParameters SecurityParameters
+ {
+ get { return mSecurityParameters; }
+ }
+
+ public abstract bool IsServer { get; }
+
+ public virtual ProtocolVersion ClientVersion
+ {
+ get { return mClientVersion; }
+ set { this.mClientVersion = value; }
+ }
+
+ public virtual ProtocolVersion ServerVersion
+ {
+ get { return mServerVersion; }
+ set { this.mServerVersion = value; }
+ }
+
+ public virtual TlsSession ResumableSession
+ {
+ get { return mSession; }
+ set { this.mSession = value; }
+ }
+
+ public virtual object UserObject
+ {
+ get { return mUserObject; }
+ set { this.mUserObject = value; }
+ }
+
+ public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length)
+ {
+ if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length))
+ throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value");
+
+ SecurityParameters sp = SecurityParameters;
+ byte[] cr = sp.ClientRandom, sr = sp.ServerRandom;
+
+ int seedLength = cr.Length + sr.Length;
+ if (context_value != null)
+ {
+ seedLength += (2 + context_value.Length);
+ }
+
+ byte[] seed = new byte[seedLength];
+ int seedPos = 0;
+
+ Array.Copy(cr, 0, seed, seedPos, cr.Length);
+ seedPos += cr.Length;
+ Array.Copy(sr, 0, seed, seedPos, sr.Length);
+ seedPos += sr.Length;
+ if (context_value != null)
+ {
+ TlsUtilities.WriteUint16(context_value.Length, seed, seedPos);
+ seedPos += 2;
+ Array.Copy(context_value, 0, seed, seedPos, context_value.Length);
+ seedPos += context_value.Length;
+ }
+
+ if (seedPos != seedLength)
+ throw new InvalidOperationException("error in calculation of seed for export");
+
+ return TlsUtilities.PRF(this, sp.MasterSecret, asciiLabel, seed, length);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/AbstractTlsCredentials.cs b/crypto/src/crypto/tls/AbstractTlsCredentials.cs
new file mode 100644
index 000000000..6411b811c
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsCredentials.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public abstract class AbstractTlsCredentials
+ : TlsCredentials
+ {
+ public abstract Certificate Certificate { get; }
+ }
+}
diff --git a/crypto/src/crypto/tls/AbstractTlsEncryptionCredentials.cs b/crypto/src/crypto/tls/AbstractTlsEncryptionCredentials.cs
new file mode 100644
index 000000000..05b129c60
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsEncryptionCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public abstract class AbstractTlsEncryptionCredentials
+ : AbstractTlsCredentials, TlsEncryptionCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ public abstract byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
+ }
+}
diff --git a/crypto/src/crypto/tls/AbstractTlsSigner.cs b/crypto/src/crypto/tls/AbstractTlsSigner.cs
new file mode 100644
index 000000000..1f4aabf74
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsSigner.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public abstract class AbstractTlsSigner
+ : TlsSigner
+ {
+ protected TlsContext mContext;
+
+ public virtual void Init(TlsContext context)
+ {
+ this.mContext = context;
+ }
+
+ public virtual byte[] GenerateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+ {
+ return GenerateRawSignature(null, privateKey, md5AndSha1);
+ }
+
+ public abstract byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash);
+
+ public virtual bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
+ {
+ return VerifyRawSignature(null, sigBytes, publicKey, md5AndSha1);
+ }
+
+ public abstract bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash);
+
+ public virtual ISigner CreateSigner(AsymmetricKeyParameter privateKey)
+ {
+ return CreateSigner(null, privateKey);
+ }
+
+ public abstract ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
+
+ public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey)
+ {
+ return CreateVerifyer(null, publicKey);
+ }
+
+ public abstract ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
+
+ public abstract bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
+ }
+}
diff --git a/crypto/src/crypto/tls/AbstractTlsSignerCredentials.cs b/crypto/src/crypto/tls/AbstractTlsSignerCredentials.cs
new file mode 100644
index 000000000..886c46c6e
--- /dev/null
+++ b/crypto/src/crypto/tls/AbstractTlsSignerCredentials.cs
@@ -0,0 +1,20 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public abstract class AbstractTlsSignerCredentials
+ : AbstractTlsCredentials, TlsSignerCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ public abstract byte[] GenerateCertificateSignature(byte[] hash);
+
+ public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm
+ {
+ get
+ {
+ throw new InvalidOperationException("TlsSignerCredentials implementation does not support (D)TLS 1.2+");
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
index 2bd2f40bf..5147a1990 100644
--- a/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
+++ b/crypto/src/crypto/tls/DefaultTlsAgreementCredentials.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Parameters;
@@ -8,69 +9,61 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
public class DefaultTlsAgreementCredentials
- : TlsAgreementCredentials
+ : AbstractTlsAgreementCredentials
{
- protected Certificate clientCert;
- protected AsymmetricKeyParameter clientPrivateKey;
+ protected readonly Certificate mCertificate;
+ protected readonly AsymmetricKeyParameter mPrivateKey;
- protected IBasicAgreement basicAgreement;
- protected bool truncateAgreement;
+ protected readonly IBasicAgreement mBasicAgreement;
+ protected readonly bool mTruncateAgreement;
- public DefaultTlsAgreementCredentials(Certificate clientCertificate, AsymmetricKeyParameter clientPrivateKey)
+ public DefaultTlsAgreementCredentials(Certificate certificate, AsymmetricKeyParameter privateKey)
{
- if (clientCertificate == null)
- {
- throw new ArgumentNullException("clientCertificate");
- }
- if (clientCertificate.Length == 0)
- {
- throw new ArgumentException("cannot be empty", "clientCertificate");
- }
- if (clientPrivateKey == null)
- {
- throw new ArgumentNullException("clientPrivateKey");
- }
- if (!clientPrivateKey.IsPrivate)
- {
- throw new ArgumentException("must be private", "clientPrivateKey");
- }
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+ if (certificate.IsEmpty)
+ throw new ArgumentException("cannot be empty", "certificate");
+ if (privateKey == null)
+ throw new ArgumentNullException("privateKey");
+ if (!privateKey.IsPrivate)
+ throw new ArgumentException("must be private", "privateKey");
- if (clientPrivateKey is DHPrivateKeyParameters)
+ if (privateKey is DHPrivateKeyParameters)
{
- basicAgreement = new DHBasicAgreement();
- truncateAgreement = true;
+ mBasicAgreement = new DHBasicAgreement();
+ mTruncateAgreement = true;
}
- else if (clientPrivateKey is ECPrivateKeyParameters)
+ else if (privateKey is ECPrivateKeyParameters)
{
- basicAgreement = new ECDHBasicAgreement();
- truncateAgreement = false;
+ mBasicAgreement = new ECDHBasicAgreement();
+ mTruncateAgreement = false;
}
else
{
- throw new ArgumentException("type not supported: "
- + clientPrivateKey.GetType().FullName, "clientPrivateKey");
+ throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
}
- this.clientCert = clientCertificate;
- this.clientPrivateKey = clientPrivateKey;
+ this.mCertificate = certificate;
+ this.mPrivateKey = privateKey;
}
- public virtual Certificate Certificate
+ public override Certificate Certificate
{
- get { return clientCert; }
+ get { return mCertificate; }
}
- public virtual byte[] GenerateAgreement(AsymmetricKeyParameter serverPublicKey)
+ /// <exception cref="IOException"></exception>
+ public override byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey)
{
- basicAgreement.Init(clientPrivateKey);
- BigInteger agreementValue = basicAgreement.CalculateAgreement(serverPublicKey);
+ mBasicAgreement.Init(mPrivateKey);
+ BigInteger agreementValue = mBasicAgreement.CalculateAgreement(peerPublicKey);
- if (truncateAgreement)
+ if (mTruncateAgreement)
{
return BigIntegers.AsUnsignedByteArray(agreementValue);
}
- return BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue);
+ return BigIntegers.AsUnsignedByteArray(mBasicAgreement.GetFieldSize(), agreementValue);
}
}
}
diff --git a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
index 18b23a67b..cc34b3028 100644
--- a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
@@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public class DefaultTlsCipherFactory
: TlsCipherFactory
{
- public virtual TlsCipher CreateCipher(TlsClientContext context,
+ public virtual TlsCipher CreateCipher(TlsContext context,
int encryptionAlgorithm, DigestAlgorithm digestAlgorithm)
{
switch (encryptionAlgorithm)
@@ -29,13 +29,13 @@ namespace Org.BouncyCastle.Crypto.Tls
}
/// <exception cref="IOException"></exception>
- protected virtual TlsCipher CreateRC4Cipher(TlsClientContext context, int cipherKeySize, DigestAlgorithm digestAlgorithm)
+ protected virtual TlsCipher CreateRC4Cipher(TlsContext context, int cipherKeySize, DigestAlgorithm digestAlgorithm)
{
return new TlsStreamCipher(context, CreateRC4StreamCipher(), CreateRC4StreamCipher(), CreateDigest(digestAlgorithm), CreateDigest(digestAlgorithm), cipherKeySize);
}
/// <exception cref="IOException"></exception>
- protected virtual TlsCipher CreateAesCipher(TlsClientContext context, int cipherKeySize,
+ protected virtual TlsCipher CreateAesCipher(TlsContext context, int cipherKeySize,
DigestAlgorithm digestAlgorithm)
{
return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(),
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Crypto.Tls
}
/// <exception cref="IOException"></exception>
- protected virtual TlsCipher CreateDesEdeCipher(TlsClientContext context, int cipherKeySize,
+ protected virtual TlsCipher CreateDesEdeCipher(TlsContext context, int cipherKeySize,
DigestAlgorithm digestAlgorithm)
{
return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(),
diff --git a/crypto/src/crypto/tls/DefaultTlsEncryptionCredentials.cs b/crypto/src/crypto/tls/DefaultTlsEncryptionCredentials.cs
new file mode 100644
index 000000000..34d15d146
--- /dev/null
+++ b/crypto/src/crypto/tls/DefaultTlsEncryptionCredentials.cs
@@ -0,0 +1,51 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class DefaultTlsEncryptionCredentials
+ : AbstractTlsEncryptionCredentials
+ {
+ protected readonly TlsContext mContext;
+ protected readonly Certificate mCertificate;
+ protected readonly AsymmetricKeyParameter mPrivateKey;
+
+ public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate,
+ AsymmetricKeyParameter privateKey)
+ {
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+ if (certificate.IsEmpty)
+ throw new ArgumentException("cannot be empty", "certificate");
+ if (privateKey == null)
+ throw new ArgumentNullException("'privateKey' cannot be null");
+ if (!privateKey.IsPrivate)
+ throw new ArgumentException("must be private", "privateKey");
+
+ if (privateKey is RsaKeyParameters)
+ {
+ }
+ else
+ {
+ throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
+ }
+
+ this.mContext = context;
+ this.mCertificate = certificate;
+ this.mPrivateKey = privateKey;
+ }
+
+ public override Certificate Certificate
+ {
+ get { return mCertificate; }
+ }
+
+ /// <exception cref="IOException"></exception>
+ public override byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret)
+ {
+ return TlsRsaUtilities.SafeDecryptPreMasterSecret(mContext, (RsaKeyParameters)mPrivateKey, encryptedPreMasterSecret);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
index 2c5aa3524..8e609938f 100644
--- a/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
+++ b/crypto/src/crypto/tls/DefaultTlsSignerCredentials.cs
@@ -1,76 +1,90 @@
using System;
+using System.IO;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Tls
{
public class DefaultTlsSignerCredentials
- : TlsSignerCredentials
+ : AbstractTlsSignerCredentials
{
- protected TlsClientContext context;
- protected Certificate clientCert;
- protected AsymmetricKeyParameter clientPrivateKey;
+ protected readonly TlsContext mContext;
+ protected readonly Certificate mCertificate;
+ protected readonly AsymmetricKeyParameter mPrivateKey;
+ protected readonly SignatureAndHashAlgorithm mSignatureAndHashAlgorithm;
- protected TlsSigner clientSigner;
+ protected readonly TlsSigner mSigner;
- public DefaultTlsSignerCredentials(TlsClientContext context,
- Certificate clientCertificate, AsymmetricKeyParameter clientPrivateKey)
+ public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey)
+ : this(context, certificate, privateKey, null)
{
- if (clientCertificate == null)
- {
- throw new ArgumentNullException("clientCertificate");
- }
- if (clientCertificate.Length == 0)
- {
+ }
+
+ public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey,
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm)
+ {
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+ if (certificate.IsEmpty)
throw new ArgumentException("cannot be empty", "clientCertificate");
- }
- if (clientPrivateKey == null)
- {
- throw new ArgumentNullException("clientPrivateKey");
- }
- if (!clientPrivateKey.IsPrivate)
- {
- throw new ArgumentException("must be private", "clientPrivateKey");
- }
+ if (privateKey == null)
+ throw new ArgumentNullException("privateKey");
+ if (!privateKey.IsPrivate)
+ throw new ArgumentException("must be private", "privateKey");
+ if (TlsUtilities.IsTlsV12(context) && signatureAndHashAlgorithm == null)
+ throw new ArgumentException("cannot be null for (D)TLS 1.2+", "signatureAndHashAlgorithm");
- if (clientPrivateKey is RsaKeyParameters)
+ if (privateKey is RsaKeyParameters)
{
- clientSigner = new TlsRsaSigner();
+ mSigner = new TlsRsaSigner();
}
- else if (clientPrivateKey is DsaPrivateKeyParameters)
+ else if (privateKey is DsaPrivateKeyParameters)
{
- clientSigner = new TlsDssSigner();
+ mSigner = new TlsDssSigner();
}
- else if (clientPrivateKey is ECPrivateKeyParameters)
+ else if (privateKey is ECPrivateKeyParameters)
{
- clientSigner = new TlsECDsaSigner();
+ mSigner = new TlsECDsaSigner();
}
else
{
- throw new ArgumentException("type not supported: "
- + clientPrivateKey.GetType().FullName, "clientPrivateKey");
+ throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
}
- this.context = context;
- this.clientCert = clientCertificate;
- this.clientPrivateKey = clientPrivateKey;
+ this.mContext = context;
+ this.mCertificate = certificate;
+ this.mPrivateKey = privateKey;
+ this.mSignatureAndHashAlgorithm = signatureAndHashAlgorithm;
}
- public virtual Certificate Certificate
+ public override Certificate Certificate
{
- get { return clientCert; }
+ get { return mCertificate; }
}
- public virtual byte[] GenerateCertificateSignature(byte[] md5andsha1)
+ /// <exception cref="IOException"></exception>
+ public override byte[] GenerateCertificateSignature(byte[] hash)
{
try
{
- return clientSigner.GenerateRawSignature(context.SecureRandom, clientPrivateKey, md5andsha1);
+ if (TlsUtilities.IsTlsV12(mContext))
+ {
+ return mSigner.GenerateRawSignature(mSignatureAndHashAlgorithm, mPrivateKey, hash);
+ }
+ else
+ {
+ return mSigner.GenerateRawSignature(mPrivateKey, hash);
+ }
}
catch (CryptoException)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
+
+ public override SignatureAndHashAlgorithm SignatureAndHashAlgorithm
+ {
+ get { return mSignatureAndHashAlgorithm; }
+ }
}
}
diff --git a/crypto/src/crypto/tls/SecurityParameters.cs b/crypto/src/crypto/tls/SecurityParameters.cs
index 9ed3969eb..3aa318da2 100644
--- a/crypto/src/crypto/tls/SecurityParameters.cs
+++ b/crypto/src/crypto/tls/SecurityParameters.cs
@@ -1,26 +1,46 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Tls
{
- public class SecurityParameters
- {
- internal byte[] clientRandom = null;
- internal byte[] serverRandom = null;
- internal byte[] masterSecret = null;
+ public class SecurityParameters
+ {
+ internal int prfAlgorithm = -1;
+ internal byte[] masterSecret = null;
+ internal byte[] clientRandom = null;
+ internal byte[] serverRandom = null;
+
+ internal virtual void Clear()
+ {
+ if (this.masterSecret != null)
+ {
+ Arrays.Fill(this.masterSecret, (byte)0);
+ this.masterSecret = null;
+ }
+ }
+
+ /**
+ * @return {@link PRFAlgorithm}
+ */
+ public virtual int PrfAlgorithm
+ {
+ get { return prfAlgorithm; }
+ }
- public byte[] ClientRandom
- {
- get { return clientRandom; }
- }
+ public virtual byte[] MasterSecret
+ {
+ get { return masterSecret; }
+ }
- public byte[] ServerRandom
- {
- get { return serverRandom; }
- }
+ public virtual byte[] ClientRandom
+ {
+ get { return clientRandom; }
+ }
- public byte[] MasterSecret
- {
- get { return masterSecret; }
- }
- }
+ public virtual byte[] ServerRandom
+ {
+ get { return serverRandom; }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsAgreementCredentials.cs b/crypto/src/crypto/tls/TlsAgreementCredentials.cs
index 46ee4f90e..7c64072e8 100644
--- a/crypto/src/crypto/tls/TlsAgreementCredentials.cs
+++ b/crypto/src/crypto/tls/TlsAgreementCredentials.cs
@@ -3,9 +3,10 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsAgreementCredentials : TlsCredentials
- {
- /// <exception cref="IOException"></exception>
- byte[] GenerateAgreement(AsymmetricKeyParameter serverPublicKey);
- }
+ public interface TlsAgreementCredentials
+ : TlsCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
+ }
}
diff --git a/crypto/src/crypto/tls/TlsBlockCipher.cs b/crypto/src/crypto/tls/TlsBlockCipher.cs
index cfbceb25e..7adab1985 100644
--- a/crypto/src/crypto/tls/TlsBlockCipher.cs
+++ b/crypto/src/crypto/tls/TlsBlockCipher.cs
@@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public class TlsBlockCipher
: TlsCipher
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected byte[] randomData;
protected IBlockCipher encryptCipher;
@@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Crypto.Tls
get { return rMac; }
}
- public TlsBlockCipher(TlsClientContext context, IBlockCipher encryptCipher,
+ public TlsBlockCipher(TlsContext context, IBlockCipher encryptCipher,
IBlockCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
{
this.context = context;
@@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Crypto.Tls
SecurityParameters securityParameters = context.SecurityParameters;
- byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
+ byte[] keyBlock = TlsUtilities.PRF(context, securityParameters.masterSecret, "key expansion",
TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
prfSize);
diff --git a/crypto/src/crypto/tls/TlsCipherFactory.cs b/crypto/src/crypto/tls/TlsCipherFactory.cs
index bd65f8b4b..e5cf96479 100644
--- a/crypto/src/crypto/tls/TlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/TlsCipherFactory.cs
@@ -6,7 +6,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public interface TlsCipherFactory
{
/// <exception cref="IOException"></exception>
- TlsCipher CreateCipher(TlsClientContext context, int encryptionAlgorithm,
+ TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm,
DigestAlgorithm digestAlgorithm);
}
}
diff --git a/crypto/src/crypto/tls/TlsClientContext.cs b/crypto/src/crypto/tls/TlsClientContext.cs
index dbb10aa76..b077d0aaf 100644
--- a/crypto/src/crypto/tls/TlsClientContext.cs
+++ b/crypto/src/crypto/tls/TlsClientContext.cs
@@ -4,12 +4,8 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsClientContext
- {
- SecureRandom SecureRandom { get; }
-
- SecurityParameters SecurityParameters { get; }
-
- object UserObject { get; set; }
- }
+ public interface TlsClientContext
+ : TlsContext
+ {
+ }
}
diff --git a/crypto/src/crypto/tls/TlsClientContextImpl.cs b/crypto/src/crypto/tls/TlsClientContextImpl.cs
index 9d5dee232..674d68937 100644
--- a/crypto/src/crypto/tls/TlsClientContextImpl.cs
+++ b/crypto/src/crypto/tls/TlsClientContextImpl.cs
@@ -4,34 +4,17 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsClientContextImpl
- : TlsClientContext
- {
- private readonly SecureRandom secureRandom;
- private readonly SecurityParameters securityParameters;
+ internal class TlsClientContextImpl
+ : AbstractTlsContext, TlsClientContext
+ {
+ internal TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+ : base(secureRandom, securityParameters)
+ {
+ }
- private object userObject = null;
-
- internal TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
- {
- this.secureRandom = secureRandom;
- this.securityParameters = securityParameters;
- }
-
- public virtual SecureRandom SecureRandom
- {
- get { return secureRandom; }
- }
-
- public virtual SecurityParameters SecurityParameters
- {
- get { return securityParameters; }
- }
-
- public virtual object UserObject
- {
- get { return userObject; }
- set { this.userObject = value; }
- }
- }
+ public override bool IsServer
+ {
+ get { return false; }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index 26d76fd3d..272e38143 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsDHKeyExchange
: TlsKeyExchange
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected int keyExchange;
protected TlsSigner tlsSigner;
@@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsAgreementCredentials agreementCredentials;
protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
- internal TlsDHKeyExchange(TlsClientContext context, int keyExchange)
+ internal TlsDHKeyExchange(TlsContext context, int keyExchange)
{
switch (keyExchange)
{
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index ee6d6eb44..a9e9a394c 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsDheKeyExchange
: TlsDHKeyExchange
{
- internal TlsDheKeyExchange(TlsClientContext context, int keyExchange)
+ internal TlsDheKeyExchange(TlsContext context, int keyExchange)
: base(context, keyExchange)
{
}
diff --git a/crypto/src/crypto/tls/TlsDsaSigner.cs b/crypto/src/crypto/tls/TlsDsaSigner.cs
index bba114e90..a5ac55974 100644
--- a/crypto/src/crypto/tls/TlsDsaSigner.cs
+++ b/crypto/src/crypto/tls/TlsDsaSigner.cs
@@ -7,45 +7,77 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal abstract class TlsDsaSigner
- : TlsSigner
+ public abstract class TlsDsaSigner
+ : AbstractTlsSigner
{
- public virtual byte[] GenerateRawSignature(SecureRandom random,
- AsymmetricKeyParameter privateKey, byte[] md5andsha1)
+ public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
{
- ISigner s = MakeSigner(new NullDigest(), true, new ParametersWithRandom(privateKey, random));
- // Note: Only use the SHA1 part of the hash
- s.BlockUpdate(md5andsha1, 16, 20);
- return s.GenerateSignature();
+ ISigner signer = MakeSigner(algorithm, true, true,
+ new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
+ if (algorithm == null)
+ {
+ // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+ signer.BlockUpdate(hash, 16, 20);
+ }
+ else
+ {
+ signer.BlockUpdate(hash, 0, hash.Length);
+ }
+ return signer.GenerateSignature();
}
- public bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5andsha1)
+ public override bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
{
- ISigner s = MakeSigner(new NullDigest(), false, publicKey);
- // Note: Only use the SHA1 part of the hash
- s.BlockUpdate(md5andsha1, 16, 20);
- return s.VerifySignature(sigBytes);
+ ISigner signer = MakeSigner(algorithm, true, false, publicKey);
+ if (algorithm == null)
+ {
+ // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+ signer.BlockUpdate(hash, 16, 20);
+ }
+ else
+ {
+ signer.BlockUpdate(hash, 0, hash.Length);
+ }
+ return signer.VerifySignature(sigBytes);
}
- public virtual ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey)
+ public override ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
{
- return MakeSigner(new Sha1Digest(), true, new ParametersWithRandom(privateKey, random));
+ return MakeSigner(algorithm, false, true, privateKey);
}
- public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey)
+ public override ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
{
- return MakeSigner(new Sha1Digest(), false, publicKey);
+ return MakeSigner(algorithm, false, false, publicKey);
}
- public abstract bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
+ protected virtual ICipherParameters MakeInitParameters(bool forSigning, ICipherParameters cp)
+ {
+ return cp;
+ }
- protected virtual ISigner MakeSigner(IDigest d, bool forSigning, ICipherParameters cp)
+ protected virtual ISigner MakeSigner(SignatureAndHashAlgorithm algorithm, bool raw, bool forSigning,
+ ICipherParameters cp)
{
- ISigner s = new DsaDigestSigner(CreateDsaImpl(), d);
- s.Init(forSigning, cp);
+ if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext))
+ throw new InvalidOperationException();
+
+ // TODO For TLS 1.2+, lift the SHA-1 restriction here
+ if (algorithm != null && (algorithm.Hash != HashAlgorithm.sha1 || algorithm.Signature != SignatureAlgorithm))
+ throw new InvalidOperationException();
+
+ byte hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.Hash;
+ IDigest d = raw ? new NullDigest() : TlsUtilities.CreateHash(hashAlgorithm);
+
+ ISigner s = new DsaDigestSigner(CreateDsaImpl(hashAlgorithm), d);
+ s.Init(forSigning, MakeInitParameters(forSigning, cp));
return s;
}
- protected abstract IDsa CreateDsaImpl();
+ protected abstract byte SignatureAlgorithm { get; }
+
+ protected abstract IDsa CreateDsaImpl(byte hashAlgorithm);
}
}
diff --git a/crypto/src/crypto/tls/TlsDssSigner.cs b/crypto/src/crypto/tls/TlsDssSigner.cs
index c6f1abcec..707ef3853 100644
--- a/crypto/src/crypto/tls/TlsDssSigner.cs
+++ b/crypto/src/crypto/tls/TlsDssSigner.cs
@@ -5,17 +5,22 @@ using Org.BouncyCastle.Crypto.Signers;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsDssSigner
- : TlsDsaSigner
- {
- public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
- {
- return publicKey is DsaPublicKeyParameters;
- }
+ public class TlsDssSigner
+ : TlsDsaSigner
+ {
+ public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey is DsaPublicKeyParameters;
+ }
- protected override IDsa CreateDsaImpl()
- {
- return new DsaSigner();
- }
- }
+ protected override IDsa CreateDsaImpl(byte hashAlgorithm)
+ {
+ return new DsaSigner(new HMacDsaKCalculator(TlsUtilities.CreateHash(hashAlgorithm)));
+ }
+
+ protected override byte SignatureAlgorithm
+ {
+ get { return Tls.SignatureAlgorithm.dsa; }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
index 65d07a10c..b02d5a4fd 100644
--- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsECDHKeyExchange
: TlsKeyExchange
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected int keyExchange;
protected TlsSigner tlsSigner;
@@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsAgreementCredentials agreementCredentials;
protected ECPrivateKeyParameters ecAgreeClientPrivateKey = null;
- internal TlsECDHKeyExchange(TlsClientContext context, int keyExchange)
+ internal TlsECDHKeyExchange(TlsContext context, int keyExchange)
{
switch (keyExchange)
{
diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
index a36bff75b..5f66dbf59 100644
--- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
internal class TlsECDheKeyExchange : TlsECDHKeyExchange
{
- internal TlsECDheKeyExchange(TlsClientContext context, int keyExchange)
+ internal TlsECDheKeyExchange(TlsContext context, int keyExchange)
: base(context, keyExchange)
{
}
diff --git a/crypto/src/crypto/tls/TlsECDsaSigner.cs b/crypto/src/crypto/tls/TlsECDsaSigner.cs
index 3c30fdc0c..fa9d0b714 100644
--- a/crypto/src/crypto/tls/TlsECDsaSigner.cs
+++ b/crypto/src/crypto/tls/TlsECDsaSigner.cs
@@ -5,17 +5,22 @@ using Org.BouncyCastle.Crypto.Signers;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsECDsaSigner
- : TlsDsaSigner
- {
- public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
- {
- return publicKey is ECPublicKeyParameters;
- }
+ public class TlsECDsaSigner
+ : TlsDsaSigner
+ {
+ public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey is ECPublicKeyParameters;
+ }
- protected override IDsa CreateDsaImpl()
- {
- return new ECDsaSigner();
- }
- }
+ protected override IDsa CreateDsaImpl(byte hashAlgorithm)
+ {
+ return new ECDsaSigner(new HMacDsaKCalculator(TlsUtilities.CreateHash(hashAlgorithm)));
+ }
+
+ protected override byte SignatureAlgorithm
+ {
+ get { return Tls.SignatureAlgorithm.ecdsa; }
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsEncryptionCredentials.cs b/crypto/src/crypto/tls/TlsEncryptionCredentials.cs
new file mode 100644
index 000000000..52f007006
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsEncryptionCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public interface TlsEncryptionCredentials
+ : TlsCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsProtocolHandler.cs b/crypto/src/crypto/tls/TlsProtocolHandler.cs
index 72bf8c5cf..cf1296b14 100644
--- a/crypto/src/crypto/tls/TlsProtocolHandler.cs
+++ b/crypto/src/crypto/tls/TlsProtocolHandler.cs
@@ -269,9 +269,8 @@ namespace Org.BouncyCastle.Crypto.Tls
/*
* Calculate our own checksum.
*/
- byte[] expectedServerVerifyData = TlsUtilities.PRF(
- securityParameters.masterSecret, "server finished",
- rs.GetCurrentHash(), 12);
+ byte[] expectedServerVerifyData = TlsUtilities.PRF(tlsClientContext,
+ securityParameters.masterSecret, ExporterLabel.server_finished, rs.GetCurrentHash(), 12);
/*
* Compare both checksums.
@@ -388,7 +387,7 @@ namespace Org.BouncyCastle.Crypto.Tls
continue;
// TODO Add session resumption support
- ///*
+ //*
// * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore
// * extensions appearing in the client hello, and send a server hello containing no
// * extensions[.]
@@ -546,9 +545,8 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
byte[] pms = this.keyExchange.GeneratePremasterSecret();
- securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret",
- TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom),
- 48);
+ securityParameters.masterSecret = TlsUtilities.PRF(tlsClientContext, pms, ExporterLabel.master_secret,
+ TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom), 48);
// TODO Is there a way to ensure the data is really overwritten?
/*
@@ -565,8 +563,8 @@ namespace Org.BouncyCastle.Crypto.Tls
/*
* Send our finished message.
*/
- byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret,
- "client finished", rs.GetCurrentHash(), 12);
+ byte[] clientVerifyData = TlsUtilities.PRF(tlsClientContext, securityParameters.masterSecret,
+ ExporterLabel.client_finished, rs.GetCurrentHash(), 12);
MemoryStream bos = new MemoryStream();
TlsUtilities.WriteUint8((byte)HandshakeType.finished, bos);
@@ -818,19 +816,22 @@ namespace Org.BouncyCastle.Crypto.Tls
if (this.tlsClient != null)
throw new InvalidOperationException("Connect can only be called once");
- /*
- * Send Client hello
- *
- * First, generate some random data.
- */
+ this.tlsClient = tlsClient;
+
this.securityParameters = new SecurityParameters();
- this.securityParameters.clientRandom = CreateRandomBlock(tlsClient.ShouldUseGmtUnixTime(), random,
- ExporterLabel.client_random);
this.tlsClientContext = new TlsClientContextImpl(random, securityParameters);
- this.tlsClient = tlsClient;
+
+ this.securityParameters.clientRandom = CreateRandomBlock(tlsClient.ShouldUseGmtUnixTime(),
+ tlsClientContext.NonceRandomGenerator);
+
this.tlsClient.Init(tlsClientContext);
+ /*
+ * Send Client hello
+ *
+ * First, send the client_random data.
+ */
MemoryStream outStr = new MemoryStream();
TlsUtilities.WriteVersion(outStr);
outStr.Write(securityParameters.clientRandom, 0, 32);
@@ -1160,20 +1161,10 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- protected static byte[] CreateRandomBlock(bool useGMTUnixTime, SecureRandom random, string asciiLabel)
+ protected static byte[] CreateRandomBlock(bool useGMTUnixTime, IRandomGenerator randomGenerator)
{
- /*
- * We use the TLS 1.0 PRF on the SecureRandom output, to guard against RNGs where the raw
- * output could be used to recover the internal state.
- */
- byte[] secret = new byte[32];
- random.NextBytes(secret);
-
- byte[] seed = new byte[8];
- // TODO Use high-resolution timer
- TlsUtilities.WriteUint64(DateTimeUtilities.CurrentUnixMs(), seed, 0);
-
- byte[] result = TlsUtilities.PRF(secret, asciiLabel, seed, 32);
+ byte[] result = new byte[32];
+ randomGenerator.NextBytes(result);
if (useGMTUnixTime)
{
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index 9961fc9d1..4a5cb4ead 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -11,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsPskKeyExchange
: TlsKeyExchange
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected int keyExchange;
protected TlsPskIdentity pskIdentity;
@@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected RsaKeyParameters rsaServerPublicKey = null;
protected byte[] premasterSecret;
- internal TlsPskKeyExchange(TlsClientContext context, int keyExchange,
+ internal TlsPskKeyExchange(TlsContext context, int keyExchange,
TlsPskIdentity pskIdentity)
{
switch (keyExchange)
@@ -139,7 +139,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public virtual void GenerateClientKeyExchange(Stream output)
{
- if (psk_identity_hint == null || psk_identity_hint.Length == 0)
+ if (psk_identity_hint == null)
{
pskIdentity.SkipIdentityHint();
}
@@ -152,16 +152,21 @@ namespace Org.BouncyCastle.Crypto.Tls
TlsUtilities.WriteOpaque16(psk_identity, output);
- if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
- context.SecureRandom, this.rsaServerPublicKey, output);
- }
- else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(
context.SecureRandom, this.dhAgreeServerPublicKey.Parameters, output);
}
+ else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
+ context, this.rsaServerPublicKey, output);
+ }
}
public virtual byte[] GeneratePremasterSecret()
diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
index aad482316..0a9fbc67d 100644
--- a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs
@@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsRsaKeyExchange
: TlsKeyExchange
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected AsymmetricKeyParameter serverPublicKey = null;
@@ -25,7 +25,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected byte[] premasterSecret;
- internal TlsRsaKeyExchange(TlsClientContext context)
+ internal TlsRsaKeyExchange(TlsContext context)
{
this.context = context;
}
@@ -110,8 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public virtual void GenerateClientKeyExchange(Stream output)
{
- this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(
- context.SecureRandom, this.rsaServerPublicKey, output);
+ this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, this.rsaServerPublicKey, output);
}
public virtual byte[] GeneratePremasterSecret()
diff --git a/crypto/src/crypto/tls/TlsRsaSigner.cs b/crypto/src/crypto/tls/TlsRsaSigner.cs
index ce18ef5e1..6da1c5e9b 100644
--- a/crypto/src/crypto/tls/TlsRsaSigner.cs
+++ b/crypto/src/crypto/tls/TlsRsaSigner.cs
@@ -10,50 +10,92 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- internal class TlsRsaSigner
- : TlsSigner
+ public class TlsRsaSigner
+ : AbstractTlsSigner
{
- public virtual byte[] GenerateRawSignature(SecureRandom random,
- AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+ public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
{
- IAsymmetricBlockCipher engine = CreateRsaImpl();
- engine.Init(true, new ParametersWithRandom(privateKey, random));
- return engine.ProcessBlock(md5AndSha1, 0, md5AndSha1.Length);
+ ISigner signer = MakeSigner(algorithm, true, true,
+ new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
+ signer.BlockUpdate(hash, 0, hash.Length);
+ return signer.GenerateSignature();
}
- public virtual bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey,
- byte[] md5AndSha1)
+ public override bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
{
- IAsymmetricBlockCipher engine = CreateRsaImpl();
- engine.Init(false, publicKey);
- byte[] signed = engine.ProcessBlock(sigBytes, 0, sigBytes.Length);
- return Arrays.ConstantTimeAreEqual(signed, md5AndSha1);
+ ISigner signer = MakeSigner(algorithm, true, false, publicKey);
+ signer.BlockUpdate(hash, 0, hash.Length);
+ return signer.VerifySignature(sigBytes);
}
- public virtual ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey)
+ public override ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
{
- return MakeSigner(new CombinedHash(), true, new ParametersWithRandom(privateKey, random));
+ return MakeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
}
- public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey)
+ public override ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
{
- return MakeSigner(new CombinedHash(), false, publicKey);
+ return MakeSigner(algorithm, false, false, publicKey);
}
- public virtual bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+ public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
{
return publicKey is RsaKeyParameters && !publicKey.IsPrivate;
}
- protected virtual ISigner MakeSigner(IDigest d, bool forSigning, ICipherParameters cp)
+ protected virtual ISigner MakeSigner(SignatureAndHashAlgorithm algorithm, bool raw, bool forSigning,
+ ICipherParameters cp)
{
- ISigner s = new GenericSigner(CreateRsaImpl(), d);
+ if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext))
+ throw new InvalidOperationException();
+ if (algorithm != null && algorithm.Signature != SignatureAlgorithm.rsa)
+ throw new InvalidOperationException();
+
+ IDigest d;
+ if (raw)
+ {
+ d = new NullDigest();
+ }
+ else if (algorithm == null)
+ {
+ d = new CombinedHash();
+ }
+ else
+ {
+ d = TlsUtilities.CreateHash(algorithm.Hash);
+ }
+
+ ISigner s;
+ if (algorithm != null)
+ {
+ /*
+ * RFC 5246 4.7. In RSA signing, the opaque vector contains the signature generated
+ * using the RSASSA-PKCS1-v1_5 signature scheme defined in [PKCS1].
+ */
+ s = new RsaDigestSigner(d, TlsUtilities.GetOidForHashAlgorithm(algorithm.Hash));
+ }
+ else
+ {
+ /*
+ * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme
+ * that did not include a DigestInfo encoding.
+ */
+ s = new GenericSigner(CreateRsaImpl(), d);
+ }
s.Init(forSigning, cp);
return s;
}
protected virtual IAsymmetricBlockCipher CreateRsaImpl()
{
+ /*
+ * RFC 5264 7.4.7.1. Implementation note: It is now known that remote timing-based attacks
+ * on TLS are possible, at least when the client and server are on the same LAN.
+ * Accordingly, implementations that use static RSA keys MUST use RSA blinding or some other
+ * anti-timing technique, as described in [TIMING].
+ */
return new Pkcs1Encoding(new RsaBlindedEngine());
}
}
diff --git a/crypto/src/crypto/tls/TlsRsaUtilities.cs b/crypto/src/crypto/tls/TlsRsaUtilities.cs
index 4450ba452..de56ffc4d 100644
--- a/crypto/src/crypto/tls/TlsRsaUtilities.cs
+++ b/crypto/src/crypto/tls/TlsRsaUtilities.cs
@@ -5,38 +5,128 @@ using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
- public abstract class TlsRsaUtilities
- {
- public static byte[] GenerateEncryptedPreMasterSecret(SecureRandom random,
- RsaKeyParameters rsaServerPublicKey, Stream output)
- {
- /*
- * Choose a PremasterSecret and send it encrypted to the server
- */
- byte[] premasterSecret = new byte[48];
- random.NextBytes(premasterSecret);
- TlsUtilities.WriteVersion(premasterSecret, 0);
-
- Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine());
- encoding.Init(true, new ParametersWithRandom(rsaServerPublicKey, random));
-
- try
- {
- byte[] keData = encoding.ProcessBlock(premasterSecret, 0, premasterSecret.Length);
- TlsUtilities.WriteOpaque16(keData, output);
- }
- catch (InvalidCipherTextException)
- {
- /*
- * This should never happen, only during decryption.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- return premasterSecret;
- }
- }
+ public abstract class TlsRsaUtilities
+ {
+ /// <exception cref="IOException"></exception>
+ public static byte[] GenerateEncryptedPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPublicKey,
+ Stream output)
+ {
+ /*
+ * Choose a PremasterSecret and send it encrypted to the server
+ */
+ byte[] premasterSecret = new byte[48];
+ context.SecureRandom.NextBytes(premasterSecret);
+ TlsUtilities.WriteVersion(context.ClientVersion, premasterSecret, 0);
+
+ Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine());
+ encoding.Init(true, new ParametersWithRandom(rsaServerPublicKey, context.SecureRandom));
+
+ try
+ {
+ byte[] encryptedPreMasterSecret = encoding.ProcessBlock(premasterSecret, 0, premasterSecret.Length);
+
+ if (TlsUtilities.IsSsl(context))
+ {
+ // TODO Do any SSLv3 servers actually expect the length?
+ output.Write(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
+ }
+ else
+ {
+ TlsUtilities.WriteOpaque16(encryptedPreMasterSecret, output);
+ }
+ }
+ catch (InvalidCipherTextException)
+ {
+ /*
+ * This should never happen, only during decryption.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return premasterSecret;
+ }
+
+ public static byte[] SafeDecryptPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPrivateKey,
+ byte[] encryptedPreMasterSecret)
+ {
+ /*
+ * RFC 5246 7.4.7.1.
+ */
+ ProtocolVersion clientVersion = context.ClientVersion;
+
+ // TODO Provide as configuration option?
+ bool versionNumberCheckDisabled = false;
+
+ /*
+ * Generate 48 random bytes we can use as a Pre-Master-Secret, if the
+ * PKCS1 padding check should fail.
+ */
+ byte[] fallback = new byte[48];
+ context.SecureRandom.NextBytes(fallback);
+
+ byte[] M = Arrays.Clone(fallback);
+ try
+ {
+ Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine(), fallback);
+ encoding.Init(false,
+ new ParametersWithRandom(rsaServerPrivateKey, context.SecureRandom));
+
+ M = encoding.ProcessBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
+ }
+ catch (Exception)
+ {
+ /*
+ * This should never happen since the decryption should never throw an exception
+ * and return a random value instead.
+ *
+ * In any case, a TLS server MUST NOT generate an alert if processing an
+ * RSA-encrypted premaster secret message fails, or the version number is not as
+ * expected. Instead, it MUST continue the handshake with a randomly generated
+ * premaster secret.
+ */
+ }
+
+ /*
+ * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST
+ * check the version number [..].
+ */
+ if (versionNumberCheckDisabled && clientVersion.IsEqualOrEarlierVersionOf(ProtocolVersion.TLSv10))
+ {
+ /*
+ * If the version number is TLS 1.0 or earlier, server
+ * implementations SHOULD check the version number, but MAY have a
+ * configuration option to disable the check.
+ *
+ * So there is nothing to do here.
+ */
+ }
+ else
+ {
+ /*
+ * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the
+ * clientVersion received during the handshake. If they don't match, we replace the
+ * decrypted Pre-Master-Secret with a random one.
+ */
+ int correct = (clientVersion.MajorVersion ^ (M[0] & 0xff))
+ | (clientVersion.MinorVersion ^ (M[1] & 0xff));
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ int mask = ~((correct & 1) - 1);
+
+ /*
+ * mask will be all bits set to 0xff if the version number differed.
+ */
+ for (int i = 0; i < 48; i++)
+ {
+ M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask));
+ }
+ }
+ return M;
+ }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsServerContext.cs b/crypto/src/crypto/tls/TlsServerContext.cs
new file mode 100644
index 000000000..4021571aa
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsServerContext.cs
@@ -0,0 +1,11 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public interface TlsServerContext
+ : TlsContext
+ {
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsServerContextImpl.cs b/crypto/src/crypto/tls/TlsServerContextImpl.cs
new file mode 100644
index 000000000..d56566ffc
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsServerContextImpl.cs
@@ -0,0 +1,20 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ internal class TlsServerContextImpl
+ : AbstractTlsContext, TlsServerContext
+ {
+ internal TlsServerContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+ : base(secureRandom, securityParameters)
+ {
+ }
+
+ public override bool IsServer
+ {
+ get { return true; }
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsSigner.cs b/crypto/src/crypto/tls/TlsSigner.cs
index 79d468fee..ffdd4c9a1 100644
--- a/crypto/src/crypto/tls/TlsSigner.cs
+++ b/crypto/src/crypto/tls/TlsSigner.cs
@@ -1,18 +1,29 @@
using System;
-using Org.BouncyCastle.Security;
-
namespace Org.BouncyCastle.Crypto.Tls
{
public interface TlsSigner
{
- byte[] GenerateRawSignature(SecureRandom random, AsymmetricKeyParameter privateKey,
- byte[] md5andsha1);
- bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5andsha1);
+ void Init(TlsContext context);
+
+ byte[] GenerateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1);
+
+ byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash);
+
+ bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1);
+
+ bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash);
+
+ ISigner CreateSigner(AsymmetricKeyParameter privateKey);
+
+ ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
- ISigner CreateSigner(SecureRandom random, AsymmetricKeyParameter privateKey);
ISigner CreateVerifyer(AsymmetricKeyParameter publicKey);
+ ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
+
bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
}
}
diff --git a/crypto/src/crypto/tls/TlsSignerCredentials.cs b/crypto/src/crypto/tls/TlsSignerCredentials.cs
index 2adb06c26..92ed7cc19 100644
--- a/crypto/src/crypto/tls/TlsSignerCredentials.cs
+++ b/crypto/src/crypto/tls/TlsSignerCredentials.cs
@@ -3,9 +3,12 @@ using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
- public interface TlsSignerCredentials : TlsCredentials
- {
- /// <exception cref="IOException"></exception>
- byte[] GenerateCertificateSignature(byte[] md5andsha1);
- }
+ public interface TlsSignerCredentials
+ : TlsCredentials
+ {
+ /// <exception cref="IOException"></exception>
+ byte[] GenerateCertificateSignature(byte[] hash);
+
+ SignatureAndHashAlgorithm SignatureAndHashAlgorithm { get; }
+ }
}
diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
index 950be87ba..46e0e02b2 100644
--- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal class TlsSrpKeyExchange
: TlsKeyExchange
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected int keyExchange;
protected TlsSigner tlsSigner;
protected byte[] identity;
@@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected BigInteger B = null;
protected Srp6Client srpClient = new Srp6Client();
- internal TlsSrpKeyExchange(TlsClientContext context, int keyExchange,
+ internal TlsSrpKeyExchange(TlsContext context, int keyExchange,
byte[] identity, byte[] password)
{
switch (keyExchange)
diff --git a/crypto/src/crypto/tls/TlsStreamCipher.cs b/crypto/src/crypto/tls/TlsStreamCipher.cs
index 35f794d96..3e6f7e06d 100644
--- a/crypto/src/crypto/tls/TlsStreamCipher.cs
+++ b/crypto/src/crypto/tls/TlsStreamCipher.cs
@@ -9,7 +9,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
public class TlsStreamCipher : TlsCipher
{
- protected TlsClientContext context;
+ protected TlsContext context;
protected IStreamCipher encryptCipher;
protected IStreamCipher decryptCipher;
@@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsMac writeMac;
protected TlsMac readMac;
- public TlsStreamCipher(TlsClientContext context, IStreamCipher encryptCipher,
+ public TlsStreamCipher(TlsContext context, IStreamCipher encryptCipher,
IStreamCipher decryptCipher, IDigest writeDigest, IDigest readDigest, int cipherKeySize)
{
this.context = context;
@@ -29,7 +29,7 @@ namespace Org.BouncyCastle.Crypto.Tls
SecurityParameters securityParameters = context.SecurityParameters;
- byte[] keyBlock = TlsUtilities.PRF(securityParameters.masterSecret, "key expansion",
+ byte[] keyBlock = TlsUtilities.PRF(context, securityParameters.masterSecret, "key expansion",
TlsUtilities.Concat(securityParameters.serverRandom, securityParameters.clientRandom),
prfSize);
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index ffb2fc3e6..462ec4074 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -4,6 +4,8 @@ using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
@@ -660,37 +662,54 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- internal static byte[] PRF(byte[] secret, string asciiLabel, byte[] seed, int size)
+ public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size)
{
- byte[] label = Strings.ToAsciiByteArray(asciiLabel);
+ ProtocolVersion version = context.ServerVersion;
- int s_half = (secret.Length + 1) / 2;
- byte[] s1 = new byte[s_half];
- byte[] s2 = new byte[s_half];
- Array.Copy(secret, 0, s1, 0, s_half);
- Array.Copy(secret, secret.Length - s_half, s2, 0, s_half);
+ if (version.IsSsl)
+ throw new InvalidOperationException("No PRF available for SSLv3 session");
+
+ byte[] label = Strings.ToByteArray(asciiLabel);
+ byte[] labelSeed = Concat(label, seed);
- byte[] ls = Concat(label, seed);
+ int prfAlgorithm = context.SecurityParameters.PrfAlgorithm;
- byte[] buf = new byte[size];
- byte[] prf = new byte[size];
- HMacHash(new MD5Digest(), s1, ls, prf);
- HMacHash(new Sha1Digest(), s2, ls, buf);
- for (int i = 0; i < size; i++)
+ if (prfAlgorithm == PrfAlgorithm.tls_prf_legacy)
{
- buf[i] ^= prf[i];
+ return PRF_legacy(secret, label, labelSeed, size);
}
+
+ IDigest prfDigest = CreatePrfHash(prfAlgorithm);
+ byte[] buf = new byte[size];
+ HMacHash(prfDigest, secret, labelSeed, buf);
return buf;
}
- internal static byte[] PRF_1_2(IDigest digest, byte[] secret, string asciiLabel, byte[] seed, int size)
+ public static byte[] PRF_legacy(byte[] secret, string asciiLabel, byte[] seed, int size)
{
- byte[] label = Strings.ToAsciiByteArray(asciiLabel);
+ byte[] label = Strings.ToByteArray(asciiLabel);
byte[] labelSeed = Concat(label, seed);
- byte[] buf = new byte[size];
- HMacHash(digest, secret, labelSeed, buf);
- return buf;
+ return PRF_legacy(secret, label, labelSeed, size);
+ }
+
+ internal static byte[] PRF_legacy(byte[] secret, byte[] label, byte[] labelSeed, int size)
+ {
+ int s_half = (secret.Length + 1) / 2;
+ byte[] s1 = new byte[s_half];
+ byte[] s2 = new byte[s_half];
+ Array.Copy(secret, 0, s1, 0, s_half);
+ Array.Copy(secret, secret.Length - s_half, s2, 0, s_half);
+
+ byte[] b1 = new byte[size];
+ byte[] b2 = new byte[size];
+ HMacHash(CreateHash(HashAlgorithm.md5), s1, labelSeed, b1);
+ HMacHash(CreateHash(HashAlgorithm.sha1), s2, labelSeed, b2);
+ for (int i = 0; i < size; i++)
+ {
+ b1[i] ^= b2[i];
+ }
+ return b1;
}
internal static byte[] Concat(byte[] a, byte[] b)
@@ -782,6 +801,64 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ public static IDigest CreatePrfHash(int prfAlgorithm)
+ {
+ switch (prfAlgorithm)
+ {
+ case PrfAlgorithm.tls_prf_legacy:
+ return new CombinedHash();
+ default:
+ return CreateHash(GetHashAlgorithmForPrfAlgorithm(prfAlgorithm));
+ }
+ }
+
+ public static IDigest ClonePrfHash(int prfAlgorithm, IDigest hash)
+ {
+ switch (prfAlgorithm)
+ {
+ case PrfAlgorithm.tls_prf_legacy:
+ return new CombinedHash((CombinedHash)hash);
+ default:
+ return CloneHash(GetHashAlgorithmForPrfAlgorithm(prfAlgorithm), hash);
+ }
+ }
+
+ public static byte GetHashAlgorithmForPrfAlgorithm(int prfAlgorithm)
+ {
+ switch (prfAlgorithm)
+ {
+ case PrfAlgorithm.tls_prf_legacy:
+ throw new ArgumentException("legacy PRF not a valid algorithm", "prfAlgorithm");
+ case PrfAlgorithm.tls_prf_sha256:
+ return HashAlgorithm.sha256;
+ case PrfAlgorithm.tls_prf_sha384:
+ return HashAlgorithm.sha384;
+ default:
+ throw new ArgumentException("unknown PrfAlgorithm", "prfAlgorithm");
+ }
+ }
+
+ public static DerObjectIdentifier GetOidForHashAlgorithm(byte hashAlgorithm)
+ {
+ switch (hashAlgorithm)
+ {
+ case HashAlgorithm.md5:
+ return PkcsObjectIdentifiers.MD5;
+ case HashAlgorithm.sha1:
+ return X509ObjectIdentifiers.IdSha1;
+ case HashAlgorithm.sha224:
+ return NistObjectIdentifiers.IdSha224;
+ case HashAlgorithm.sha256:
+ return NistObjectIdentifiers.IdSha256;
+ case HashAlgorithm.sha384:
+ return NistObjectIdentifiers.IdSha384;
+ case HashAlgorithm.sha512:
+ return NistObjectIdentifiers.IdSha512;
+ default:
+ throw new ArgumentException("unknown HashAlgorithm", "hashAlgorithm");
+ }
+ }
+
private static IList VectorOfOne(object obj)
{
IList v = Platform.CreateArrayList(1);
|