diff --git a/crypto/src/tls/CertificateCompressionAlgorithm.cs b/crypto/src/tls/CertificateCompressionAlgorithm.cs
new file mode 100644
index 000000000..4b6ebdadc
--- /dev/null
+++ b/crypto/src/tls/CertificateCompressionAlgorithm.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Tls
+{
+ /**
+ * RFC 8879
+ */
+ public abstract class CertificateCompressionAlgorithm
+ {
+ public const int zlib = 1;
+ public const int brotli = 2;
+ public const int zstd = 3;
+
+ public static string GetName(int certificateCompressionAlgorithm)
+ {
+ switch (certificateCompressionAlgorithm)
+ {
+ case zlib:
+ return "zlib";
+ case brotli:
+ return "brotli";
+ case zstd:
+ return "zstd";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ public static string GetText(int certificateCompressionAlgorithm)
+ {
+ return GetName(certificateCompressionAlgorithm) + "(" + certificateCompressionAlgorithm + ")";
+ }
+
+ public static bool IsRecognized(int certificateCompressionAlgorithm)
+ {
+ switch (certificateCompressionAlgorithm)
+ {
+ case zlib:
+ case brotli:
+ case zstd:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/crypto/src/tls/DeferredHash.cs b/crypto/src/tls/DeferredHash.cs
index bba3019a1..ac66c8f0c 100644
--- a/crypto/src/tls/DeferredHash.cs
+++ b/crypto/src/tls/DeferredHash.cs
@@ -16,7 +16,7 @@ namespace Org.BouncyCastle.Tls
private readonly TlsContext m_context;
private DigestInputBuffer m_buf;
- private readonly IDictionary m_hashes;
+ private IDictionary m_hashes;
private bool m_forceBuffering;
private bool m_sealed;
@@ -29,25 +29,16 @@ namespace Org.BouncyCastle.Tls
this.m_sealed = false;
}
- private DeferredHash(TlsContext context, IDictionary hashes)
- {
- this.m_context = context;
- this.m_buf = null;
- this.m_hashes = hashes;
- this.m_forceBuffering = false;
- this.m_sealed = true;
- }
-
/// <exception cref="IOException"/>
public void CopyBufferTo(Stream output)
{
if (m_buf == null)
{
- // If you see this, you need to call forceBuffering() before SealHashAlgorithms()
+ // If you see this, you need to call ForceBuffering() before SealHashAlgorithms()
throw new InvalidOperationException("Not buffering");
}
- m_buf.CopyTo(output);
+ m_buf.CopyInputTo(output);
}
public void ForceBuffering()
@@ -96,7 +87,7 @@ namespace Org.BouncyCastle.Tls
CheckStopBuffering();
}
- public TlsHandshakeHash StopTracking()
+ public void StopTracking()
{
SecurityParameters securityParameters = m_context.SecurityParameters;
@@ -106,8 +97,8 @@ namespace Org.BouncyCastle.Tls
case PrfAlgorithm.ssl_prf_legacy:
case PrfAlgorithm.tls_prf_legacy:
{
- CloneHash(newHashes, HashAlgorithm.md5);
- CloneHash(newHashes, HashAlgorithm.sha1);
+ CloneHash(newHashes, CryptoHashAlgorithm.md5);
+ CloneHash(newHashes, CryptoHashAlgorithm.sha1);
break;
}
default:
@@ -116,7 +107,11 @@ namespace Org.BouncyCastle.Tls
break;
}
}
- return new DeferredHash(m_context, newHashes);
+
+ this.m_buf = null;
+ this.m_hashes = newHashes;
+ this.m_forceBuffering = false;
+ this.m_sealed = true;
}
public TlsHash ForkPrfHash()
@@ -131,7 +126,9 @@ namespace Org.BouncyCastle.Tls
case PrfAlgorithm.ssl_prf_legacy:
case PrfAlgorithm.tls_prf_legacy:
{
- prfHash = new CombinedHash(m_context, CloneHash(HashAlgorithm.md5), CloneHash(HashAlgorithm.sha1));
+ TlsHash md5Hash = CloneHash(CryptoHashAlgorithm.md5);
+ TlsHash sha1Hash = CloneHash(CryptoHashAlgorithm.sha1);
+ prfHash = new CombinedHash(m_context, md5Hash, sha1Hash);
break;
}
default:
@@ -151,20 +148,20 @@ namespace Org.BouncyCastle.Tls
public byte[] GetFinalHash(int cryptoHashAlgorithm)
{
- TlsHash d = (TlsHash)m_hashes[cryptoHashAlgorithm];
- if (d == null)
+ TlsHash hash = (TlsHash)m_hashes[cryptoHashAlgorithm];
+ if (hash == null)
throw new InvalidOperationException("CryptoHashAlgorithm." + cryptoHashAlgorithm
+ " is not being tracked");
CheckStopBuffering();
- d = d.CloneHash();
+ hash = hash.CloneHash();
if (m_buf != null)
{
- m_buf.UpdateDigest(d);
+ m_buf.UpdateDigest(hash);
}
- return d.CalculateHash();
+ return hash.CalculateHash();
}
public void Update(byte[] input, int inOff, int len)
diff --git a/crypto/src/tls/DigestInputBuffer.cs b/crypto/src/tls/DigestInputBuffer.cs
index 7dd525f88..9b4ea4b06 100644
--- a/crypto/src/tls/DigestInputBuffer.cs
+++ b/crypto/src/tls/DigestInputBuffer.cs
@@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
- internal void CopyTo(Stream output)
+ internal void CopyInputTo(Stream output)
{
// TODO[tls-port]
// NOTE: Copy data since the output here may be under control of external code.
diff --git a/crypto/src/tls/DtlsReliableHandshake.cs b/crypto/src/tls/DtlsReliableHandshake.cs
index e27d72762..7581e4766 100644
--- a/crypto/src/tls/DtlsReliableHandshake.cs
+++ b/crypto/src/tls/DtlsReliableHandshake.cs
@@ -142,11 +142,9 @@ namespace Org.BouncyCastle.Tls
get { return m_handshakeHash; }
}
- internal TlsHandshakeHash PrepareToFinish()
+ internal void PrepareToFinish()
{
- TlsHandshakeHash result = m_handshakeHash;
- this.m_handshakeHash = m_handshakeHash.StopTracking();
- return result;
+ m_handshakeHash.StopTracking();
}
/// <exception cref="IOException"/>
@@ -173,68 +171,60 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
+ internal Message ReceiveMessage()
+ {
+ Message message = ImplReceiveMessage();
+ UpdateHandshakeMessagesDigest(message);
+ return message;
+ }
+
+ /// <exception cref="IOException"/>
internal byte[] ReceiveMessageBody(short msg_type)
{
- Message message = ReceiveMessage();
+ Message message = ImplReceiveMessage();
if (message.Type != msg_type)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ UpdateHandshakeMessagesDigest(message);
return message.Body;
}
/// <exception cref="IOException"/>
- internal Message ReceiveMessage()
+ internal Message ReceiveMessageDelayedDigest(short msg_type)
{
- long currentTimeMillis = DateTimeUtilities.CurrentUnixMs();
-
- if (null == m_resendTimeout)
- {
- m_resendMillis = INITIAL_RESEND_MILLIS;
- m_resendTimeout = new Timeout(m_resendMillis, currentTimeMillis);
-
- PrepareInboundFlight(Platform.CreateHashtable());
- }
+ Message message = ImplReceiveMessage();
+ if (message.Type != msg_type)
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
- byte[] buf = null;
+ return message;
+ }
- for (;;)
+ /// <exception cref="IOException"/>
+ internal void UpdateHandshakeMessagesDigest(Message message)
+ {
+ short msg_type = message.Type;
+ switch (msg_type)
{
- if (m_recordLayer.IsClosed)
- throw new TlsFatalAlert(AlertDescription.user_canceled);
-
- Message pending = GetPendingMessage();
- if (pending != null)
- return pending;
-
- if (Timeout.HasExpired(m_handshakeTimeout, currentTimeMillis))
- throw new TlsTimeoutException("Handshake timed out");
-
- int waitMillis = Timeout.GetWaitMillis(m_handshakeTimeout, currentTimeMillis);
- waitMillis = Timeout.ConstrainWaitMillis(waitMillis, m_resendTimeout, currentTimeMillis);
-
- // NOTE: Ensure a finite wait, of at least 1ms
- if (waitMillis < 1)
- {
- waitMillis = 1;
- }
-
- int receiveLimit = m_recordLayer.GetReceiveLimit();
- if (buf == null || buf.Length < receiveLimit)
- {
- buf = new byte[receiveLimit];
- }
-
- int received = m_recordLayer.Receive(buf, 0, receiveLimit, waitMillis);
- if (received < 0)
- {
- ResendOutboundFlight();
- }
- else
- {
- ProcessRecord(MAX_RECEIVE_AHEAD, m_recordLayer.ReadEpoch, buf, 0, received);
- }
+ case HandshakeType.hello_request:
+ case HandshakeType.hello_verify_request:
+ case HandshakeType.key_update:
+ break;
- currentTimeMillis = DateTimeUtilities.CurrentUnixMs();
+ // TODO[dtls13] Not included in the transcript for (D)TLS 1.3+
+ case HandshakeType.new_session_ticket:
+ default:
+ {
+ byte[] body = message.Body;
+ byte[] buf = new byte[MESSAGE_HEADER_LENGTH];
+ TlsUtilities.WriteUint8(msg_type, buf, 0);
+ TlsUtilities.WriteUint24(body.Length, buf, 1);
+ TlsUtilities.WriteUint16(message.Seq, buf, 4);
+ TlsUtilities.WriteUint24(0, buf, 6);
+ TlsUtilities.WriteUint24(body.Length, buf, 9);
+ m_handshakeHash.Update(buf, 0, buf.Length);
+ m_handshakeHash.Update(body, 0, body.Length);
+ break;
+ }
}
}
@@ -297,12 +287,68 @@ namespace Org.BouncyCastle.Tls
if (body != null)
{
m_previousInboundFlight = null;
- return UpdateHandshakeMessagesDigest(new Message(m_next_receive_seq++, next.MsgType, body));
+ return new Message(m_next_receive_seq++, next.MsgType, body);
}
}
return null;
}
+ /// <exception cref="IOException"/>
+ private Message ImplReceiveMessage()
+ {
+ long currentTimeMillis = DateTimeUtilities.CurrentUnixMs();
+
+ if (null == m_resendTimeout)
+ {
+ m_resendMillis = INITIAL_RESEND_MILLIS;
+ m_resendTimeout = new Timeout(m_resendMillis, currentTimeMillis);
+
+ PrepareInboundFlight(Platform.CreateHashtable());
+ }
+
+ byte[] buf = null;
+
+ for (;;)
+ {
+ if (m_recordLayer.IsClosed)
+ throw new TlsFatalAlert(AlertDescription.user_canceled);
+
+ Message pending = GetPendingMessage();
+ if (pending != null)
+ return pending;
+
+ if (Timeout.HasExpired(m_handshakeTimeout, currentTimeMillis))
+ throw new TlsTimeoutException("Handshake timed out");
+
+ int waitMillis = Timeout.GetWaitMillis(m_handshakeTimeout, currentTimeMillis);
+ waitMillis = Timeout.ConstrainWaitMillis(waitMillis, m_resendTimeout, currentTimeMillis);
+
+ // NOTE: Ensure a finite wait, of at least 1ms
+ if (waitMillis < 1)
+ {
+ waitMillis = 1;
+ }
+
+ int receiveLimit = m_recordLayer.GetReceiveLimit();
+ if (buf == null || buf.Length < receiveLimit)
+ {
+ buf = new byte[receiveLimit];
+ }
+
+ int received = m_recordLayer.Receive(buf, 0, receiveLimit, waitMillis);
+ if (received < 0)
+ {
+ ResendOutboundFlight();
+ }
+ else
+ {
+ ProcessRecord(MAX_RECEIVE_AHEAD, m_recordLayer.ReadEpoch, buf, 0, received);
+ }
+
+ currentTimeMillis = DateTimeUtilities.CurrentUnixMs();
+ }
+ }
+
private void PrepareInboundFlight(IDictionary nextFlight)
{
ResetAll(m_currentInboundFlight);
@@ -400,37 +446,6 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
- private Message UpdateHandshakeMessagesDigest(Message message)
- {
- short msg_type = message.Type;
- switch (msg_type)
- {
- case HandshakeType.hello_request:
- case HandshakeType.hello_verify_request:
- case HandshakeType.key_update:
- break;
-
- // TODO[dtls13] Not included in the transcript for (D)TLS 1.3+
- case HandshakeType.new_session_ticket:
- default:
- {
- byte[] body = message.Body;
- byte[] buf = new byte[MESSAGE_HEADER_LENGTH];
- TlsUtilities.WriteUint8(msg_type, buf, 0);
- TlsUtilities.WriteUint24(body.Length, buf, 1);
- TlsUtilities.WriteUint16(message.Seq, buf, 4);
- TlsUtilities.WriteUint24(0, buf, 6);
- TlsUtilities.WriteUint24(body.Length, buf, 9);
- m_handshakeHash.Update(buf, 0, buf.Length);
- m_handshakeHash.Update(body, 0, body.Length);
- break;
- }
- }
-
- return message;
- }
-
- /// <exception cref="IOException"/>
private void WriteMessage(Message message)
{
int sendLimit = m_recordLayer.GetSendLimit();
diff --git a/crypto/src/tls/DtlsServerProtocol.cs b/crypto/src/tls/DtlsServerProtocol.cs
index 99c47ba1b..b49122423 100644
--- a/crypto/src/tls/DtlsServerProtocol.cs
+++ b/crypto/src/tls/DtlsServerProtocol.cs
@@ -297,12 +297,17 @@ namespace Org.BouncyCastle.Tls
* parameters).
*/
{
- TlsHandshakeHash certificateVerifyHash = handshake.PrepareToFinish();
-
if (ExpectCertificateVerifyMessage(state))
{
- byte[] certificateVerifyBody = handshake.ReceiveMessageBody(HandshakeType.certificate_verify);
- ProcessCertificateVerify(state, certificateVerifyBody, certificateVerifyHash);
+ clientMessage = handshake.ReceiveMessageDelayedDigest(HandshakeType.certificate_verify);
+ byte[] certificateVerifyBody = clientMessage.Body;
+ ProcessCertificateVerify(state, certificateVerifyBody, handshake.HandshakeHash);
+ handshake.PrepareToFinish();
+ handshake.UpdateHandshakeMessagesDigest(clientMessage);
+ }
+ else
+ {
+ handshake.PrepareToFinish();
}
}
diff --git a/crypto/src/tls/ExtensionType.cs b/crypto/src/tls/ExtensionType.cs
index 87f6a7574..a1f1fa7e8 100644
--- a/crypto/src/tls/ExtensionType.cs
+++ b/crypto/src/tls/ExtensionType.cs
@@ -107,6 +107,11 @@ namespace Org.BouncyCastle.Tls
public const int cached_info = 25;
/*
+ * RFC 8879
+ */
+ public const int compress_certificate = 27;
+
+ /*
* RFC 8449
*/
public const int record_size_limit = 28;
@@ -191,6 +196,8 @@ namespace Org.BouncyCastle.Tls
return "token_binding";
case cached_info:
return "cached_info";
+ case compress_certificate:
+ return "compress_certificate";
case record_size_limit:
return "record_size_limit";
case session_ticket:
@@ -257,6 +264,7 @@ namespace Org.BouncyCastle.Tls
case extended_master_secret:
case token_binding:
case cached_info:
+ case compress_certificate:
case record_size_limit:
case session_ticket:
case pre_shared_key:
diff --git a/crypto/src/tls/HandshakeType.cs b/crypto/src/tls/HandshakeType.cs
index 563cd1150..ad2c29c07 100644
--- a/crypto/src/tls/HandshakeType.cs
+++ b/crypto/src/tls/HandshakeType.cs
@@ -44,6 +44,11 @@ namespace Org.BouncyCastle.Tls
public const short key_update = 24;
public const short message_hash = 254;
+ /*
+ * RFC 8879
+ */
+ public const short compressed_certificate = 25;
+
public static string GetName(short handshakeType)
{
switch (handshakeType)
@@ -88,6 +93,8 @@ namespace Org.BouncyCastle.Tls
return "key_update";
case message_hash:
return "message_hash";
+ case compressed_certificate:
+ return "compressed_certificate";
default:
return "UNKNOWN";
}
@@ -122,6 +129,7 @@ namespace Org.BouncyCastle.Tls
case encrypted_extensions:
case key_update:
case message_hash:
+ case compressed_certificate:
return true;
default:
return false;
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index c132b257b..cb59289ae 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -315,6 +315,7 @@ namespace Org.BouncyCastle.Tls
case HandshakeType.certificate_url:
case HandshakeType.client_hello:
case HandshakeType.client_key_exchange:
+ case HandshakeType.compressed_certificate:
case HandshakeType.end_of_early_data:
case HandshakeType.hello_request:
case HandshakeType.hello_verify_request:
@@ -608,7 +609,7 @@ namespace Org.BouncyCastle.Tls
this.m_connectionState = CS_CLIENT_CERTIFICATE_VERIFY;
}
- this.m_handshakeHash = m_handshakeHash.StopTracking();
+ m_handshakeHash.StopTracking();
SendChangeCipherSpec();
SendFinishedMessage();
@@ -743,6 +744,7 @@ namespace Org.BouncyCastle.Tls
case HandshakeType.certificate_verify:
case HandshakeType.client_hello:
case HandshakeType.client_key_exchange:
+ case HandshakeType.compressed_certificate:
case HandshakeType.encrypted_extensions:
case HandshakeType.end_of_early_data:
case HandshakeType.hello_verify_request:
diff --git a/crypto/src/tls/TlsExtensionsUtilities.cs b/crypto/src/tls/TlsExtensionsUtilities.cs
index 5a13d8d2e..e1db93016 100644
--- a/crypto/src/tls/TlsExtensionsUtilities.cs
+++ b/crypto/src/tls/TlsExtensionsUtilities.cs
@@ -53,6 +53,12 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
+ public static void AddCompressCertificateExtension(IDictionary extensions, int[] algorithms)
+ {
+ extensions[ExtensionType.compress_certificate] = CreateCompressCertificateExtension(algorithms);
+ }
+
+ /// <exception cref="IOException"/>
public static void AddCookieExtension(IDictionary extensions, byte[] cookie)
{
extensions[ExtensionType.cookie] = CreateCookieExtension(cookie);
@@ -280,6 +286,13 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
+ public static int[] GetCompressCertificateExtension(IDictionary extensions)
+ {
+ byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.compress_certificate);
+ return extensionData == null ? null : ReadCompressCertificateExtension(extensionData);
+ }
+
+ /// <exception cref="IOException"/>
public static byte[] GetCookieExtension(IDictionary extensions)
{
byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.cookie);
@@ -580,6 +593,15 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
+ public static byte[] CreateCompressCertificateExtension(int[] algorithms)
+ {
+ if (TlsUtilities.IsNullOrEmpty(algorithms) || algorithms.Length > 127)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
+ return TlsUtilities.EncodeUint16ArrayWithUint8Length(algorithms);
+ }
+
+ /// <exception cref="IOException"/>
public static byte[] CreateCookieExtension(byte[] cookie)
{
if (TlsUtilities.IsNullOrEmpty(cookie) || cookie.Length >= (1 << 16))
@@ -995,6 +1017,16 @@ namespace Org.BouncyCastle.Tls
}
/// <exception cref="IOException"/>
+ public static int[] ReadCompressCertificateExtension(byte[] extensionData)
+ {
+ int[] algorithms = TlsUtilities.DecodeUint16ArrayWithUint8Length(extensionData);
+ if (algorithms.Length < 1)
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+
+ return algorithms;
+ }
+
+ /// <exception cref="IOException"/>
public static byte[] ReadCookieExtension(byte[] extensionData)
{
return TlsUtilities.DecodeOpaque16(extensionData, 1);
diff --git a/crypto/src/tls/TlsHandshakeHash.cs b/crypto/src/tls/TlsHandshakeHash.cs
index aa33c680d..88aeaaa32 100644
--- a/crypto/src/tls/TlsHandshakeHash.cs
+++ b/crypto/src/tls/TlsHandshakeHash.cs
@@ -20,7 +20,7 @@ namespace Org.BouncyCastle.Tls
void SealHashAlgorithms();
- TlsHandshakeHash StopTracking();
+ void StopTracking();
TlsHash ForkPrfHash();
diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs
index 40218a2fb..0ab8a7a98 100644
--- a/crypto/src/tls/TlsServerProtocol.cs
+++ b/crypto/src/tls/TlsServerProtocol.cs
@@ -834,6 +834,7 @@ namespace Org.BouncyCastle.Tls
case HandshakeType.certificate_status:
case HandshakeType.certificate_url:
case HandshakeType.client_key_exchange:
+ case HandshakeType.compressed_certificate:
case HandshakeType.encrypted_extensions:
case HandshakeType.end_of_early_data:
case HandshakeType.hello_request:
@@ -1201,6 +1202,7 @@ namespace Org.BouncyCastle.Tls
case HandshakeType.certificate_request:
case HandshakeType.certificate_status:
case HandshakeType.certificate_url:
+ case HandshakeType.compressed_certificate:
case HandshakeType.encrypted_extensions:
case HandshakeType.end_of_early_data:
case HandshakeType.hello_request:
@@ -1320,7 +1322,7 @@ namespace Org.BouncyCastle.Tls
TlsUtilities.VerifyCertificateVerifyClient(m_tlsServerContext, m_certificateRequest, certificateVerify,
m_handshakeHash);
- this.m_handshakeHash = m_handshakeHash.StopTracking();
+ m_handshakeHash.StopTracking();
}
/// <exception cref="IOException"/>
@@ -1355,7 +1357,7 @@ namespace Org.BouncyCastle.Tls
if (!ExpectCertificateVerifyMessage())
{
- this.m_handshakeHash = m_handshakeHash.StopTracking();
+ m_handshakeHash.StopTracking();
}
}
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index 8733fd68f..1d9759bca 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -486,6 +486,14 @@ namespace Org.BouncyCastle.Tls
}
}
+ public static void WriteUint16ArrayWithUint8Length(int[] u16s, byte[] buf, int offset)
+ {
+ int length = 2 * u16s.Length;
+ CheckUint8(length);
+ WriteUint8(length, buf, offset);
+ WriteUint16Array(u16s, buf, offset + 1);
+ }
+
public static void WriteUint16ArrayWithUint16Length(int[] u16s, Stream output)
{
int length = 2 * u16s.Length;
@@ -577,6 +585,25 @@ namespace Org.BouncyCastle.Tls
return ReadUint16(buf, 0);
}
+ public static int[] DecodeUint16ArrayWithUint8Length(byte[] buf)
+ {
+ if (buf == null)
+ throw new ArgumentNullException("buf");
+
+ int length = ReadUint8(buf, 0);
+ if (buf.Length != (length + 1) || (length & 1) != 0)
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+
+ int count = length / 2, pos = 1;
+ int[] u16s = new int[count];
+ for (int i = 0; i < count; ++i)
+ {
+ u16s[i] = ReadUint16(buf, pos);
+ pos += 2;
+ }
+ return u16s;
+ }
+
public static long DecodeUint32(byte[] buf)
{
if (buf == null)
@@ -636,6 +663,14 @@ namespace Org.BouncyCastle.Tls
return encoding;
}
+ public static byte[] EncodeUint16ArrayWithUint8Length(int[] u16s)
+ {
+ int length = 2 * u16s.Length;
+ byte[] result = new byte[1 + length];
+ WriteUint16ArrayWithUint8Length(u16s, result, 0);
+ return result;
+ }
+
public static byte[] EncodeUint16ArrayWithUint16Length(int[] u16s)
{
int length = 2 * u16s.Length;
@@ -2083,7 +2118,7 @@ namespace Org.BouncyCastle.Tls
output.Write(extraSignatureInput, 0, extraSignatureInput.Length);
}
- buf.CopyTo(output);
+ buf.CopyInputTo(output);
Platform.Dispose(output);
}
@@ -5348,6 +5383,7 @@ namespace Org.BouncyCastle.Tls
}
}
case ExtensionType.signature_algorithms:
+ case ExtensionType.compress_certificate:
case ExtensionType.certificate_authorities:
case ExtensionType.signature_algorithms_cert:
{
diff --git a/crypto/src/tls/crypto/TlsCryptoUtilities.cs b/crypto/src/tls/crypto/TlsCryptoUtilities.cs
index a22049e5d..757eda1be 100644
--- a/crypto/src/tls/crypto/TlsCryptoUtilities.cs
+++ b/crypto/src/tls/crypto/TlsCryptoUtilities.cs
@@ -68,6 +68,24 @@ namespace Org.BouncyCastle.Tls.Crypto
}
}
+ public static int GetHashInternalSize(int cryptoHashAlgorithm)
+ {
+ switch (cryptoHashAlgorithm)
+ {
+ case CryptoHashAlgorithm.md5:
+ case CryptoHashAlgorithm.sha1:
+ case CryptoHashAlgorithm.sha224:
+ case CryptoHashAlgorithm.sha256:
+ case CryptoHashAlgorithm.sm3:
+ return 64;
+ case CryptoHashAlgorithm.sha384:
+ case CryptoHashAlgorithm.sha512:
+ return 128;
+ default:
+ throw new ArgumentException();
+ }
+ }
+
public static int GetHashOutputSize(int cryptoHashAlgorithm)
{
switch (cryptoHashAlgorithm)
diff --git a/crypto/src/tls/crypto/impl/bc/BcDefaultTlsCredentialedAgreement.cs b/crypto/src/tls/crypto/impl/bc/BcDefaultTlsCredentialedAgreement.cs
index 15944cd89..863b96634 100644
--- a/crypto/src/tls/crypto/impl/bc/BcDefaultTlsCredentialedAgreement.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcDefaultTlsCredentialedAgreement.cs
@@ -100,7 +100,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
{
BcTlsCertificate bcCert = BcTlsCertificate.Convert(m_crypto, peerCertificate);
ECPublicKeyParameters peerPublicKey = bcCert.GetPubKeyEC();
- return BcTlsECDomain.CalculateBasicAgreement(m_crypto, m_privateKey, peerPublicKey);
+ return BcTlsECDomain.CalculateECDHAgreement(m_crypto, m_privateKey, peerPublicKey);
}
public Certificate Certificate
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs b/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs
index 69e353bae..e763422ed 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs
@@ -139,9 +139,10 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public override TlsNonceGenerator CreateNonceGenerator(byte[] additionalSeedMaterial)
{
- IDigest digest = CreateDigest(CryptoHashAlgorithm.sha256);
+ int cryptoHashAlgorithm = CryptoHashAlgorithm.sha256;
+ IDigest digest = CreateDigest(cryptoHashAlgorithm);
- byte[] seed = new byte[digest.GetDigestSize()];
+ byte[] seed = new byte[TlsCryptoUtilities.GetHashOutputSize(cryptoHashAlgorithm)];
SecureRandom.NextBytes(seed);
DigestRandomGenerator randomGenerator = new DigestRandomGenerator(digest);
@@ -187,7 +188,20 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public override bool HasCryptoHashAlgorithm(int cryptoHashAlgorithm)
{
- return true;
+ switch (cryptoHashAlgorithm)
+ {
+ case CryptoHashAlgorithm.md5:
+ case CryptoHashAlgorithm.sha1:
+ case CryptoHashAlgorithm.sha224:
+ case CryptoHashAlgorithm.sha256:
+ case CryptoHashAlgorithm.sha384:
+ case CryptoHashAlgorithm.sha512:
+ case CryptoHashAlgorithm.sm3:
+ return true;
+
+ default:
+ return false;
+ }
}
public override bool HasCryptoSignatureAlgorithm(int cryptoSignatureAlgorithm)
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsDH.cs b/crypto/src/tls/crypto/impl/bc/BcTlsDH.cs
index 8af94f7c6..63fa00ce4 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsDH.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsDH.cs
@@ -1,5 +1,4 @@
using System;
-using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
@@ -20,7 +19,6 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
this.m_domain = domain;
}
- /// <exception cref="IOException"/>
public virtual byte[] GenerateEphemeral()
{
this.m_localKeyPair = m_domain.GenerateKeyPair();
@@ -28,13 +26,11 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
return m_domain.EncodePublicKey((DHPublicKeyParameters)m_localKeyPair.Public);
}
- /// <exception cref="IOException"/>
public virtual void ReceivePeerValue(byte[] peerValue)
{
this.m_peerPublicKey = m_domain.DecodePublicKey(peerValue);
}
- /// <exception cref="IOException"/>
public virtual TlsSecret CalculateSecret()
{
return m_domain.CalculateDHAgreement((DHPrivateKeyParameters)m_localKeyPair.Private, m_peerPublicKey);
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs b/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs
index 90b8ce94f..faf6b4576 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
return crypto.AdoptLocalSecret(secret);
}
- public static DHParameters GetParameters(TlsDHConfig dhConfig)
+ public static DHParameters GetDomainParameters(TlsDHConfig dhConfig)
{
DHGroup dhGroup = TlsDHUtilities.GetDHGroup(dhConfig);
if (dhGroup == null)
@@ -46,21 +46,21 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
return new DHParameters(dhGroup.P, dhGroup.G, dhGroup.Q, dhGroup.L);
}
- protected readonly BcTlsCrypto crypto;
- protected readonly TlsDHConfig dhConfig;
- protected readonly DHParameters dhParameters;
+ protected readonly BcTlsCrypto m_crypto;
+ protected readonly TlsDHConfig m_config;
+ protected readonly DHParameters m_domainParameters;
public BcTlsDHDomain(BcTlsCrypto crypto, TlsDHConfig dhConfig)
{
- this.crypto = crypto;
- this.dhConfig = dhConfig;
- this.dhParameters = GetParameters(dhConfig);
+ this.m_crypto = crypto;
+ this.m_config = dhConfig;
+ this.m_domainParameters = GetDomainParameters(dhConfig);
}
public virtual BcTlsSecret CalculateDHAgreement(DHPrivateKeyParameters privateKey,
DHPublicKeyParameters publicKey)
{
- return CalculateDHAgreement(crypto, privateKey, publicKey, dhConfig.IsPadded);
+ return CalculateDHAgreement(m_crypto, privateKey, publicKey, m_config.IsPadded);
}
public virtual TlsAgreement CreateDH()
@@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
/// <exception cref="IOException"/>
public virtual BigInteger DecodeParameter(byte[] encoding)
{
- if (dhConfig.IsPadded && GetValueLength(dhParameters) != encoding.Length)
+ if (m_config.IsPadded && GetValueLength(m_domainParameters) != encoding.Length)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
return new BigInteger(1, encoding);
@@ -89,7 +89,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
{
BigInteger y = DecodeParameter(encoding);
- return new DHPublicKeyParameters(y, dhParameters);
+ return new DHPublicKeyParameters(y, m_domainParameters);
}
catch (Exception e)
{
@@ -97,22 +97,20 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
}
}
- /// <exception cref="IOException"/>
public virtual byte[] EncodeParameter(BigInteger x)
{
- return EncodeValue(dhParameters, dhConfig.IsPadded, x);
+ return EncodeValue(m_domainParameters, m_config.IsPadded, x);
}
- /// <exception cref="IOException"/>
public virtual byte[] EncodePublicKey(DHPublicKeyParameters publicKey)
{
- return EncodeValue(dhParameters, true, publicKey.Y);
+ return EncodeValue(m_domainParameters, true, publicKey.Y);
}
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
DHBasicKeyPairGenerator keyPairGenerator = new DHBasicKeyPairGenerator();
- keyPairGenerator.Init(new DHKeyGenerationParameters(crypto.SecureRandom, dhParameters));
+ keyPairGenerator.Init(new DHKeyGenerationParameters(m_crypto.SecureRandom, m_domainParameters));
return keyPairGenerator.GenerateKeyPair();
}
}
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsECDomain.cs b/crypto/src/tls/crypto/impl/bc/BcTlsECDomain.cs
index 61d11fb42..ab3481924 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsECDomain.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsECDomain.cs
@@ -4,7 +4,6 @@ using System.IO;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Agreement;
-using Org.BouncyCastle.Crypto.EC;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
@@ -19,7 +18,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public class BcTlsECDomain
: TlsECDomain
{
- public static BcTlsSecret CalculateBasicAgreement(BcTlsCrypto crypto, ECPrivateKeyParameters privateKey,
+ public static BcTlsSecret CalculateECDHAgreement(BcTlsCrypto crypto, ECPrivateKeyParameters privateKey,
ECPublicKeyParameters publicKey)
{
ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
@@ -57,20 +56,20 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
}
protected readonly BcTlsCrypto m_crypto;
- protected readonly TlsECConfig m_ecConfig;
- protected readonly ECDomainParameters m_ecDomainParameters;
+ protected readonly TlsECConfig m_config;
+ protected readonly ECDomainParameters m_domainParameters;
public BcTlsECDomain(BcTlsCrypto crypto, TlsECConfig ecConfig)
{
this.m_crypto = crypto;
- this.m_ecConfig = ecConfig;
- this.m_ecDomainParameters = GetDomainParameters(ecConfig);
+ this.m_config = ecConfig;
+ this.m_domainParameters = GetDomainParameters(ecConfig);
}
public virtual BcTlsSecret CalculateECDHAgreement(ECPrivateKeyParameters privateKey,
ECPublicKeyParameters publicKey)
{
- return CalculateBasicAgreement(m_crypto, privateKey, publicKey);
+ return CalculateECDHAgreement(m_crypto, privateKey, publicKey);
}
public virtual TlsAgreement CreateECDH()
@@ -80,16 +79,17 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public virtual ECPoint DecodePoint(byte[] encoding)
{
- return m_ecDomainParameters.Curve.DecodePoint(encoding);
+ return m_domainParameters.Curve.DecodePoint(encoding);
}
+ /// <exception cref="IOException"/>
public virtual ECPublicKeyParameters DecodePublicKey(byte[] encoding)
{
try
{
ECPoint point = DecodePoint(encoding);
- return new ECPublicKeyParameters(point, m_ecDomainParameters);
+ return new ECPublicKeyParameters(point, m_domainParameters);
}
catch (IOException e)
{
@@ -114,7 +114,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
- keyPairGenerator.Init(new ECKeyGenerationParameters(m_ecDomainParameters, m_crypto.SecureRandom));
+ keyPairGenerator.Init(new ECKeyGenerationParameters(m_domainParameters, m_crypto.SecureRandom));
return keyPairGenerator.GenerateKeyPair();
}
}
|