private BufferOffsetSize[] ConcatenateBuffersOnWin9x(BufferOffsetSize[] buffers) { if (ComNetOS.IsWin9x && (buffers.Length > 0x10)) { int num; BufferOffsetSize[] sizeArray = new BufferOffsetSize[0x10]; for (num = 0; num < 0x10; num++) { sizeArray[num] = buffers[num]; } int size = 0; for (num = 15; num < buffers.Length; num++) { size += buffers[num].Size; } if (size > 0) { sizeArray[15] = new BufferOffsetSize(new byte[size], 0, size, false); size = 0; for (num = 15; num < buffers.Length; num++) { Buffer.BlockCopy(buffers[num].Buffer, buffers[num].Offset, sizeArray[15].Buffer, size, buffers[num].Size); size += buffers[num].Size; } } buffers = sizeArray; } return(buffers); }
internal void MultipleSend (BufferOffsetSize[] buffers, SocketFlags socketFlags) { var segments = new ArraySegment<byte> [buffers.Length]; for (int i = 0; i < buffers.Length; i++) segments [i] = new ArraySegment<byte> (buffers [i].Buffer, buffers [i].Offset, buffers [i].Size); Send (segments, socketFlags); }
/// <devdoc> /// <para> /// Due to Winsock restrictions /// If on Win9x platforms and the number of buffers are more than 16, performs /// concatenation of the buffers, so that we have 16 buffers. /// </para> /// </devdoc> private BufferOffsetSize[] ConcatenateBuffersOnWin9x(BufferOffsetSize[] buffers) { if (ComNetOS.IsWin9x && buffers.Length > 16) { // We met the limitation of winsock on Win9x // Combine buffers after the 15th into one so overall number does not exceed 16 BufferOffsetSize[] newBuffers = new BufferOffsetSize[16]; int i; for (i = 0; i < 16; ++i) { newBuffers[i] = buffers[i]; } int size = 0; for (i = 15; i < buffers.Length; ++i) { size += buffers[i].Size; } if (size > 0) { newBuffers[15] = new BufferOffsetSize(new byte[size], 0, size, false); for (size = 0, i = 15; i < buffers.Length; size += buffers[i].Size, ++i) { System.Buffer.BlockCopy(buffers[i].Buffer, buffers[i].Offset, newBuffers[15].Buffer, size, buffers[i].Size); } } buffers = newBuffers; } return(buffers); }
internal IAsyncResult BeginMultipleSend (BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state) { var segments = new ArraySegment<byte> [buffers.Length]; for (int i = 0; i < buffers.Length; i++) segments [i] = new ArraySegment<byte> (buffers [i].Buffer, buffers [i].Offset, buffers [i].Size); return BeginSend (segments, socketFlags, callback, state); }
public IBufferOffsetSize Decrypt(ContentType contentType, IBufferOffsetSize input) { var output = new BufferOffsetSize(input.Size); var ret = Decrypt(contentType, input, output); output.TruncateTo(ret); return(output); }
// // Constructor: // internal NestedMultipleAsyncResult(Object asyncObject, Object asyncState, AsyncCallback asyncCallback, BufferOffsetSize[] buffers) : base( asyncObject, asyncState, asyncCallback ) { Buffers = buffers; Size = 0; for (int i = 0; i < Buffers.Length; i++) { Size += Buffers[i].Size; } }
public IBufferOffsetSize Encrypt(ContentType contentType, IBufferOffsetSize data) { var output = new BufferOffsetSize(GetEncryptedSize(data.Size)); var ret = Encrypt(contentType, data, output); output.TruncateTo(ret); return(output); }
public MobileAuthenticatedStream(Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings, AppleTlsProvider provider) : base(innerStream, leaveInnerStreamOpen) { Settings = settings; Provider = provider; readBuffer = new BufferOffsetSize (new byte [16384], 0, 0); writeBuffer = new BufferOffsetSize (new byte [16384], 0, 0); }
// // Combined sync/async write method. For sync case asyncRequest==null // private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (_SslState.LastPayload != null) { // // !!! LastPayload Only used in TlsStream for HTTP and it needs re-work for a general case !!! // BufferOffsetSize[] buffers = new BufferOffsetSize[1]; buffers[0] = new BufferOffsetSize(buffer, offset, count, false); if (asyncRequest != null) { ProcessWrite(buffers, new SplitWriteAsyncProtocolRequest(asyncRequest.UserAsyncResult)); } else { ProcessWrite(buffers, null); } return; } ValidateParameters(buffer, offset, count); _SslState.CheckThrow(authSuccessCheck: true, shutdownCheck: true); if (Interlocked.Exchange(ref _NestedWrite, 1) == 1) { throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null? "BeginWrite":"Write"), "write")); } bool failed = false; try { StartWriting(buffer, offset, count, asyncRequest); } catch (Exception e) { _SslState.FinishWrite(); failed = true; if (e is IOException) { throw; } throw new IOException(SR.GetString(SR.net_io_write), e); } finally { if (asyncRequest == null || failed) { _NestedWrite = 0; } } }
public ArraySegment <byte> this[int i] { get { var bufferOffsetSizes = _buffers as BufferOffsetSize[]; if (bufferOffsetSizes != null) { BufferOffsetSize element = bufferOffsetSizes[i]; return(new ArraySegment <byte>(element.Buffer, element.Offset, element.Size)); } return(((IList <ArraySegment <byte> >)_buffers)[i]); } }
private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (this._SslState.LastPayload != null) { BufferOffsetSize[] buffers = new BufferOffsetSize[] { new BufferOffsetSize(buffer, offset, count, false) }; if (asyncRequest != null) { this.ProcessWrite(buffers, new SplitWriteAsyncProtocolRequest(asyncRequest.UserAsyncResult)); } else { this.ProcessWrite(buffers, null); } } else { this.ValidateParameters(buffer, offset, count); if (Interlocked.Exchange(ref this._NestedWrite, 1) == 1) { throw new NotSupportedException(SR.GetString("net_io_invalidnestedcall", new object[] { (asyncRequest != null) ? "BeginWrite" : "Write", "write" })); } bool flag = false; try { this.StartWriting(buffer, offset, count, asyncRequest); } catch (Exception exception) { this._SslState.FinishWrite(); flag = true; if (exception is IOException) { throw; } throw new IOException(SR.GetString("net_io_write"), exception); } finally { if ((asyncRequest == null) || flag) { this._NestedWrite = 0; } } } }
private static IAsyncResult BeginMultipleWrite(IList <ArraySegment <byte> > sendBuffers, AsyncCallback callback, object asyncState) { Contract.Assert(sendBuffers != null, "'sendBuffers' MUST NOT be NULL."); Contract.Assert(asyncState != null, "'asyncState' MUST NOT be NULL."); WebSocketConnection connection = asyncState as WebSocketConnection; Contract.Assert(connection != null, "'connection' MUST NOT be NULL."); BufferOffsetSize[] buffers = new BufferOffsetSize[sendBuffers.Count]; for (int index = 0; index < sendBuffers.Count; index++) { ArraySegment <byte> sendBuffer = sendBuffers[index]; buffers[index] = new BufferOffsetSize(sendBuffer.Array, sendBuffer.Offset, sendBuffer.Count, false); } WebSocketHelpers.ThrowIfConnectionAborted(connection.m_InnerStream, false); return(connection.m_InnerStream.NetworkStream.BeginMultipleWrite(buffers, callback, asyncState)); }
protected override int Encrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { // Calculate message MAC byte[] mac = null; if (IsServer) { mac = ComputeServerRecordMAC(contentType, input); } else { mac = ComputeClientRecordMAC(contentType, input); } #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("RECORD MAC", mac); } #endif int plen; byte padLen; int totalLength = GetEncryptedSize(input.Size, out plen, out padLen); var totalOutput = new BufferOffsetSize(output.Buffer, output.Offset, totalLength); var outputWriter = new TlsBuffer(totalOutput); outputWriter.Position += HeaderSize; outputWriter.Write(input.Buffer, input.Offset, input.Size); outputWriter.Write(mac); for (int i = 0; i <= padLen; i++) { outputWriter.Write(padLen); } // Encrypt the message EncryptRecord(d, totalOutput); return(totalLength); }
protected async Task ExpectBlob(TestContext ctx, ICommonConnection connection, HandshakeInstrumentType type, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); LogDebug(ctx, 2, "ExpectBlob", connection, type); var buffer = new byte [4096]; var blob = Instrumentation.GetTextBuffer(type); var ret = await connection.Stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken); LogDebug(ctx, 2, "ExpectBlob #1", connection, type, ret); if (ctx.Expect(ret, Is.GreaterThan(0), "read success")) { var result = new BufferOffsetSize(buffer, 0, ret); ctx.Expect(result, new IsEqualBlob(blob), "blob"); } LogDebug(ctx, 2, "ExpectBlob done", connection, type); }
public void TestDecryptWithInvalidPadding2(TestContext ctx, [TestHost] IEncryptionTestHost host) { var input = GetBuffer(Data11Result); var modified = new TlsBuffer(input.Size); modified.Write(input.Buffer); // Flip a bit in the last byte, this will affect the padding size. modified.Buffer [modified.Size - 1] ^= 0x01; input = new BufferOffsetSize(modified.Buffer, 0, modified.Size); try { host.Decrypt(input); ctx.AssertFail("#1"); } catch (Exception ex) { ctx.Assert(ex, Is.InstanceOf <TlsException> (), "#2"); var tlsEx = (TlsException)ex; ctx.Assert(tlsEx.Alert.Level, Is.EqualTo(AlertLevel.Fatal), "#3"); ctx.Assert(tlsEx.Alert.Description, Is.EqualTo(AlertDescription.BadRecordMAC), "#4"); } }
public void TestDecryptWithInvalidPadding(TestContext ctx, [TestHost] IEncryptionTestHost host) { var input = GetBuffer(ExtraPaddingResult); var modified = new TlsBuffer(input.Size); modified.Write(input.Buffer); var theOffset = modified.Size - (2 * host.BlockSize) - 5; modified.Buffer [theOffset] ^= 0x01; input = new BufferOffsetSize(modified.Buffer, 0, modified.Size); try { host.Decrypt(input); ctx.AssertFail("#1"); } catch (Exception ex) { ctx.Assert(ex, Is.InstanceOf <TlsException> (), "#2"); var tlsEx = (TlsException)ex; ctx.Assert(tlsEx.Alert.Level, Is.EqualTo(AlertLevel.Fatal), "#3"); ctx.Assert(tlsEx.Alert.Description, Is.EqualTo(AlertDescription.BadRecordMAC), "#4"); } }
internal virtual IAsyncResult BeginMultipleWrite( BufferOffsetSize[] buffers, AsyncCallback callback, Object state) { // // parameter validation // if (buffers == null) { throw new ArgumentNullException("buffers"); } Socket chkStreamSocket = m_StreamSocket; if(chkStreamSocket == null) { throw new IOException(SR.GetString(SR.net_io_writefailure)); } try { // // call BeginMultipleSend on the Socket. // IAsyncResult asyncResult = chkStreamSocket.BeginMultipleSend( buffers, SocketFlags.None, callback, state); return asyncResult; } catch (Exception exception) { // // some sort of error occured on the socket call, // set the SocketException as InnerException and throw // throw new IOException(SR.GetString(SR.net_io_writefailure), exception); } }
IAsyncResult BeginReadOrWrite (ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, AsyncCallback asyncCallback, object asyncState) { LazyAsyncResult lazyResult = new LazyAsyncResult (this, asyncState, asyncCallback); ProcessReadOrWrite (ref nestedRequest, ref internalBuffer, operation, userBuffer, lazyResult); return lazyResult; }
async Task RunMainLoopBlob (TestContext ctx, HandshakeInstrumentType type, CancellationToken cancellationToken) { var expected = Instrumentation.GetTextBuffer (type).GetBuffer (); var buffer = new byte [4096]; int ret = await Server.Stream.ReadAsync (buffer, 0, buffer.Length); ctx.Assert (ret, Is.EqualTo (expected.Length)); buffer = new BufferOffsetSize (buffer, 0, ret).GetBuffer (); ctx.Assert (buffer, Is.EqualTo (expected), "blob"); await Shutdown (ctx, SupportsCleanShutdown, true, cancellationToken); }
byte[] _CreateAlert (Alert alert) { var buffer = new BufferOffsetSize (2); buffer.Buffer [0] = (byte)alert.Level; buffer.Buffer [1] = (byte)alert.Description; return EncodeRecord (ContentType.Alert, buffer); }
} // SetUnmanagedStructures() internal void SetUnmanagedStructures( BufferOffsetSize[] buffers, SocketFlags socketFlags) { // // create the event handle // m_OverlappedEvent = new AutoResetEvent(false); // // fill in the overlapped structure with the event handle. // Marshal.WriteIntPtr( m_UnmanagedBlob, Win32.OverlappedhEventOffset, m_OverlappedEvent.Handle ); // // Fill in Buffer Array structure that will be used for our send/recv Buffer // m_WSABuffers = new WSABuffer[buffers.Length]; m_GCHandles = new GCHandle[buffers.Length]; for (int i = 0; i < buffers.Length; i++) { m_GCHandles[i] = GCHandle.Alloc(buffers[i].Buffer, GCHandleType.Pinned); m_WSABuffers[i].Length = buffers[i].Size; m_WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffers[i].Buffer, buffers[i].Offset); } // // fill in flags if we use it. // m_Flags = socketFlags; }
// // Combined [....]/async write method. For [....] case asyncRequest==null // private void ProcessWrite(BufferOffsetSize[] buffers, SplitWriteAsyncProtocolRequest asyncRequest) { foreach (BufferOffsetSize buffer in buffers) { ValidateParameters(buffer.Buffer, buffer.Offset, buffer.Size); } if (Interlocked.Exchange(ref _NestedWrite, 1) == 1) { throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null? "BeginWrite":"Write"), "write")); } bool failed = false; try { SplitWritesState splitWrite = new SplitWritesState(buffers); if (asyncRequest != null) asyncRequest.SetNextRequest(splitWrite, _ResumeAsyncWriteCallback); StartWriting(splitWrite, asyncRequest); } catch (Exception e) { _SslState.FinishWrite(); failed = true; if (e is IOException) { throw; } throw new IOException(SR.GetString(SR.net_io_write), e); } finally { if (asyncRequest == null || failed) { _NestedWrite = 0; } } }
// // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones. // Returns the same array that is encrypted or a new array of encrypted buffers. // private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List<BufferOffsetSize> arrayList = null; SecurityStatus status = SecurityStatus.OK; foreach(BufferOffsetSize buffer in buffers) { int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); byte[] outBuffer = null; int outSize; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) break; if (chunkBytes != buffer.Size || arrayList != null) { if (arrayList == null) { arrayList = new List<BufferOffsetSize>(buffers.Length * (buffer.Size/chunkBytes+1)); if (lastHandshakePayload != null) arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false)); foreach(BufferOffsetSize oldBuffer in buffers) { if (oldBuffer == buffer) break; arrayList.Add(oldBuffer); } } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); while ((buffer.Size-=chunkBytes) != 0) { buffer.Offset += chunkBytes; chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); outBuffer = null; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) break; arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); } } else { buffer.Buffer = outBuffer; buffer.Offset = 0; buffer.Size = outSize; } if (status != SecurityStatus.OK) break; } if (status != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, status); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (arrayList != null) buffers = arrayList.ToArray(); else if (lastHandshakePayload != null) { BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length+1]; Array.Copy(buffers, 0, result, 1, buffers.Length); result[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = result; } return buffers; }
int ProcessReadOrWrite (ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, LazyAsyncResult lazyResult) { if (userBuffer == null || userBuffer.Buffer == null) throw new ArgumentNullException ("buffer"); if (userBuffer.Offset < 0) throw new ArgumentOutOfRangeException ("offset"); if (userBuffer.Size < 0 || userBuffer.Offset + userBuffer.Size > userBuffer.Buffer.Length) throw new ArgumentOutOfRangeException ("count"); CheckThrow (true); var name = internalBuffer == readBuffer ? "read" : "write"; Debug ("ProcessReadOrWrite: {0} {1}", name, userBuffer); var asyncRequest = new AsyncProtocolRequest (this, lazyResult, userBuffer); return StartOperation (ref nestedRequest, ref internalBuffer, operation, asyncRequest, name); }
private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List <BufferOffsetSize> list = null; SecurityStatus oK = SecurityStatus.OK; foreach (BufferOffsetSize size in buffers) { int num2; int count = Math.Min(size.Size, this._SslState.MaxDataSize); byte[] outBuffer = null; oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } if ((count != size.Size) || (list != null)) { if (list == null) { list = new List <BufferOffsetSize>(buffers.Length * ((size.Size / count) + 1)); if (lastHandshakePayload != null) { list.Add(new BufferOffsetSize(lastHandshakePayload, false)); } foreach (BufferOffsetSize size2 in buffers) { if (size2 == size) { break; } list.Add(size2); } } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); while ((size.Size -= count) != 0) { size.Offset += count; count = Math.Min(size.Size, this._SslState.MaxDataSize); oK = this._SslState.EncryptData(size.Buffer, size.Offset, count, ref outBuffer, out num2); if (oK != SecurityStatus.OK) { break; } list.Add(new BufferOffsetSize(outBuffer, 0, num2, false)); } } else { size.Buffer = outBuffer; size.Offset = 0; size.Size = num2; } if (oK != SecurityStatus.OK) { break; } } if (oK != SecurityStatus.OK) { ProtocolToken token = new ProtocolToken(null, oK); throw new IOException(SR.GetString("net_io_encrypt"), token.GetException()); } if (list != null) { buffers = list.ToArray(); return(buffers); } if (lastHandshakePayload != null) { BufferOffsetSize[] destinationArray = new BufferOffsetSize[buffers.Length + 1]; Array.Copy(buffers, 0, destinationArray, 1, buffers.Length); destinationArray[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = destinationArray; } return(buffers); }
int StartOperation(ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize internalBuffer, AsyncOperation operation, AsyncProtocolRequest asyncRequest, string name) { if (Interlocked.CompareExchange (ref nestedRequest, asyncRequest, null) != null) throw new InvalidOperationException ("Invalid nested call."); bool failed = false; try { internalBuffer.Reset (); asyncRequest.StartOperation (operation); return asyncRequest.UserResult; } catch (Exception e) { failed = true; if (e is IOException) throw; throw new IOException (name + " failed", e); } finally { if (asyncRequest.UserAsyncResult == null || failed) { internalBuffer.Reset (); nestedRequest = null; } } }
int InternalRead (AsyncProtocolRequest asyncRequest, BufferOffsetSize internalBuffer, byte[] buffer, int offset, int size, out bool wantMore) { if (asyncRequest == null) throw new InvalidOperationException (); Debug ("InternalRead: {0} {1} {2}", internalBuffer, offset, size); /* * One of Apple's native functions wants to read 'size' bytes of data. * * First, we check whether we already have enough in the internal buffer. * * If the internal buffer is empty (it will be the first time we're called), we save * the amount of bytes that were requested and return 'SslStatus.WouldBlock' to our * native caller. This native function will then return this code to managed code, * where we read the requested amount of data into the internal buffer, then call the * native function again. */ if (internalBuffer.Size == 0 && !internalBuffer.Complete) { Debug ("InternalRead #1: {0} {1}", internalBuffer.Offset, internalBuffer.TotalBytes); internalBuffer.Offset = internalBuffer.Size = 0; asyncRequest.RequestRead (size); wantMore = true; return 0; } /* * The second time we're called, the native buffer will contain the exact amount of data that the * previous call requested from us, so we should be able to return it all here. However, just in * case that Apple's native function changed its mind, we can also return less. * * In either case, if we have any data buffered, then we return as much of it as possible - if the * native code isn't satisfied, then it will call us again to request more. */ var len = System.Math.Min (internalBuffer.Size, size); Buffer.BlockCopy (internalBuffer.Buffer, internalBuffer.Offset, buffer, offset, len); internalBuffer.Offset += len; internalBuffer.Size -= len; wantMore = !internalBuffer.Complete && len < size; return len; }
protected override int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) { return(-1); } if (input.Size < MinExtraEncryptedBytes) { return(-1); } var plen = DecryptRecord(d, input, output); if (plen <= 0) { return(-1); } var padlen = output.Buffer [output.Offset + plen - 1]; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("DECRYPT: {0} {1} {2}", input.Size, plen, padlen); DebugHelper.WriteBuffer("DECRYPTED", output.Buffer, output.Offset, plen); } #endif /* * VERY IMPORTANT: * * The Compiler and JIT *** MUST NOT *** optimize the following block of code. * * It is essential that the dummy checks and dummy calls be kept in place. * Also do not put any debugging code into that region as it would mess up with * the timing. * */ #region The following block of code *** MUST NOT *** be optimized in any way if (MacSize + padlen + 1 > plen) { // Invalid padding: plaintext is not long enough. // First run a loop as if there were 256 bytes of padding, with a dummy check. int ok = -1; for (int i = 0; i < 256; i++) { if (output.Buffer [i % output.Size] != padlen) { ok--; } } // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC(contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return(ok); } else { int ok = 0; var resultLength = plen - padlen - MacSize - 1; for (int i = 0; i < padlen; i++) { if (output.Buffer [output.Offset + resultLength + MacSize + i] != padlen) { ok--; } } var dummyOk = ok; var dummyLen = 256 - padlen - 1; for (int i = 0; i < dummyLen; i++) { if (output.Buffer [i % output.Size] != padlen) { dummyOk--; } } if (ok < 0) { // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC(contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return(ok); } else { var first = new BufferOffsetSize(output.Buffer, output.Offset, resultLength); var checkMac = ComputeRecordMAC(contentType, first); var L1 = 13 + plen - MacSize; var L2 = 13 + plen - padlen - 1 - MacSize; var additional = ((L1 - 55) / 64) - ((L2 - 55) / 64); if (additional > 0) { var algorithm = HMac.CreateHash(Cipher.HashAlgorithmType); for (int i = 0; i < additional; i++) { algorithm.TransformBlock(input.Buffer, input.Offset, BlockSize, null, 0); } } ok += TlsBuffer.ConstantTimeCompare(checkMac, 0, checkMac.Length, output.Buffer, output.Offset + resultLength, MacSize); if (ok == 0) { ok = resultLength; } return(ok); } } #endregion }
public IBufferOffsetSize Encrypt (ContentType contentType, IBufferOffsetSize data) { var output = new BufferOffsetSize (GetEncryptedSize (data.Size)); var ret = Encrypt (contentType, data, output); output.TruncateTo (ret); return output; }
/// <devdoc> /// <para> /// Due to Winsock restrictions /// If on Win9x platforms and the number of buffers are more than 16, performs /// concatenation of the buffers, so that we have 16 buffers. /// </para> /// </devdoc> private BufferOffsetSize[] ConcatenateBuffersOnWin9x(BufferOffsetSize[] buffers) { return buffers; }
// // internal void Write(BufferOffsetSize[] buffers) { ProcessWrite(buffers, null); }
internal virtual IAsyncResult UnsafeBeginMultipleWrite( BufferOffsetSize[] buffers, AsyncCallback callback, Object state) { #if DEBUG GlobalLog.ThreadContract(ThreadKinds.Unknown, "NetworkStream#" + ValidationHelper.HashString(this) + "::BeginMultipleWrite"); using (GlobalLog.SetThreadKind(ThreadKinds.Async)) { #endif // // parameter validation // if (buffers == null) { throw new ArgumentNullException("buffers"); } Socket chkStreamSocket = m_StreamSocket; if(chkStreamSocket == null) { throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed))); } try { // // call BeginMultipleSend on the Socket. // IAsyncResult asyncResult = chkStreamSocket.UnsafeBeginMultipleSend( buffers, SocketFlags.None, callback, state); return asyncResult; } catch (Exception exception) { if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { throw; } // // some sort of error occured on the socket call, // set the SocketException as InnerException and throw // throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); } #if DEBUG } #endif }
// // Assumes that InnerStream type == typeof(NetworkStream) // internal IAsyncResult BeginWrite(BufferOffsetSize[] buffers, AsyncCallback asyncCallback, object asyncState) { LazyAsyncResult lazyResult = new LazyAsyncResult(this, asyncState, asyncCallback); SplitWriteAsyncProtocolRequest asyncRequest = new SplitWriteAsyncProtocolRequest(lazyResult); ProcessWrite(buffers, asyncRequest); return lazyResult; }
public BufferList(BufferOffsetSize[] buffers) { _buffers = buffers; }
// // Combined [....]/async write method. For [....] case asyncRequest==null // private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { if (_SslState.LastPayload != null) { // // !!! LastPayload Only used in TlsStream for HTTP and it needs re-work for a general case !!! // BufferOffsetSize[] buffers = new BufferOffsetSize[1]; buffers[0] = new BufferOffsetSize(buffer, offset, count, false); if (asyncRequest != null) ProcessWrite(buffers, new SplitWriteAsyncProtocolRequest(asyncRequest.UserAsyncResult)); else ProcessWrite(buffers, null); return; } ValidateParameters(buffer, offset, count); if (Interlocked.Exchange(ref _NestedWrite, 1) == 1) { throw new NotSupportedException(SR.GetString(SR.net_io_invalidnestedcall, (asyncRequest != null? "BeginWrite":"Write"), "write")); } bool failed = false; try { StartWriting(buffer, offset, count, asyncRequest); } catch (Exception e) { _SslState.FinishWrite(); failed = true; if (e is IOException) { throw; } throw new IOException(SR.GetString(SR.net_io_write), e); } finally { if (asyncRequest == null || failed) { _NestedWrite = 0; } } }
public bool ProcessHandshakeMessage (HandshakeType type, TlsBuffer incoming, out SecurityStatus status) { if (HasPendingOutput && type != HandshakeType.HelloRequest) throw new TlsException (AlertDescription.InternalError); if (!VerifyMessage (type)) { if (type == HandshakeType.HelloRequest) { status = SecurityStatus.ContinueNeeded; return false; } throw new TlsException (AlertDescription.UnexpectedMessage); } var incomingBuffer = new BufferOffsetSize (incoming.Buffer, incoming.Position - 4, incoming.Remaining + 4); var startPosition = incoming.Position - 4; var message = CreateMessage (type, incoming); incoming.Position = startPosition; #if DEBUG_FULL if (Context.EnableDebugging) DebugHelper.WriteLine ("ProcessMessage: {0} {1} {2}", GetType ().Name, Context.IsServer, type); #endif #if INSTRUMENTATION if (State == NegotiationState.InitialServerConnection && Context.HasInstrument (HandshakeInstrumentType.CloseServerConnection)) { DebugHelper.WriteLine ("Instrumentation requested to close server connection."); status = SecurityStatus.InvalidHandle; return true; } #endif var result = HandleMessage (message); switch (result) { case MessageStatus.CredentialsNeeded: status = SecurityStatus.CredentialsNeeded; return false; case MessageStatus.Finished: hasPendingOutput = true; if (Context.IsServer) Context.HandshakeParameters.HandshakeMessages.Add (message, incomingBuffer); status = SecurityStatus.OK; return true; case MessageStatus.IgnoreMessage: status = SecurityStatus.ContinueNeeded; return false; case MessageStatus.Renegotiate: hasPendingOutput = true; if (message.Type != HandshakeType.HelloRequest) Context.HandshakeParameters.HandshakeMessages.Add (message, incomingBuffer); status = SecurityStatus.ContinueNeeded; return true; case MessageStatus.GenerateOutput: hasPendingOutput = true; Context.HandshakeParameters.HandshakeMessages.Add (message, incomingBuffer); status = SecurityStatus.ContinueNeeded; return true; case MessageStatus.ContinueNeeded: Context.HandshakeParameters.HandshakeMessages.Add (message, incomingBuffer); status = SecurityStatus.ContinueNeeded; return false; default: throw new InvalidOperationException (); } }
static void EncodeRecord_internal (TlsProtocolCode protocol, ContentType contentType, CryptoParameters crypto, IBufferOffsetSize buffer, TlsStream output, int fragmentSize = MAX_FRAGMENT_SIZE) { var maxExtraBytes = crypto != null ? crypto.MaxExtraEncryptedBytes : 0; var offset = buffer.Offset; var remaining = buffer.Size; #if !INSTRUMENTATION fragmentSize = MAX_FRAGMENT_SIZE; #endif do { BufferOffsetSize fragment; var encryptedSize = crypto != null ? crypto.GetEncryptedSize (remaining) : remaining; if (encryptedSize <= fragmentSize) fragment = new BufferOffsetSize (buffer.Buffer, offset, remaining); else { fragment = new BufferOffsetSize (buffer.Buffer, offset, fragmentSize - maxExtraBytes); encryptedSize = crypto != null ? crypto.GetEncryptedSize (fragment.Size) : fragment.Size; } // Write tls message output.Write ((byte)contentType); output.Write ((short)protocol); output.Write ((short)encryptedSize); if (crypto != null) { output.MakeRoom (encryptedSize); var ret = crypto.Encrypt (contentType, fragment, output.GetRemaining ()); output.Position += ret; } else { output.Write (fragment.Buffer, fragment.Offset, fragment.Size); } offset += fragment.Size; remaining -= fragment.Size; } while (remaining > 0); }
private static IAsyncResult BeginMultipleWrite(IList<ArraySegment<byte>> sendBuffers, AsyncCallback callback, object asyncState) { Contract.Assert(sendBuffers != null, "'sendBuffers' MUST NOT be NULL."); Contract.Assert(asyncState != null, "'asyncState' MUST NOT be NULL."); WebSocketConnection connection = asyncState as WebSocketConnection; Contract.Assert(connection != null, "'connection' MUST NOT be NULL."); BufferOffsetSize[] buffers = new BufferOffsetSize[sendBuffers.Count]; for (int index = 0; index < sendBuffers.Count; index++) { ArraySegment<byte> sendBuffer = sendBuffers[index]; buffers[index] = new BufferOffsetSize(sendBuffer.Array, sendBuffer.Offset, sendBuffer.Count, false); } WebSocketHelpers.ThrowIfConnectionAborted(connection.m_InnerStream, false); return connection.m_InnerStream.NetworkStream.BeginMultipleWrite(buffers, callback, asyncState); }
/// <devdoc> /// <para> /// Performs a [....] Write of an array of buffers. /// </para> /// </devdoc> internal virtual void MultipleWrite(BufferOffsetSize[] buffers) { GlobalLog.ThreadContract(ThreadKinds.Sync, "NetworkStream#" + ValidationHelper.HashString(this) + "::MultipleWrite"); // // parameter validation // if (buffers == null) { throw new ArgumentNullException("buffers"); } Socket chkStreamSocket = m_StreamSocket; if(chkStreamSocket == null) { throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed))); } try { chkStreamSocket.MultipleSend( buffers, SocketFlags.None); } catch (Exception exception) { if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { throw; } // // some sort of error occured on the socket call, // set the SocketException as InnerException and throw // throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); } }
internal IAsyncResult UnsafeBeginMultipleSend (BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state) { return BeginMultipleSend (buffers, socketFlags, callback, state); }
public AsyncProtocolRequest(MobileAuthenticatedStream parent, LazyAsyncResult lazyResult, BufferOffsetSize userBuffer = null) { Parent = parent; UserAsyncResult = lazyResult; UserBuffer = userBuffer; }
public IBufferOffsetSize Decrypt (ContentType contentType, IBufferOffsetSize input) { var output = new BufferOffsetSize (input.Size); var ret = Decrypt (contentType, input, output); output.TruncateTo (ret); return output; }
public bool ProcessHandshakeMessage(HandshakeType type, TlsBuffer incoming, out SecurityStatus status) { if (HasPendingOutput && type != HandshakeType.HelloRequest) { throw new TlsException(AlertDescription.InternalError); } if (!VerifyMessage(type)) { throw new TlsException(AlertDescription.UnexpectedMessage); } var incomingBuffer = new BufferOffsetSize(incoming.Buffer, incoming.Position - 4, incoming.Remaining + 4); var startPosition = incoming.Position - 4; var message = CreateMessage(type, incoming); incoming.Position = startPosition; #if FIXME incoming.Offset = incoming.Position; #endif #if DEBUG_FULL if (Context.EnableDebugging) { DebugHelper.WriteLine("ProcessMessage: {0} {1} {2}", GetType().Name, Context.IsServer, type); } #endif var result = HandleMessage(message); switch (result) { case MessageStatus.CredentialsNeeded: status = SecurityStatus.CredentialsNeeded; return(false); case MessageStatus.Finished: hasPendingOutput = true; if (Context.IsServer) { Context.HandshakeParameters.HandshakeMessages.Add(message, incomingBuffer); } status = SecurityStatus.OK; return(true); case MessageStatus.IgnoreMessage: status = SecurityStatus.ContinueNeeded; return(false); case MessageStatus.Renegotiate: hasPendingOutput = true; if (message.Type != HandshakeType.HelloRequest) { Context.HandshakeParameters.HandshakeMessages.Add(message, incomingBuffer); } status = SecurityStatus.Renegotiate; return(true); case MessageStatus.GenerateOutput: hasPendingOutput = true; Context.HandshakeParameters.HandshakeMessages.Add(message, incomingBuffer); status = SecurityStatus.ContinueNeeded; return(true); case MessageStatus.ContinueNeeded: Context.HandshakeParameters.HandshakeMessages.Add(message, incomingBuffer); status = SecurityStatus.ContinueNeeded; return(false); default: throw new InvalidOperationException(); } }
protected override int Encrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { // Calculate message MAC byte[] mac = null; if (IsServer) mac = ComputeServerRecordMAC (contentType, input); else mac = ComputeClientRecordMAC (contentType, input); #if DEBUG_FULL if (Cipher.EnableDebugging) DebugHelper.WriteLine ("RECORD MAC", mac); #endif int plen; byte padLen; int totalLength = GetEncryptedSize (input.Size, out plen, out padLen); var totalOutput = new BufferOffsetSize (output.Buffer, output.Offset, totalLength); var outputWriter = new TlsBuffer (totalOutput); outputWriter.Position += HeaderSize; outputWriter.Write (input.Buffer, input.Offset, input.Size); outputWriter.Write (mac); for (int i = 0; i <= padLen; i++) outputWriter.Write (padLen); // Encrypt the message EncryptRecord (d, totalOutput); return totalLength; }
// // Performs encryption of an array of buffers, proceeds buffer by buffer, if the individual // buffer size exceeds a SSL limit of SecureChannel.MaxDataSize,the buffers are then split into smaller ones. // Returns the same array that is encrypted or a new array of encrypted buffers. // private BufferOffsetSize[] EncryptBuffers(BufferOffsetSize[] buffers, byte[] lastHandshakePayload) { List <BufferOffsetSize> arrayList = null; SecurityStatus status = SecurityStatus.OK; foreach (BufferOffsetSize buffer in buffers) { int chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); byte[] outBuffer = null; int outSize; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) { break; } if (chunkBytes != buffer.Size || arrayList != null) { if (arrayList == null) { arrayList = new List <BufferOffsetSize>(buffers.Length * (buffer.Size / chunkBytes + 1)); if (lastHandshakePayload != null) { arrayList.Add(new BufferOffsetSize(lastHandshakePayload, false)); } foreach (BufferOffsetSize oldBuffer in buffers) { if (oldBuffer == buffer) { break; } arrayList.Add(oldBuffer); } } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); while ((buffer.Size -= chunkBytes) != 0) { buffer.Offset += chunkBytes; chunkBytes = Math.Min(buffer.Size, _SslState.MaxDataSize); outBuffer = null; status = _SslState.EncryptData(buffer.Buffer, buffer.Offset, chunkBytes, ref outBuffer, out outSize); if (status != SecurityStatus.OK) { break; } arrayList.Add(new BufferOffsetSize(outBuffer, 0, outSize, false)); } } else { buffer.Buffer = outBuffer; buffer.Offset = 0; buffer.Size = outSize; } if (status != SecurityStatus.OK) { break; } } if (status != SecurityStatus.OK) { // ProtocolToken message = new ProtocolToken(null, status); throw new IOException(SR.GetString(SR.net_io_encrypt), message.GetException()); } if (arrayList != null) { buffers = arrayList.ToArray(); } else if (lastHandshakePayload != null) { BufferOffsetSize[] result = new BufferOffsetSize[buffers.Length + 1]; Array.Copy(buffers, 0, result, 1, buffers.Length); result[0] = new BufferOffsetSize(lastHandshakePayload, false); buffers = result; } return(buffers); }
protected override int Decrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) return -1; if (input.Size < MinExtraEncryptedBytes) return -1; var plen = DecryptRecord (d, input, output); if (plen <= 0) return -1; var padlen = output.Buffer [output.Offset + plen - 1]; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine ("DECRYPT: {0} {1} {2}", input.Size, plen, padlen); DebugHelper.WriteBuffer ("DECRYPTED", output.Buffer, output.Offset, plen); } #endif /* * VERY IMPORTANT: * * The Compiler and JIT *** MUST NOT *** optimize the following block of code. * * It is essential that the dummy checks and dummy calls be kept in place. * Also do not put any debugging code into that region as it would mess up with * the timing. * */ #region The following block of code *** MUST NOT *** be optimized in any way if (MacSize + padlen + 1 > plen) { // Invalid padding: plaintext is not long enough. // First run a loop as if there were 256 bytes of padding, with a dummy check. int ok = -1; for (int i = 0; i < 256; i++) { if (output.Buffer [i % output.Size] != padlen) ok--; } // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize (output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC (contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare (invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return ok; } else { int ok = 0; var resultLength = plen - padlen - MacSize - 1; for (int i = 0; i < padlen; i++) { if (output.Buffer [output.Offset + resultLength + MacSize + i] != padlen) ok--; } var dummyOk = ok; var dummyLen = 256 - padlen - 1; for (int i = 0; i < dummyLen; i++) { if (output.Buffer [i % output.Size] != padlen) dummyOk--; } if (ok < 0) { // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize (output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC (contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare (invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return ok; } else { var first = new BufferOffsetSize (output.Buffer, output.Offset, resultLength); var checkMac = ComputeRecordMAC (contentType, first); var L1 = 13 + plen - MacSize; var L2 = 13 + plen - padlen - 1 - MacSize; var additional = ((L1 - 55) / 64) - ((L2 - 55) / 64); if (additional > 0) { var algorithm = HMac.CreateHash (Cipher.HashAlgorithmType); for (int i = 0; i < additional; i++) algorithm.TransformBlock (input.Buffer, input.Offset, BlockSize, null, 0); } ok += TlsBuffer.ConstantTimeCompare (checkMac, 0, checkMac.Length, output.Buffer, output.Offset + resultLength, MacSize); if (ok == 0) ok = resultLength; return ok; } } #endregion }