-//
-// TlsBuffer.cs
-//
-// Author:
-// Martin Baulig <martin.baulig@xamarin.com>
-//
-// Copyright (c) 2014-2016 Xamarin Inc. (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-
-namespace Mono.Security.Interface
-{
- public class TlsBuffer : SecretParameters
- {
- public int Position {
- get; set;
- }
-
- public int Remaining {
- get { return Size - (Position - Offset); }
- }
-
- public byte[] Buffer {
- get { return innerBuffer.Buffer; }
- }
-
- public int Offset {
- get { return innerBuffer.Offset; }
- }
-
- public int Size {
- get { return innerBuffer.Size; }
- }
-
- public int EndOffset {
- get { return Offset + Size; }
- }
-
- IBufferOffsetSize innerBuffer;
-
- protected TlsBuffer ()
- : this (null, 0, 0)
- {
- }
-
- public TlsBuffer (IBufferOffsetSize bos)
- {
- innerBuffer = bos;
- Position = bos.Offset;
- }
-
- public TlsBuffer (byte[] buffer, int offset, int size)
- : this (new BufferOffsetSize (buffer, offset, size))
- {
- }
-
- public TlsBuffer (byte[] buffer)
- : this (buffer, 0, buffer.Length)
- {
- }
-
- public TlsBuffer (int size)
- : this (new byte [size], 0, size)
- {
- }
-
- public byte ReadByte ()
- {
- if (Position >= EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- return Buffer [Position++];
- }
-
- public short ReadInt16 ()
- {
- if (Position + 1 >= EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- var retval = (short)(Buffer [Position] << 8 | Buffer [Position + 1]);
- Position += 2;
- return retval;
- }
-
- public int ReadInt24 ()
- {
- if (Position + 2 >= EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- var retval = ((Buffer [Position] << 16) | (Buffer [Position+1] << 8) | Buffer [Position+2]);
- Position += 3;
- return retval;
- }
-
- public int ReadInt32 ()
- {
- if (Position + 3 >= EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- var retval = ((Buffer [Position] << 24) | (Buffer [Position+1] << 16) | (Buffer [Position+2] << 8) | Buffer [Position+3]);
- Position += 4;
- return retval;
- }
-
- public TlsBuffer ReadBuffer (int length)
- {
- if (Position + length > EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- var retval = new TlsBuffer (Buffer, Position, length);
- Position += length;
- return retval;
- }
-
- public IBufferOffsetSize GetRemaining ()
- {
- return new BufferOffsetSize (Buffer, Position, Remaining);
- }
-
- protected virtual void MakeRoomInternal (int size)
- {
- if (Position + size > EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- }
-
- public void Write (byte value)
- {
- MakeRoomInternal (1);
- Buffer [Position++] = value;
- }
-
- public void Write (short value)
- {
- MakeRoomInternal (2);
- WriteInt16 (Buffer, Position, value);
- Position += 2;
- }
-
- public static void WriteInt16 (byte[] buffer, int offset, short value)
- {
- buffer[offset] = ((byte)(value >> 8));
- buffer[offset+1] = ((byte)value);
- }
-
- public void Write (int value)
- {
- MakeRoomInternal (4);
- WriteInt32 (Buffer, Position, value);
- Position += 4;
- }
-
- public void WriteInt24 (int value)
- {
- MakeRoomInternal (3);
- WriteInt24 (Buffer, Position, value);
- Position += 3;
- }
-
- #pragma warning disable 3001
- public void Write (ulong value)
- #pragma warning restore 3001
- {
- MakeRoomInternal (8);
- WriteInt64 (Buffer, Position, value);
- Position += 8;
- }
-
- public static void WriteInt24 (byte[] buffer, int offset, int value)
- {
- buffer[offset] = ((byte)(value >> 16));
- buffer[offset+1] = ((byte)(value >> 8));
- buffer[offset+2] = ((byte)value);
- }
-
- public static void WriteInt32 (byte[] buffer, int offset, int value)
- {
- buffer[offset] = ((byte)(value >> 24));
- buffer[offset+1] = ((byte)(value >> 16));
- buffer[offset+2] = ((byte)(value >> 8));
- buffer[offset+3] = ((byte)value);
- }
-
- #pragma warning disable 3001
- public static void WriteInt64 (byte[] buffer, int offset, ulong value)
- #pragma warning restore 3001
- {
- buffer[offset] = (byte) (value >> 56);
- buffer[offset+1] = (byte) (value >> 48);
- buffer[offset+2] = (byte) (value >> 40);
- buffer[offset+3] = (byte) (value >> 32);
- buffer[offset+4] = (byte) (value >> 24);
- buffer[offset+5] = (byte) (value >> 16);
- buffer[offset+6] = (byte) (value >> 8);
- buffer[offset+7] = (byte) value;
- }
-
- public void Write (byte[] buffer)
- {
- Write (buffer, 0, buffer.Length);
- }
-
- public void Write (byte[] buffer, int offset, int size)
- {
- MakeRoomInternal (size);
- Array.Copy (buffer, offset, Buffer, Position, size);
- Position += size;
- }
-
- public void Write (IBufferOffsetSize buffer)
- {
- Write (buffer.Buffer, buffer.Offset, buffer.Size);
- }
-
- public SecureBuffer ReadSecureBuffer (int count)
- {
- return new SecureBuffer (ReadBytes (count));
- }
-
- public byte[] ReadBytes (int count)
- {
- if (Position + count > EndOffset)
- throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
- var retval = new byte [count];
- Array.Copy (Buffer, Position, retval, 0, count);
- Position += count;
- return retval;
- }
-
- internal static bool Compare (SecureBuffer buffer1, SecureBuffer buffer2)
- {
- if (buffer1 == null || buffer2 == null)
- return false;
-
- if (buffer1.Size != buffer2.Size)
- return false;
-
- for (int i = 0; i < buffer1.Size; i++) {
- if (buffer1.Buffer [i] != buffer2.Buffer [i])
- return false;
- }
- return true;
- }
-
- public static bool Compare (IBufferOffsetSize buffer1, IBufferOffsetSize buffer2)
- {
- if (buffer1 == null || buffer2 == null)
- return false;
-
- if (buffer1.Size != buffer2.Size)
- return false;
-
- for (int i = 0; i < buffer1.Size; i++) {
- if (buffer1.Buffer [buffer1.Offset + i] != buffer2.Buffer [buffer2.Offset + i])
- return false;
- }
- return true;
- }
-
- public static bool Compare (byte[] buffer1, byte[] buffer2)
- {
- if (buffer1 == null || buffer2 == null)
- return false;
-
- return Compare (buffer1, 0, buffer1.Length, buffer2, 0, buffer2.Length);
- }
-
- public static bool Compare (byte[] buffer1, int offset1, int size1, byte[] buffer2, int offset2, int size2)
- {
- if (buffer1 == null || buffer2 == null)
- return false;
-
- if (size1 != size2)
- return false;
-
- for (int i = 0; i < size1; i++) {
- if (buffer1 [offset1 + i] != buffer2 [offset2 + i])
- return false;
- }
- return true;
-
- }
-
- public static int ConstantTimeCompare (byte[] buffer1, int offset1, int size1, byte[] buffer2, int offset2, int size2)
- {
- int status = 0;
- int effectiveSize;
- if (size1 < size2) {
- status--;
- effectiveSize = size1;
- } else if (size2 < size1) {
- status--;
- effectiveSize = size2;
- } else {
- effectiveSize = size1;
- }
-
- for (int i = 0; i < effectiveSize; i++) {
- if (buffer1 [offset1 + i] != buffer2 [offset2 + i])
- status--;
- }
-
- return status;
- }
-
- protected void SetBuffer (byte[] buffer, int offset, int size)
- {
- innerBuffer = new BufferOffsetSize (buffer, offset, size);
- }
-
- protected override void Clear ()
- {
- var disposable = innerBuffer as IDisposable;
- if (disposable != null)
- disposable.Dispose ();
- innerBuffer = null;
- Position = 0;
- }
-
- public static readonly byte[] EmptyArray = new byte [0];
- }
-}
-