private DecryptData ( byte buffer, int &offset, int &count ) : SecurityStatusPal | ||
buffer | byte | |
offset | int | |
count | int | |
return | SecurityStatusPal |
// // readBytes == SSL Data Payload size on input or 0 on EOF // private int ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (readBytes == 0) { // EOF throw new IOException(SR.net_io_eof); } // Set readBytes to total number of received bytes. readBytes += SecureChannel.ReadHeaderSize; // Decrypt into internal buffer, change "readBytes" to count now _Decrypted Bytes_. int data_offset = 0; Interop.SecurityStatus errorCode = _SslState.DecryptData(InternalBuffer, ref data_offset, ref readBytes); if (errorCode != Interop.SecurityStatus.OK) { byte[] extraBuffer = null; if (readBytes != 0) { extraBuffer = new byte[readBytes]; Buffer.BlockCopy(InternalBuffer, data_offset, extraBuffer, 0, readBytes); } // Reset internal buffer count. SkipBytes(InternalBufferCount); return(ProcessReadErrorCode(errorCode, buffer, offset, count, asyncRequest, extraBuffer)); } if (readBytes == 0 && count != 0) { // Read again since remote side has sent encrypted 0 bytes. SkipBytes(InternalBufferCount); return(-1); } // Decrypted data start from "data_offset" offset, the total count can be shrunk after decryption. EnsureInternalBufferSize(0, data_offset + readBytes); SkipBytes(data_offset); if (readBytes > count) { readBytes = count; } Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, readBytes); // This will adjust both the remaining internal buffer count and the offset. SkipBytes(readBytes); _SslState.FinishRead(null); if (asyncRequest != null) { asyncRequest.CompleteUser((object)readBytes); } return(readBytes); }
// // readBytes == SSL Data Payload size on input or 0 on EOF. // private int ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (readBytes == 0) { // EOF throw new IOException(SR.net_io_eof); } // At this point, readBytes contains the size of the header plus body. // Set _decrytpedBytesOffset/Count to the current frame we have (including header) // DecryptData will decrypt in-place and modify these to point to the actual decrypted data, which may be smaller. _decryptedBytesOffset = _internalOffset; _decryptedBytesCount = readBytes; SecurityStatusPal status = _sslState.DecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount); // Treat the bytes we just decrypted as consumed // Note, we won't do another buffer read until the decrypted bytes are processed ConsumeBufferedBytes(readBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { byte[] extraBuffer = null; if (_decryptedBytesCount != 0) { extraBuffer = new byte[_decryptedBytesCount]; Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount); _decryptedBytesCount = 0; } return(ProcessReadErrorCode(status, asyncRequest, extraBuffer)); } if (_decryptedBytesCount == 0) { // Read again since remote side has sent encrypted 0 bytes. return(-1); } int copyBytes = CopyDecryptedData(buffer, offset, count); _sslState.FinishRead(null); asyncRequest?.CompleteUser(copyBytes); return(copyBytes); }
private async ValueTask <int> ReadAsyncInternal <TReadAdapter>(TReadAdapter adapter, Memory <byte> buffer) where TReadAdapter : ISslReadAdapter { if (Interlocked.Exchange(ref _nestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(ReadAsync), "read")); } while (true) { int copyBytes; if (_decryptedBytesCount != 0) { copyBytes = CopyDecryptedData(buffer); _sslState.FinishRead(null); _nestedRead = 0; return(copyBytes); } copyBytes = await adapter.LockAsync(buffer).ConfigureAwait(false); try { if (copyBytes > 0) { return(copyBytes); } ResetReadBuffer(); int readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); if (readBytes == 0) { return(0); } int payloadBytes = _sslState.GetRemainingFrameSize(_internalBuffer, _internalOffset, readBytes); if (payloadBytes < 0) { throw new IOException(SR.net_frame_read_size); } readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize + payloadBytes).ConfigureAwait(false); if (readBytes < 0) { throw new IOException(SR.net_frame_read_size); } // At this point, readBytes contains the size of the header plus body. // Set _decrytpedBytesOffset/Count to the current frame we have (including header) // DecryptData will decrypt in-place and modify these to point to the actual decrypted data, which may be smaller. _decryptedBytesOffset = _internalOffset; _decryptedBytesCount = readBytes; SecurityStatusPal status = _sslState.DecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount); // Treat the bytes we just decrypted as consumed // Note, we won't do another buffer read until the decrypted bytes are processed ConsumeBufferedBytes(readBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { byte[] extraBuffer = null; if (_decryptedBytesCount != 0) { extraBuffer = new byte[_decryptedBytesCount]; Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount); _decryptedBytesCount = 0; } ProtocolToken message = new ProtocolToken(null, status); if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"***Processing an error Status = {message.Status}"); } if (message.Renegotiate) { if (!_sslState._sslAuthenticationOptions.AllowRenegotiation) { throw new IOException(SR.net_ssl_io_renego); } _sslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _sslState.FinishRead(null); return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); } } catch (Exception e) { _sslState.FinishRead(null); if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { _nestedRead = 0; } } }