5 // Martin Baulig <martin.baulig@xamarin.com>
7 // Copyright (c) 2014-2016 Xamarin Inc. (http://www.xamarin.com)
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 namespace Mono.Security.Interface
30 public class TlsBuffer : SecretParameters
36 public int Remaining {
37 get { return Size - (Position - Offset); }
40 public byte[] Buffer {
41 get { return innerBuffer.Buffer; }
45 get { return innerBuffer.Offset; }
49 get { return innerBuffer.Size; }
52 public int EndOffset {
53 get { return Offset + Size; }
56 IBufferOffsetSize innerBuffer;
58 protected TlsBuffer ()
63 public TlsBuffer (IBufferOffsetSize bos)
66 Position = bos.Offset;
69 public TlsBuffer (byte[] buffer, int offset, int size)
70 : this (new BufferOffsetSize (buffer, offset, size))
74 public TlsBuffer (byte[] buffer)
75 : this (buffer, 0, buffer.Length)
79 public TlsBuffer (int size)
80 : this (new byte [size], 0, size)
84 public byte ReadByte ()
86 if (Position >= EndOffset)
87 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
88 return Buffer [Position++];
91 public short ReadInt16 ()
93 if (Position + 1 >= EndOffset)
94 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
95 var retval = (short)(Buffer [Position] << 8 | Buffer [Position + 1]);
100 public int ReadInt24 ()
102 if (Position + 2 >= EndOffset)
103 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
104 var retval = ((Buffer [Position] << 16) | (Buffer [Position+1] << 8) | Buffer [Position+2]);
109 public int ReadInt32 ()
111 if (Position + 3 >= EndOffset)
112 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
113 var retval = ((Buffer [Position] << 24) | (Buffer [Position+1] << 16) | (Buffer [Position+2] << 8) | Buffer [Position+3]);
118 public TlsBuffer ReadBuffer (int length)
120 if (Position + length > EndOffset)
121 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
122 var retval = new TlsBuffer (Buffer, Position, length);
127 public IBufferOffsetSize GetRemaining ()
129 return new BufferOffsetSize (Buffer, Position, Remaining);
132 protected virtual void MakeRoomInternal (int size)
134 if (Position + size > EndOffset)
135 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
138 public void Write (byte value)
140 MakeRoomInternal (1);
141 Buffer [Position++] = value;
144 public void Write (short value)
146 MakeRoomInternal (2);
147 WriteInt16 (Buffer, Position, value);
151 public static void WriteInt16 (byte[] buffer, int offset, short value)
153 buffer[offset] = ((byte)(value >> 8));
154 buffer[offset+1] = ((byte)value);
157 public void Write (int value)
159 MakeRoomInternal (4);
160 WriteInt32 (Buffer, Position, value);
164 public void WriteInt24 (int value)
166 MakeRoomInternal (3);
167 WriteInt24 (Buffer, Position, value);
171 #pragma warning disable 3001
172 public void Write (ulong value)
173 #pragma warning restore 3001
175 MakeRoomInternal (8);
176 WriteInt64 (Buffer, Position, value);
180 public static void WriteInt24 (byte[] buffer, int offset, int value)
182 buffer[offset] = ((byte)(value >> 16));
183 buffer[offset+1] = ((byte)(value >> 8));
184 buffer[offset+2] = ((byte)value);
187 public static void WriteInt32 (byte[] buffer, int offset, int value)
189 buffer[offset] = ((byte)(value >> 24));
190 buffer[offset+1] = ((byte)(value >> 16));
191 buffer[offset+2] = ((byte)(value >> 8));
192 buffer[offset+3] = ((byte)value);
195 #pragma warning disable 3001
196 public static void WriteInt64 (byte[] buffer, int offset, ulong value)
197 #pragma warning restore 3001
199 buffer[offset] = (byte) (value >> 56);
200 buffer[offset+1] = (byte) (value >> 48);
201 buffer[offset+2] = (byte) (value >> 40);
202 buffer[offset+3] = (byte) (value >> 32);
203 buffer[offset+4] = (byte) (value >> 24);
204 buffer[offset+5] = (byte) (value >> 16);
205 buffer[offset+6] = (byte) (value >> 8);
206 buffer[offset+7] = (byte) value;
209 public void Write (byte[] buffer)
211 Write (buffer, 0, buffer.Length);
214 public void Write (byte[] buffer, int offset, int size)
216 MakeRoomInternal (size);
217 Array.Copy (buffer, offset, Buffer, Position, size);
221 public void Write (IBufferOffsetSize buffer)
223 Write (buffer.Buffer, buffer.Offset, buffer.Size);
226 public SecureBuffer ReadSecureBuffer (int count)
228 return new SecureBuffer (ReadBytes (count));
231 public byte[] ReadBytes (int count)
233 if (Position + count > EndOffset)
234 throw new TlsException (AlertDescription.DecodeError, "Buffer overflow");
235 var retval = new byte [count];
236 Array.Copy (Buffer, Position, retval, 0, count);
241 internal static bool Compare (SecureBuffer buffer1, SecureBuffer buffer2)
243 if (buffer1 == null || buffer2 == null)
246 if (buffer1.Size != buffer2.Size)
249 for (int i = 0; i < buffer1.Size; i++) {
250 if (buffer1.Buffer [i] != buffer2.Buffer [i])
256 public static bool Compare (IBufferOffsetSize buffer1, IBufferOffsetSize buffer2)
258 if (buffer1 == null || buffer2 == null)
261 if (buffer1.Size != buffer2.Size)
264 for (int i = 0; i < buffer1.Size; i++) {
265 if (buffer1.Buffer [buffer1.Offset + i] != buffer2.Buffer [buffer2.Offset + i])
271 public static bool Compare (byte[] buffer1, byte[] buffer2)
273 if (buffer1 == null || buffer2 == null)
276 return Compare (buffer1, 0, buffer1.Length, buffer2, 0, buffer2.Length);
279 public static bool Compare (byte[] buffer1, int offset1, int size1, byte[] buffer2, int offset2, int size2)
281 if (buffer1 == null || buffer2 == null)
287 for (int i = 0; i < size1; i++) {
288 if (buffer1 [offset1 + i] != buffer2 [offset2 + i])
295 public static int ConstantTimeCompare (byte[] buffer1, int offset1, int size1, byte[] buffer2, int offset2, int size2)
301 effectiveSize = size1;
302 } else if (size2 < size1) {
304 effectiveSize = size2;
306 effectiveSize = size1;
309 for (int i = 0; i < effectiveSize; i++) {
310 if (buffer1 [offset1 + i] != buffer2 [offset2 + i])
317 protected void SetBuffer (byte[] buffer, int offset, int size)
319 innerBuffer = new BufferOffsetSize (buffer, offset, size);
322 protected override void Clear ()
324 var disposable = innerBuffer as IDisposable;
325 if (disposable != null)
326 disposable.Dispose ();
331 public static readonly byte[] EmptyArray = new byte [0];