diff options
author | David Hook <dgh@cryptoworkshop.com> | 2022-03-23 13:24:15 +1100 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2022-03-23 13:24:15 +1100 |
commit | fbd1138e762589b0b5b754b225660f912aa0d2f2 (patch) | |
tree | 780bba5af2f988ac6e8cd59b88160e9768111372 | |
parent | fixed case of IV to upper github #353 (diff) | |
parent | Refactoring (diff) | |
download | BouncyCastle.NET-ed25519-fbd1138e762589b0b5b754b225660f912aa0d2f2.tar.xz |
Merge remote-tracking branch 'refs/remotes/origin/master'
22 files changed, 335 insertions, 149 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 875c99cfe..3d84af346 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -1602,6 +1602,7 @@ <Compile Include="src\tls\CachedInformationType.cs" /> <Compile Include="src\tls\CertChainType.cs" /> <Compile Include="src\tls\Certificate.cs" /> + <Compile Include="src\tls\CertificateCompressionAlgorithm.cs" /> <Compile Include="src\tls\CertificateEntry.cs" /> <Compile Include="src\tls\CertificateRequest.cs" /> <Compile Include="src\tls\CertificateStatus.cs" /> diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index f7083b062..84d7bf6fc 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -1596,6 +1596,7 @@ <Compile Include="src\tls\CachedInformationType.cs" /> <Compile Include="src\tls\CertChainType.cs" /> <Compile Include="src\tls\Certificate.cs" /> + <Compile Include="src\tls\CertificateCompressionAlgorithm.cs" /> <Compile Include="src\tls\CertificateEntry.cs" /> <Compile Include="src\tls\CertificateRequest.cs" /> <Compile Include="src\tls\CertificateStatus.cs" /> diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 4490f0f07..d76444e71 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -1597,6 +1597,7 @@ <Compile Include="src\tls\CachedInformationType.cs" /> <Compile Include="src\tls\CertChainType.cs" /> <Compile Include="src\tls\Certificate.cs" /> + <Compile Include="src\tls\CertificateCompressionAlgorithm.cs" /> <Compile Include="src\tls\CertificateEntry.cs" /> <Compile Include="src\tls\CertificateRequest.cs" /> <Compile Include="src\tls\CertificateStatus.cs" /> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index d3666bfcf..092331032 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -7869,6 +7869,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\tls\CertificateCompressionAlgorithm.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\tls\CertificateEntry.cs" SubType = "Code" BuildAction = "Compile" 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(); } } |