@@ -200,6 +200,7 @@ public sealed class Session : ISession
200200 private Socket _socket ;
201201
202202 private ArrayBuffer _receiveBuffer = new ( 4 * 1024 ) ;
203+ private byte [ ] _plaintextReceiveBuffer = new byte [ 4 * 1024 ] ;
203204
204205 /// <summary>
205206 /// Gets the session semaphore that controls session channels.
@@ -1319,19 +1320,24 @@ private Message ReceiveMessage(Socket socket)
13191320
13201321 // Construct buffer for holding the payload and the inbound packet sequence as we need both in order
13211322 // to generate the hash.
1322- var data = new byte [ 4 + totalPacketLength - serverMacLength ] ;
1323+ var plaintextLength = 4 + totalPacketLength - serverMacLength ;
13231324
1324- BinaryPrimitives . WriteUInt32BigEndian ( data , _inboundPacketSequence ) ;
1325+ if ( _plaintextReceiveBuffer . Length < plaintextLength )
1326+ {
1327+ Array . Resize ( ref _plaintextReceiveBuffer , Math . Max ( plaintextLength , 2 * _plaintextReceiveBuffer . Length ) ) ;
1328+ }
1329+
1330+ BinaryPrimitives . WriteUInt32BigEndian ( _plaintextReceiveBuffer , _inboundPacketSequence ) ;
13251331
1326- plainFirstBlock . AsSpan ( ) . CopyTo ( data . AsSpan ( 4 ) ) ;
1332+ plainFirstBlock . AsSpan ( ) . CopyTo ( _plaintextReceiveBuffer . AsSpan ( 4 ) ) ;
13271333
13281334 if ( _serverMac != null && _serverEtm )
13291335 {
13301336 // ETM mac = MAC(key, sequence_number || packet_length || encrypted_packet)
13311337
13321338 // sequence_number
13331339 _ = _serverMac . TransformBlock (
1334- inputBuffer : data ,
1340+ inputBuffer : _plaintextReceiveBuffer ,
13351341 inputOffset : 0 ,
13361342 inputCount : 4 ,
13371343 outputBuffer : null ,
@@ -1363,21 +1369,23 @@ private Message ReceiveMessage(Socket socket)
13631369 input : _receiveBuffer . DangerousGetUnderlyingBuffer ( ) ,
13641370 offset : _receiveBuffer . ActiveStartOffset + blockSize ,
13651371 length : numberOfBytesToDecrypt ,
1366- output : data ,
1372+ output : _plaintextReceiveBuffer ,
13671373 outputOffset : 4 + blockSize ) ;
13681374
13691375 Debug . Assert ( numberOfBytesDecrypted == numberOfBytesToDecrypt ) ;
13701376 }
13711377 else
13721378 {
1373- _receiveBuffer . ActiveReadOnlySpan . Slice ( blockSize , numberOfBytesToDecrypt ) . CopyTo ( data . AsSpan ( 4 + blockSize ) ) ;
1379+ _receiveBuffer . ActiveReadOnlySpan
1380+ . Slice ( blockSize , numberOfBytesToDecrypt )
1381+ . CopyTo ( _plaintextReceiveBuffer . AsSpan ( 4 + blockSize ) ) ;
13741382 }
13751383
13761384 if ( _serverMac != null && ! _serverEtm )
13771385 {
13781386 // non-ETM mac = MAC(key, sequence_number || unencrypted_packet)
13791387
1380- var clientHash = _serverMac . ComputeHash ( data ) ;
1388+ var clientHash = _serverMac . ComputeHash ( _plaintextReceiveBuffer , 0 , plaintextLength ) ;
13811389
13821390 if ( ! CryptoAbstraction . FixedTimeEquals ( clientHash , _receiveBuffer . ActiveSpan . Slice ( totalPacketLength - serverMacLength , serverMacLength ) ) )
13831391 {
@@ -1387,19 +1395,16 @@ private Message ReceiveMessage(Socket socket)
13871395
13881396 _receiveBuffer . Discard ( totalPacketLength ) ;
13891397
1390- var paddingLength = data [ inboundPacketSequenceLength + packetLengthFieldLength ] ;
1391- var messagePayloadLength = packetLength - paddingLength - paddingLengthFieldLength ;
1392- var messagePayloadOffset = inboundPacketSequenceLength + packetLengthFieldLength + paddingLengthFieldLength ;
1398+ var paddingLength = _plaintextReceiveBuffer [ inboundPacketSequenceLength + packetLengthFieldLength ] ;
1399+
1400+ ArraySegment < byte > payload = new (
1401+ _plaintextReceiveBuffer ,
1402+ offset : inboundPacketSequenceLength + packetLengthFieldLength + paddingLengthFieldLength ,
1403+ count : packetLength - paddingLength - paddingLengthFieldLength ) ;
13931404
13941405 if ( _serverDecompression != null )
13951406 {
1396- data = _serverDecompression . Decompress ( data , messagePayloadOffset , messagePayloadLength ) ;
1397-
1398- // Data now only contains the decompressed payload, and as such the offset is reset to zero
1399- messagePayloadOffset = 0 ;
1400-
1401- // The length of the payload is now the complete decompressed content
1402- messagePayloadLength = data . Length ;
1407+ payload = new ( _serverDecompression . Decompress ( payload . Array , payload . Offset , payload . Count ) ) ;
14031408 }
14041409
14051410 _inboundPacketSequence ++ ;
@@ -1411,7 +1416,7 @@ private Message ReceiveMessage(Socket socket)
14111416 throw new SshConnectionException ( "Inbound packet sequence number is about to wrap during initial key exchange." , DisconnectReason . KeyExchangeFailed ) ;
14121417 }
14131418
1414- return LoadMessage ( data , messagePayloadOffset , messagePayloadLength ) ;
1419+ return LoadMessage ( payload . Array , payload . Offset , payload . Count ) ;
14151420 }
14161421
14171422 private void TrySendDisconnect ( DisconnectReason reasonCode , string message )
0 commit comments