diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2017-03-24 17:58:58 +1030 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2017-03-24 17:58:58 +1030 |
commit | 29d257cfe975d62169584ad1b8896157d415c5d7 (patch) | |
tree | 472b1b39cb48675ebbe6bda3db8c54c7550e3a1d | |
parent | Reduce TLS memory usage (diff) | |
download | BouncyCastle.NET-ed25519-29d257cfe975d62169584ad1b8896157d415c5d7.tar.xz |
Avoid copies when handshake records not fragmented
-rw-r--r-- | crypto/src/crypto/tls/ByteQueue.cs | 15 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsProtocol.cs | 128 |
2 files changed, 81 insertions, 62 deletions
diff --git a/crypto/src/crypto/tls/ByteQueue.cs b/crypto/src/crypto/tls/ByteQueue.cs index f9d4ee606..b4df6850e 100644 --- a/crypto/src/crypto/tls/ByteQueue.cs +++ b/crypto/src/crypto/tls/ByteQueue.cs @@ -48,6 +48,8 @@ namespace Org.BouncyCastle.Crypto.Tls */ private int available = 0; + private bool readOnlyBuf = false; + public ByteQueue() : this(DefaultCapacity) { @@ -55,7 +57,15 @@ namespace Org.BouncyCastle.Crypto.Tls public ByteQueue(int capacity) { - this.databuf = new byte[capacity]; + this.databuf = capacity == 0 ? TlsUtilities.EmptyBytes : new byte[capacity]; + } + + public ByteQueue(byte[] buf, int off, int len) + { + this.databuf = buf; + this.skipped = off; + this.available = len; + this.readOnlyBuf = true; } /// <summary>Add some data to our buffer.</summary> @@ -67,6 +77,9 @@ namespace Org.BouncyCastle.Crypto.Tls int offset, int len) { + if (readOnlyBuf) + throw new InvalidOperationException("Cannot add data to read-only buffer"); + if ((skipped + available + len) > databuf.Length) { int desiredSize = ByteQueue.NextTwoPow(available + len); diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 69361bf6f..490580fad 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Crypto.Tls */ private ByteQueue mApplicationDataQueue = new ByteQueue(0); private ByteQueue mAlertQueue = new ByteQueue(2); - private ByteQueue mHandshakeQueue = new ByteQueue(); + private ByteQueue mHandshakeQueue = new ByteQueue(0); // private ByteQueue mHeartbeatQueue = new ByteQueue(); /* @@ -233,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Tls } } - protected internal void ProcessRecord(byte protocol, byte[] buf, int offset, int len) + protected internal void ProcessRecord(byte protocol, byte[] buf, int off, int len) { /* * Have a look at the protocol type, and add it to the correct queue. @@ -242,8 +242,8 @@ namespace Org.BouncyCastle.Crypto.Tls { case ContentType.alert: { - mAlertQueue.AddData(buf, offset, len); - ProcessAlert(); + mAlertQueue.AddData(buf, off, len); + ProcessAlertQueue(); break; } case ContentType.application_data: @@ -251,19 +251,32 @@ namespace Org.BouncyCastle.Crypto.Tls if (!mAppDataReady) throw new TlsFatalAlert(AlertDescription.unexpected_message); - mApplicationDataQueue.AddData(buf, offset, len); - ProcessApplicationData(); + mApplicationDataQueue.AddData(buf, off, len); + ProcessApplicationDataQueue(); break; } case ContentType.change_cipher_spec: { - ProcessChangeCipherSpec(buf, offset, len); + ProcessChangeCipherSpec(buf, off, len); break; } case ContentType.handshake: { - mHandshakeQueue.AddData(buf, offset, len); - ProcessHandshake(); + if (mHandshakeQueue.Available > 0) + { + mHandshakeQueue.AddData(buf, off, len); + ProcessHandshakeQueue(mHandshakeQueue); + } + else + { + ByteQueue tmpQueue = new ByteQueue(buf, off, len); + ProcessHandshakeQueue(tmpQueue); + int remaining = tmpQueue.Available; + if (remaining > 0) + { + mHandshakeQueue.AddData(buf, off + len - remaining, remaining); + } + } break; } //case ContentType.heartbeat: @@ -282,71 +295,64 @@ namespace Org.BouncyCastle.Crypto.Tls } } - private void ProcessHandshake() + private void ProcessHandshakeQueue(ByteQueue queue) { - bool read; - do + while (queue.Available >= 4) { - read = false; /* * We need the first 4 bytes, they contain type and length of the message. */ - if (mHandshakeQueue.Available >= 4) - { - byte[] beginning = new byte[4]; - mHandshakeQueue.Read(beginning, 0, 4, 0); - byte type = TlsUtilities.ReadUint8(beginning, 0); - int length = TlsUtilities.ReadUint24(beginning, 1); - int totalLength = 4 + length; + byte[] beginning = new byte[4]; + queue.Read(beginning, 0, 4, 0); + byte type = TlsUtilities.ReadUint8(beginning, 0); + int length = TlsUtilities.ReadUint24(beginning, 1); + int totalLength = 4 + length; - /* - * Check if we have enough bytes in the buffer to read the full message. - */ - if (mHandshakeQueue.Available >= totalLength) + /* + * Check if we have enough bytes in the buffer to read the full message. + */ + if (queue.Available < totalLength) + break; + + CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished); + + /* + * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages + * starting at client hello up to, but not including, this finished message. + * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes. + */ + switch (type) + { + case HandshakeType.hello_request: + break; + case HandshakeType.finished: + default: + { + TlsContext ctx = Context; + if (type == HandshakeType.finished + && this.mExpectedVerifyData == null + && ctx.SecurityParameters.MasterSecret != null) { - CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished); + this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); + } - /* - * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages - * starting at client hello up to, but not including, this finished message. - * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes. - */ - switch (type) - { - case HandshakeType.hello_request: - break; - case HandshakeType.finished: - default: - { - TlsContext ctx = Context; - if (type == HandshakeType.finished - && this.mExpectedVerifyData == null - && ctx.SecurityParameters.MasterSecret != null) - { - this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); - } - - mHandshakeQueue.CopyTo(mRecordStream.HandshakeHashUpdater, totalLength); - break; - } - } + queue.CopyTo(mRecordStream.HandshakeHashUpdater, totalLength); + break; + } + } - mHandshakeQueue.RemoveData(4); + queue.RemoveData(4); - MemoryStream buf = mHandshakeQueue.ReadFrom(length); + MemoryStream buf = queue.ReadFrom(length); - /* - * Now, parse the message. - */ - HandleHandshakeMessage(type, buf); - read = true; - } - } + /* + * Now, parse the message. + */ + HandleHandshakeMessage(type, buf); } - while (read); } - private void ProcessApplicationData() + private void ProcessApplicationDataQueue() { /* * There is nothing we need to do here. @@ -355,7 +361,7 @@ namespace Org.BouncyCastle.Crypto.Tls */ } - private void ProcessAlert() + private void ProcessAlertQueue() { while (mAlertQueue.Available >= 2) { |