openssl: OpenSSL 1.1.0 is thread-safe so we don't have to setup callbacks
[strongswan.git] / src / libstrongswan / bio / bio_reader.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "bio_reader.h"
20
21 #include <utils/debug.h>
22
23 typedef struct private_bio_reader_t private_bio_reader_t;
24
25 /**
26 * Private data of an bio_reader_t object.
27 */
28 struct private_bio_reader_t {
29
30 /**
31 * Public bio_reader_t interface.
32 */
33 bio_reader_t public;
34
35 /**
36 * Remaining data to process
37 */
38 chunk_t buf;
39
40 /**
41 * Optional data to free during destruction
42 */
43 chunk_t cleanup;
44 };
45
46 METHOD(bio_reader_t, remaining, uint32_t,
47 private_bio_reader_t *this)
48 {
49 return this->buf.len;
50 }
51
52 METHOD(bio_reader_t, peek, chunk_t,
53 private_bio_reader_t *this)
54 {
55 return this->buf;
56 }
57
58 /**
59 * A version of chunk_skip() that supports skipping from the end (i.e. simply
60 * reducing the size)
61 */
62 static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end)
63 {
64 if (chunk.len > bytes)
65 {
66 if (!from_end)
67 {
68 chunk.ptr += bytes;
69 }
70 chunk.len -= bytes;
71 return chunk;
72 }
73 return chunk_empty;
74 }
75
76 /**
77 * Returns a pointer to the data to read, optionally from the end
78 */
79 static inline u_char *get_ptr_end(private_bio_reader_t *this, uint32_t len,
80 bool from_end)
81 {
82 return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr;
83 }
84
85 /**
86 * Read an uint8_t from the buffer, optionally from the end of the buffer
87 */
88 static bool read_uint8_internal(private_bio_reader_t *this, uint8_t *res,
89 bool from_end)
90 {
91 if (this->buf.len < 1)
92 {
93 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data",
94 this->buf.len);
95 return FALSE;
96 }
97 *res = *get_ptr_end(this, 1, from_end);
98 this->buf = chunk_skip_end(this->buf, 1, from_end);
99 return TRUE;
100 }
101
102 /**
103 * Read an uint16_t from the buffer, optionally from the end
104 */
105 static bool read_uint16_internal(private_bio_reader_t *this, uint16_t *res,
106 bool from_end)
107 {
108 if (this->buf.len < 2)
109 {
110 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data",
111 this->buf.len);
112 return FALSE;
113 }
114 *res = untoh16(get_ptr_end(this, 2, from_end));
115 this->buf = chunk_skip_end(this->buf, 2, from_end);
116 return TRUE;
117 }
118
119 /**
120 * Read an uint32_t (only 24-bit) from the buffer, optionally from the end
121 */
122 static bool read_uint24_internal(private_bio_reader_t *this, uint32_t *res,
123 bool from_end)
124 {
125 if (this->buf.len < 3)
126 {
127 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data",
128 this->buf.len);
129 return FALSE;
130 }
131 *res = untoh32(get_ptr_end(this, 3, from_end)) >> 8;
132 this->buf = chunk_skip_end(this->buf, 3, from_end);
133 return TRUE;
134 }
135
136 /**
137 * Read an uint32_t from the buffer, optionally from the end
138 */
139 static bool read_uint32_internal(private_bio_reader_t *this, uint32_t *res,
140 bool from_end)
141 {
142 if (this->buf.len < 4)
143 {
144 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data",
145 this->buf.len);
146 return FALSE;
147 }
148 *res = untoh32(get_ptr_end(this, 4, from_end));
149 this->buf = chunk_skip_end(this->buf, 4, from_end);
150 return TRUE;
151 }
152
153 /**
154 * Read an uint64_t from the buffer, optionally from the end
155 */
156 static bool read_uint64_internal(private_bio_reader_t *this, uint64_t *res,
157 bool from_end)
158 {
159 if (this->buf.len < 8)
160 {
161 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int64 data",
162 this->buf.len);
163 return FALSE;
164 }
165 *res = untoh64(get_ptr_end(this, 8, from_end));
166 this->buf = chunk_skip_end(this->buf, 8, from_end);
167 return TRUE;
168 }
169
170 /**
171 * Read a chunk of data from the buffer, optionally from the end
172 */
173 static bool read_data_internal(private_bio_reader_t *this, uint32_t len,
174 chunk_t *res, bool from_end)
175 {
176 if (this->buf.len < len)
177 {
178 DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data",
179 this->buf.len, len);
180 return FALSE;
181 }
182 *res = chunk_create(get_ptr_end(this, len, from_end), len);
183 this->buf = chunk_skip_end(this->buf, len, from_end);
184 return TRUE;
185 }
186
187 METHOD(bio_reader_t, read_uint8, bool,
188 private_bio_reader_t *this, uint8_t *res)
189 {
190 return read_uint8_internal(this, res, FALSE);
191 }
192
193 METHOD(bio_reader_t, read_uint16, bool,
194 private_bio_reader_t *this, uint16_t *res)
195 {
196 return read_uint16_internal(this, res, FALSE);
197 }
198
199 METHOD(bio_reader_t, read_uint24, bool,
200 private_bio_reader_t *this, uint32_t *res)
201 {
202 return read_uint24_internal(this, res, FALSE);
203 }
204
205 METHOD(bio_reader_t, read_uint32, bool,
206 private_bio_reader_t *this, uint32_t *res)
207 {
208 return read_uint32_internal(this, res, FALSE);
209 }
210
211 METHOD(bio_reader_t, read_uint64, bool,
212 private_bio_reader_t *this, uint64_t *res)
213 {
214 return read_uint64_internal(this, res, FALSE);
215 }
216
217 METHOD(bio_reader_t, read_data, bool,
218 private_bio_reader_t *this, uint32_t len, chunk_t *res)
219 {
220 return read_data_internal(this, len, res, FALSE);
221 }
222
223 METHOD(bio_reader_t, read_uint8_end, bool,
224 private_bio_reader_t *this, uint8_t *res)
225 {
226 return read_uint8_internal(this, res, TRUE);
227 }
228
229 METHOD(bio_reader_t, read_uint16_end, bool,
230 private_bio_reader_t *this, uint16_t *res)
231 {
232 return read_uint16_internal(this, res, TRUE);
233 }
234
235 METHOD(bio_reader_t, read_uint24_end, bool,
236 private_bio_reader_t *this, uint32_t *res)
237 {
238 return read_uint24_internal(this, res, TRUE);
239 }
240
241 METHOD(bio_reader_t, read_uint32_end, bool,
242 private_bio_reader_t *this, uint32_t *res)
243 {
244 return read_uint32_internal(this, res, TRUE);
245 }
246
247 METHOD(bio_reader_t, read_uint64_end, bool,
248 private_bio_reader_t *this, uint64_t *res)
249 {
250 return read_uint64_internal(this, res, TRUE);
251 }
252
253 METHOD(bio_reader_t, read_data_end, bool,
254 private_bio_reader_t *this, uint32_t len, chunk_t *res)
255 {
256 return read_data_internal(this, len, res, TRUE);
257 }
258
259 METHOD(bio_reader_t, read_data8, bool,
260 private_bio_reader_t *this, chunk_t *res)
261 {
262 uint8_t len;
263
264 if (!read_uint8(this, &len))
265 {
266 return FALSE;
267 }
268 return read_data(this, len, res);
269 }
270
271 METHOD(bio_reader_t, read_data16, bool,
272 private_bio_reader_t *this, chunk_t *res)
273 {
274 uint16_t len;
275
276 if (!read_uint16(this, &len))
277 {
278 return FALSE;
279 }
280 return read_data(this, len, res);
281 }
282
283 METHOD(bio_reader_t, read_data24, bool,
284 private_bio_reader_t *this, chunk_t *res)
285 {
286 uint32_t len;
287
288 if (!read_uint24(this, &len))
289 {
290 return FALSE;
291 }
292 return read_data(this, len, res);
293 }
294
295 METHOD(bio_reader_t, read_data32, bool,
296 private_bio_reader_t *this, chunk_t *res)
297 {
298 uint32_t len;
299
300 if (!read_uint32(this, &len))
301 {
302 return FALSE;
303 }
304 return read_data(this, len, res);
305 }
306
307 METHOD(bio_reader_t, destroy, void,
308 private_bio_reader_t *this)
309 {
310 free(this->cleanup.ptr);
311 free(this);
312 }
313
314 /**
315 * See header
316 */
317 bio_reader_t *bio_reader_create(chunk_t data)
318 {
319 private_bio_reader_t *this;
320
321 INIT(this,
322 .public = {
323 .remaining = _remaining,
324 .peek = _peek,
325 .read_uint8 = _read_uint8,
326 .read_uint16 = _read_uint16,
327 .read_uint24 = _read_uint24,
328 .read_uint32 = _read_uint32,
329 .read_uint64 = _read_uint64,
330 .read_data = _read_data,
331 .read_uint8_end = _read_uint8_end,
332 .read_uint16_end = _read_uint16_end,
333 .read_uint24_end = _read_uint24_end,
334 .read_uint32_end = _read_uint32_end,
335 .read_uint64_end = _read_uint64_end,
336 .read_data_end = _read_data_end,
337 .read_data8 = _read_data8,
338 .read_data16 = _read_data16,
339 .read_data24 = _read_data24,
340 .read_data32 = _read_data32,
341 .destroy = _destroy,
342 },
343 .buf = data,
344 );
345
346 return &this->public;
347 }
348
349 /**
350 * See header
351 */
352 bio_reader_t *bio_reader_create_own(chunk_t data)
353 {
354 private_bio_reader_t *this;
355
356 this = (private_bio_reader_t*)bio_reader_create(data);
357
358 this->cleanup = data;
359
360 return &this->public;
361 }