]> git.ipfire.org Git - thirdparty/openssl.git/blame_incremental - ssl/packet.c
remove horrible pragma macro and remove __owur from SSL_CTX_add_session() declaration
[thirdparty/openssl.git] / ssl / packet.c
... / ...
CommitLineData
1/*
2 * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include "e_os.h"
11#include "packet_locl.h"
12
13#define DEFAULT_BUF_SIZE 256
14
15int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
16{
17 if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
18 return 0;
19
20 pkt->written += len;
21 pkt->curr += len;
22 return 1;
23}
24
25int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
26 unsigned char **allocbytes, size_t lenbytes)
27{
28 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
29 || !WPACKET_allocate_bytes(pkt, len, allocbytes)
30 || !WPACKET_close(pkt))
31 return 0;
32
33 return 1;
34}
35
36#define GETBUF(p) (((p)->staticbuf != NULL) \
37 ? (p)->staticbuf : (unsigned char *)(p)->buf->data)
38
39int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
40{
41 /* Internal API, so should not fail */
42 if (!ossl_assert(pkt->subs != NULL && len != 0))
43 return 0;
44
45 if (pkt->maxsize - pkt->written < len)
46 return 0;
47
48 if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) {
49 size_t newlen;
50 size_t reflen;
51
52 reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
53
54 if (reflen > SIZE_MAX / 2) {
55 newlen = SIZE_MAX;
56 } else {
57 newlen = reflen * 2;
58 if (newlen < DEFAULT_BUF_SIZE)
59 newlen = DEFAULT_BUF_SIZE;
60 }
61 if (BUF_MEM_grow(pkt->buf, newlen) == 0)
62 return 0;
63 }
64 if (allocbytes != NULL)
65 *allocbytes = WPACKET_get_curr(pkt);
66
67 return 1;
68}
69
70int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
71 unsigned char **allocbytes, size_t lenbytes)
72{
73 if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
74 return 0;
75
76 *allocbytes += lenbytes;
77
78 return 1;
79}
80
81static size_t maxmaxsize(size_t lenbytes)
82{
83 if (lenbytes >= sizeof(size_t) || lenbytes == 0)
84 return SIZE_MAX;
85
86 return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
87}
88
89static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
90{
91 unsigned char *lenchars;
92
93 pkt->curr = 0;
94 pkt->written = 0;
95
96 pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
97 if (pkt->subs == NULL)
98 return 0;
99
100 if (lenbytes == 0)
101 return 1;
102
103 pkt->subs->pwritten = lenbytes;
104 pkt->subs->lenbytes = lenbytes;
105
106 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
107 OPENSSL_free(pkt->subs);
108 pkt->subs = NULL;
109 return 0;
110 }
111 pkt->subs->packet_len = lenchars - GETBUF(pkt);
112
113 return 1;
114}
115
116int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
117 size_t lenbytes)
118{
119 size_t max = maxmaxsize(lenbytes);
120
121 /* Internal API, so should not fail */
122 if (!ossl_assert(buf != NULL && len > 0))
123 return 0;
124
125 pkt->staticbuf = buf;
126 pkt->buf = NULL;
127 pkt->maxsize = (max < len) ? max : len;
128
129 return wpacket_intern_init_len(pkt, lenbytes);
130}
131
132int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
133{
134 /* Internal API, so should not fail */
135 if (!ossl_assert(buf != NULL))
136 return 0;
137
138 pkt->staticbuf = NULL;
139 pkt->buf = buf;
140 pkt->maxsize = maxmaxsize(lenbytes);
141
142 return wpacket_intern_init_len(pkt, lenbytes);
143}
144
145int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
146{
147 return WPACKET_init_len(pkt, buf, 0);
148}
149
150int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
151{
152 /* Internal API, so should not fail */
153 if (!ossl_assert(pkt->subs != NULL))
154 return 0;
155
156 pkt->subs->flags = flags;
157
158 return 1;
159}
160
161/* Store the |value| of length |len| at location |data| */
162static int put_value(unsigned char *data, size_t value, size_t len)
163{
164 for (data += len - 1; len > 0; len--) {
165 *data = (unsigned char)(value & 0xff);
166 data--;
167 value >>= 8;
168 }
169
170 /* Check whether we could fit the value in the assigned number of bytes */
171 if (value > 0)
172 return 0;
173
174 return 1;
175}
176
177
178/*
179 * Internal helper function used by WPACKET_close(), WPACKET_finish() and
180 * WPACKET_fill_lengths() to close a sub-packet and write out its length if
181 * necessary. If |doclose| is 0 then it goes through the motions of closing
182 * (i.e. it fills in all the lengths), but doesn't actually close anything.
183 */
184static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
185{
186 size_t packlen = pkt->written - sub->pwritten;
187
188 if (packlen == 0
189 && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
190 return 0;
191
192 if (packlen == 0
193 && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
194 /* We can't handle this case. Return an error */
195 if (!doclose)
196 return 0;
197
198 /* Deallocate any bytes allocated for the length of the WPACKET */
199 if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
200 pkt->written -= sub->lenbytes;
201 pkt->curr -= sub->lenbytes;
202 }
203
204 /* Don't write out the packet length */
205 sub->packet_len = 0;
206 sub->lenbytes = 0;
207 }
208
209 /* Write out the WPACKET length if needed */
210 if (sub->lenbytes > 0
211 && !put_value(&GETBUF(pkt)[sub->packet_len], packlen,
212 sub->lenbytes))
213 return 0;
214
215 if (doclose) {
216 pkt->subs = sub->parent;
217 OPENSSL_free(sub);
218 }
219
220 return 1;
221}
222
223int WPACKET_fill_lengths(WPACKET *pkt)
224{
225 WPACKET_SUB *sub;
226
227 if (!ossl_assert(pkt->subs != NULL))
228 return 0;
229
230 for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
231 if (!wpacket_intern_close(pkt, sub, 0))
232 return 0;
233 }
234
235 return 1;
236}
237
238int WPACKET_close(WPACKET *pkt)
239{
240 /*
241 * Internal API, so should not fail - but we do negative testing of this
242 * so no assert (otherwise the tests fail)
243 */
244 if (pkt->subs == NULL || pkt->subs->parent == NULL)
245 return 0;
246
247 return wpacket_intern_close(pkt, pkt->subs, 1);
248}
249
250int WPACKET_finish(WPACKET *pkt)
251{
252 int ret;
253
254 /*
255 * Internal API, so should not fail - but we do negative testing of this
256 * so no assert (otherwise the tests fail)
257 */
258 if (pkt->subs == NULL || pkt->subs->parent != NULL)
259 return 0;
260
261 ret = wpacket_intern_close(pkt, pkt->subs, 1);
262 if (ret) {
263 OPENSSL_free(pkt->subs);
264 pkt->subs = NULL;
265 }
266
267 return ret;
268}
269
270int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
271{
272 WPACKET_SUB *sub;
273 unsigned char *lenchars;
274
275 /* Internal API, so should not fail */
276 if (!ossl_assert(pkt->subs != NULL))
277 return 0;
278
279 sub = OPENSSL_zalloc(sizeof(*sub));
280 if (sub == NULL)
281 return 0;
282
283 sub->parent = pkt->subs;
284 pkt->subs = sub;
285 sub->pwritten = pkt->written + lenbytes;
286 sub->lenbytes = lenbytes;
287
288 if (lenbytes == 0) {
289 sub->packet_len = 0;
290 return 1;
291 }
292
293 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
294 return 0;
295 /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
296 sub->packet_len = lenchars - GETBUF(pkt);
297
298 return 1;
299}
300
301int WPACKET_start_sub_packet(WPACKET *pkt)
302{
303 return WPACKET_start_sub_packet_len__(pkt, 0);
304}
305
306int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size)
307{
308 unsigned char *data;
309
310 /* Internal API, so should not fail */
311 if (!ossl_assert(size <= sizeof(unsigned int))
312 || !WPACKET_allocate_bytes(pkt, size, &data)
313 || !put_value(data, val, size))
314 return 0;
315
316 return 1;
317}
318
319int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
320{
321 WPACKET_SUB *sub;
322 size_t lenbytes;
323
324 /* Internal API, so should not fail */
325 if (!ossl_assert(pkt->subs != NULL))
326 return 0;
327
328 /* Find the WPACKET_SUB for the top level */
329 for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
330 continue;
331
332 lenbytes = sub->lenbytes;
333 if (lenbytes == 0)
334 lenbytes = sizeof(pkt->maxsize);
335
336 if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
337 return 0;
338
339 pkt->maxsize = maxsize;
340
341 return 1;
342}
343
344int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
345{
346 unsigned char *dest;
347
348 if (len == 0)
349 return 1;
350
351 if (!WPACKET_allocate_bytes(pkt, len, &dest))
352 return 0;
353
354 memset(dest, ch, len);
355
356 return 1;
357}
358
359int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
360{
361 unsigned char *dest;
362
363 if (len == 0)
364 return 1;
365
366 if (!WPACKET_allocate_bytes(pkt, len, &dest))
367 return 0;
368
369 memcpy(dest, src, len);
370
371 return 1;
372}
373
374int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
375 size_t lenbytes)
376{
377 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
378 || !WPACKET_memcpy(pkt, src, len)
379 || !WPACKET_close(pkt))
380 return 0;
381
382 return 1;
383}
384
385int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
386{
387 /* Internal API, so should not fail */
388 if (!ossl_assert(written != NULL))
389 return 0;
390
391 *written = pkt->written;
392
393 return 1;
394}
395
396int WPACKET_get_length(WPACKET *pkt, size_t *len)
397{
398 /* Internal API, so should not fail */
399 if (!ossl_assert(pkt->subs != NULL && len != NULL))
400 return 0;
401
402 *len = pkt->written - pkt->subs->pwritten;
403
404 return 1;
405}
406
407unsigned char *WPACKET_get_curr(WPACKET *pkt)
408{
409 return GETBUF(pkt) + pkt->curr;
410}
411
412void WPACKET_cleanup(WPACKET *pkt)
413{
414 WPACKET_SUB *sub, *parent;
415
416 for (sub = pkt->subs; sub != NULL; sub = parent) {
417 parent = sub->parent;
418 OPENSSL_free(sub);
419 }
420 pkt->subs = NULL;
421}