diff --git a/crypto/src/crypto/tls/DeferredHash.cs b/crypto/src/crypto/tls/DeferredHash.cs
index 1112d4a3c..f402f26d2 100644
--- a/crypto/src/crypto/tls/DeferredHash.cs
+++ b/crypto/src/crypto/tls/DeferredHash.cs
@@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Crypto.Tls
{
IDigest d = (IDigest)mHashes[hashAlgorithm];
if (d == null)
- throw new InvalidOperationException("HashAlgorithm " + hashAlgorithm + " is not being tracked");
+ throw new InvalidOperationException("HashAlgorithm." + HashAlgorithm.GetText(hashAlgorithm) + " is not being tracked");
d = TlsUtilities.CloneHash(hashAlgorithm, d);
if (mBuf != null)
diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs
index 9c7caf290..e2e9eddfc 100644
--- a/crypto/src/crypto/tls/DtlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs
@@ -458,6 +458,9 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual void ProcessCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
{
+ if (state.certificateRequest == null)
+ throw new InvalidOperationException();
+
MemoryStream buf = new MemoryStream(body, false);
TlsServerContextImpl context = state.serverContext;
@@ -466,13 +469,15 @@ namespace Org.BouncyCastle.Crypto.Tls
TlsProtocol.AssertEmpty(buf);
// Verify the CertificateVerify message contains a correct signature.
- bool verified = false;
try
{
+ SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm;
+
byte[] hash;
if (TlsUtilities.IsTlsV12(context))
{
- hash = prepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash);
+ TlsUtilities.VerifySupportedSignatureAlgorithm(state.certificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm);
+ hash = prepareFinishHash.GetFinalHash(signatureAlgorithm.Hash);
}
else
{
@@ -485,15 +490,17 @@ namespace Org.BouncyCastle.Crypto.Tls
TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)state.clientCertificateType);
tlsSigner.Init(context);
- verified = tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm,
- clientCertificateVerify.Signature, publicKey, hash);
+ if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash))
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
- catch (Exception)
+ catch (TlsFatalAlert e)
{
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new TlsFatalAlert(AlertDescription.decrypt_error, e);
}
-
- if (!verified)
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body)
diff --git a/crypto/src/crypto/tls/HashAlgorithm.cs b/crypto/src/crypto/tls/HashAlgorithm.cs
index ac6def26f..ff540d2e0 100644
--- a/crypto/src/crypto/tls/HashAlgorithm.cs
+++ b/crypto/src/crypto/tls/HashAlgorithm.cs
@@ -12,5 +12,33 @@ namespace Org.BouncyCastle.Crypto.Tls
public const byte sha256 = 4;
public const byte sha384 = 5;
public const byte sha512 = 6;
+
+ public static string GetName(byte hashAlgorithm)
+ {
+ switch (hashAlgorithm)
+ {
+ case none:
+ return "none";
+ case md5:
+ return "md5";
+ case sha1:
+ return "sha1";
+ case sha224:
+ return "sha224";
+ case sha256:
+ return "sha256";
+ case sha384:
+ return "sha384";
+ case sha512:
+ return "sha512";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ public static string GetText(byte hashAlgorithm)
+ {
+ return GetName(hashAlgorithm) + "(" + hashAlgorithm + ")";
+ }
}
}
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index 4ab628b13..5716c0cd1 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -460,6 +460,9 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf)
{
+ if (mCertificateRequest == null)
+ throw new InvalidOperationException();
+
DigitallySigned clientCertificateVerify = DigitallySigned.Parse(Context, buf);
AssertEmpty(buf);
@@ -467,10 +470,13 @@ namespace Org.BouncyCastle.Crypto.Tls
// Verify the CertificateVerify message contains a correct signature.
try
{
+ SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm;
+
byte[] hash;
if (TlsUtilities.IsTlsV12(Context))
{
- hash = mPrepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash);
+ TlsUtilities.VerifySupportedSignatureAlgorithm(mCertificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm);
+ hash = mPrepareFinishHash.GetFinalHash(signatureAlgorithm.Hash);
}
else
{
@@ -483,11 +489,12 @@ namespace Org.BouncyCastle.Crypto.Tls
TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)mClientCertificateType);
tlsSigner.Init(Context);
- if (!tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm,
- clientCertificateVerify.Signature, publicKey, hash))
- {
+ if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash))
throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
+ }
+ catch (TlsFatalAlert e)
+ {
+ throw e;
}
catch (Exception e)
{
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 26fb0d5e8..7d1d488d7 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -129,14 +129,24 @@ namespace Org.BouncyCastle.Crypto.Tls
return context.ServerVersion.IsSsl;
}
+ public static bool IsTlsV11(ProtocolVersion version)
+ {
+ return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion());
+ }
+
public static bool IsTlsV11(TlsContext context)
{
- return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+ return IsTlsV11(context.ServerVersion);
+ }
+
+ public static bool IsTlsV12(ProtocolVersion version)
+ {
+ return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion());
}
public static bool IsTlsV12(TlsContext context)
{
- return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+ return IsTlsV12(context.ServerVersion);
}
public static void WriteUint8(byte i, Stream output)
@@ -712,11 +722,10 @@ namespace Org.BouncyCastle.Crypto.Tls
public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, bool allowAnonymous,
Stream output)
{
- if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
- || supportedSignatureAlgorithms.Count >= (1 << 15))
- {
+ if (supportedSignatureAlgorithms == null)
+ throw new ArgumentNullException("supportedSignatureAlgorithms");
+ if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15))
throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
- }
// supported_signature_algorithms
int length = 2 * supportedSignatureAlgorithms.Count;
@@ -762,6 +771,27 @@ namespace Org.BouncyCastle.Crypto.Tls
return supportedSignatureAlgorithms;
}
+ public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm)
+ {
+ if (supportedSignatureAlgorithms == null)
+ throw new ArgumentNullException("supportedSignatureAlgorithms");
+ if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15))
+ throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
+ if (signatureAlgorithm == null)
+ throw new ArgumentNullException("signatureAlgorithm");
+
+ if (signatureAlgorithm.Signature != SignatureAlgorithm.anonymous)
+ {
+ foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
+ {
+ if (entry.Hash == signatureAlgorithm.Hash && entry.Signature == signatureAlgorithm.Signature)
+ return;
+ }
+ }
+
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size)
{
ProtocolVersion version = context.ServerVersion;
|