Initial commit.
[BoarSSL] / SSLTLS / IO.cs
1 /*
2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 using System;
26 using System.IO;
27
28 namespace SSLTLS {
29
30 internal class IO {
31
32 internal static void Enc16be(int x, byte[] buf, int off)
33 {
34 buf[off + 0] = (byte)(x >> 8);
35 buf[off + 1] = (byte)x;
36 }
37
38 internal static void Enc24be(int x, byte[] buf, int off)
39 {
40 buf[off + 0] = (byte)(x >> 16);
41 buf[off + 1] = (byte)(x >> 8);
42 buf[off + 2] = (byte)x;
43 }
44
45 internal static void Enc32be(uint x, byte[] buf, int off)
46 {
47 buf[off + 0] = (byte)(x >> 24);
48 buf[off + 1] = (byte)(x >> 16);
49 buf[off + 2] = (byte)(x >> 8);
50 buf[off + 3] = (byte)x;
51 }
52
53 internal static void Enc64be(ulong x, byte[] buf, int off)
54 {
55 for (int i = 0; i < 8; i ++) {
56 buf[off + 7 - i] = (byte)x;
57 x >>= 8;
58 }
59 }
60
61 internal static int Dec16be(byte[] buf, int off)
62 {
63 return (buf[off + 0] << 8)
64 | buf[off + 1];
65 }
66
67 internal static int Dec24be(byte[] buf, int off)
68 {
69 return (buf[off + 0] << 16)
70 | (buf[off + 1] << 8)
71 | buf[off + 2];
72 }
73
74 internal static uint Dec32be(byte[] buf, int off)
75 {
76 return ((uint)buf[off + 0] << 24)
77 | ((uint)buf[off + 1] << 16)
78 | ((uint)buf[off + 2] << 8)
79 | (uint)buf[off + 3];
80 }
81
82 internal static ulong Dec64be(byte[] buf, int off)
83 {
84 ulong x = 0;
85 for (int i = 0; i < 8; i ++) {
86 x = (x << 8) | buf[off + i];
87 }
88 return x;
89 }
90
91 internal static void Write16(Stream s, int x)
92 {
93 s.WriteByte((byte)(x >> 8));
94 s.WriteByte((byte)x);
95 }
96
97 internal static void Write24(Stream s, int x)
98 {
99 s.WriteByte((byte)(x >> 16));
100 s.WriteByte((byte)(x >> 8));
101 s.WriteByte((byte)x);
102 }
103
104 /*
105 * Write a 5-byte record header at the specified offset.
106 */
107 internal static void WriteHeader(int recordType, int version,
108 int length, byte[] buf, int off)
109 {
110 buf[off] = (byte)recordType;
111 IO.Enc16be(version, buf, off + 1);
112 IO.Enc16be(length, buf, off + 3);
113 }
114
115 /*
116 * Read all requested bytes. Fail on unexpected EOF, unless
117 * 'eof' is true, in which case an EOF is acceptable at the
118 * very beginning (i.e. no byte read at all).
119 *
120 * Returned value is true, unless there was an EOF at the
121 * start and 'eof' is true, in which case returned value is
122 * false.
123 */
124 internal static bool ReadAll(Stream s, byte[] buf, bool eof)
125 {
126 return ReadAll(s, buf, 0, buf.Length, eof);
127 }
128
129 /*
130 * Read all requested bytes. Fail on unexpected EOF, unless
131 * 'eof' is true, in which case an EOF is acceptable at the
132 * very beginning (i.e. no byte read at all).
133 *
134 * Returned value is true, unless there was an EOF at the
135 * start and 'eof' is true, in which case returned value is
136 * false.
137 */
138 internal static bool ReadAll(Stream s,
139 byte[] buf, int off, int len, bool eof)
140 {
141 int tlen = 0;
142 while (tlen < len) {
143 int rlen = s.Read(buf, off + tlen, len - tlen);
144 if (rlen <= 0) {
145 if (eof && tlen == 0) {
146 return false;
147 }
148 throw new SSLException("Unexpected EOF");
149 }
150 tlen += rlen;
151 }
152 return true;
153 }
154
155 /*
156 * Compare two arrays of bytes for equality.
157 */
158 internal static bool Eq(byte[] a, byte[] b)
159 {
160 return EqCT(a, b) != 0;
161 }
162
163 /*
164 * Compare two arrays of bytes for equality. This is constant-time
165 * if both arrays have the same length. Returned value is 0xFFFFFFFF
166 * on equality, 0 otherwise.
167 */
168 internal static uint EqCT(byte[] a, byte[] b)
169 {
170 int n = a.Length;
171 if (n != b.Length) {
172 return 0;
173 }
174 int z = 0;
175 for (int i = 0; i < n; i ++) {
176 z |= a[i] ^ b[i];
177 }
178 return ~(uint)((z | -z) >> 31);
179 }
180
181 /*
182 * Duplicate an array of bytes. null is duplicated into null.
183 */
184 internal static byte[] CopyBlob(byte[] x)
185 {
186 if (x == null) {
187 return null;
188 }
189 byte[] y = new byte[x.Length];
190 Array.Copy(x, 0, y, 0, x.Length);
191 return y;
192 }
193 }
194
195 }