]> git.ipfire.org Git - thirdparty/openssl.git/blame - ssl/packet.c
Move from explicit sub-packets to implicit ones
[thirdparty/openssl.git] / ssl / packet.c
CommitLineData
b7273855
MC
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 "packet_locl.h"
11
12/*
0217dd19 13 * Allocate bytes in the WPACKET for the output. This reserves the bytes
b7273855
MC
14 * and count them as "written", but doesn't actually do the writing.
15 */
0217dd19 16int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
b7273855 17{
0217dd19
MC
18 if (pkt->subs == NULL || len == 0)
19 return 0;
b7273855 20
0217dd19 21 if (SIZE_MAX - pkt->written < len)
b7273855
MC
22 return 0;
23
0217dd19 24 if (pkt->maxsize > 0 && pkt->written + len > pkt->maxsize)
b7273855
MC
25 return 0;
26
0217dd19 27 if (pkt->buf->length - pkt->written < len) {
b7273855
MC
28 size_t newlen;
29
0217dd19 30 if (pkt->buf->length > SIZE_MAX / 2)
b7273855
MC
31 newlen = SIZE_MAX;
32 else
0217dd19
MC
33 newlen = pkt->buf->length * 2;
34 if (BUF_MEM_grow(pkt->buf, newlen) == 0)
35 return 0;
b7273855 36 }
0217dd19
MC
37 pkt->written += len;
38 *allocbytes = pkt->curr;
39 pkt->curr += len;
b7273855 40
0217dd19 41 return 1;
b7273855
MC
42}
43
44/*
ae2f7b37
MC
45 * Initialise a WPACKET with the buffer in |buf|. The buffer must exist
46 * for the whole time that the WPACKET is being used. Additionally |lenbytes| of
b7273855 47 * data is preallocated at the start of the buffer to store the length of the
ae2f7b37 48 * WPACKET once we know it.
b7273855 49 */
ae2f7b37 50int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
b7273855 51{
b7273855
MC
52 /* Sanity check */
53 if (buf == NULL)
54 return 0;
55
0217dd19
MC
56 pkt->buf = buf;
57 pkt->curr = (unsigned char *)buf->data;
58 pkt->written = 0;
59 pkt->maxsize = 0;
b7273855 60
0217dd19
MC
61 pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
62 if (pkt->subs == NULL)
63 return 0;
b7273855 64
0217dd19 65 if (lenbytes == 0)
b7273855 66 return 1;
b7273855 67
0217dd19
MC
68 pkt->subs->pwritten = lenbytes;
69 pkt->subs->lenbytes = lenbytes;
70
71 if (!WPACKET_allocate_bytes(pkt, lenbytes, &(pkt->subs->packet_len))) {
72 OPENSSL_free(pkt->subs);
73 pkt->subs = NULL;
b7273855
MC
74 return 0;
75 }
76
77 return 1;
78}
79
80/*
ae2f7b37 81 * Same as WPACKET_init_len except there is no preallocation of the WPACKET
b7273855
MC
82 * length.
83 */
ae2f7b37 84int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
b7273855 85{
ae2f7b37 86 return WPACKET_init_len(pkt, buf, 0);
b7273855
MC
87}
88
89/*
ae2f7b37
MC
90 * Set the WPACKET length, and the location for where we should write that
91 * length. Normally this will be at the start of the WPACKET, and therefore
92 * the WPACKET would have been initialised via WPACKET_init_len(). However there
b7273855 93 * is the possibility that the length needs to be written to some other location
ae2f7b37 94 * other than the start of the WPACKET. In that case init via WPACKET_init() and
b7273855
MC
95 * then set the location for the length using this function.
96 */
ae2f7b37 97int WPACKET_set_packet_len(WPACKET *pkt, unsigned char *packet_len,
b7273855
MC
98 size_t lenbytes)
99{
100 /* We only allow this to be set once */
0217dd19 101 if (pkt->subs == NULL)
b7273855
MC
102 return 0;
103
0217dd19
MC
104 pkt->subs->lenbytes = lenbytes;
105 pkt->subs->packet_len = packet_len;
b7273855
MC
106
107 return 1;
108}
109
ae2f7b37 110int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
b7273855 111{
0217dd19
MC
112 if (pkt->subs == NULL)
113 return 0;
114
115 pkt->subs->flags = flags;
b7273855
MC
116
117 return 1;
118}
119
0217dd19 120
b7273855 121/*
0217dd19
MC
122 * Internal helper function used by WPACKET_close() and WPACKET_finish() to
123 * close a sub-packet and write out its length if necessary.
b7273855 124 */
0217dd19 125static int wpacket_intern_close(WPACKET *pkt)
b7273855
MC
126{
127 size_t packlen;
0217dd19 128 WPACKET_SUB *sub = pkt->subs;
b7273855 129
0217dd19
MC
130 packlen = pkt->written - sub->pwritten;
131 if (packlen == 0
132 && sub->flags & OPENSSL_WPACKET_FLAGS_NON_ZERO_LENGTH)
b7273855
MC
133 return 0;
134
135 if (packlen == 0
0217dd19 136 && sub->flags & OPENSSL_WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
ae2f7b37 137 /* Deallocate any bytes allocated for the length of the WPACKET */
0217dd19
MC
138 if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
139 pkt->written -= sub->lenbytes;
140 pkt->curr -= sub->lenbytes;
b7273855
MC
141 }
142
143 /* Don't write out the packet length */
0217dd19 144 sub->packet_len = NULL;
b7273855
MC
145 }
146
ae2f7b37 147 /* Write out the WPACKET length if needed */
0217dd19 148 if (sub->packet_len != NULL) {
b7273855
MC
149 size_t lenbytes;
150
0217dd19 151 lenbytes = sub->lenbytes;
b7273855
MC
152
153 for (; lenbytes > 0; lenbytes--) {
0217dd19
MC
154 sub->packet_len[lenbytes - 1]
155 = (unsigned char)(packlen & 0xff);
b7273855
MC
156 packlen >>= 8;
157 }
158 if (packlen > 0) {
159 /*
160 * We've extended beyond the max allowed for the number of len bytes
161 */
162 return 0;
163 }
164 }
165
0217dd19
MC
166 pkt->subs = sub->parent;
167 OPENSSL_free(sub);
b7273855
MC
168
169 return 1;
170}
171
172/*
0217dd19
MC
173 * Closes the most recent sub-packet. It also writes out the length of the
174 * packet to the required location (normally the start of the WPACKET) if
175 * appropriate. The top level WPACKET should be closed using WPACKET_finish()
176 * instead of this function.
b7273855 177 */
0217dd19 178int WPACKET_close(WPACKET *pkt)
b7273855 179{
0217dd19 180 if (pkt->subs == NULL || pkt->subs->parent == NULL)
b7273855
MC
181 return 0;
182
0217dd19 183 return wpacket_intern_close(pkt);
b7273855
MC
184}
185
186/*
0217dd19
MC
187 * The same as WPACKET_close() but only for the top most WPACKET. Additionally
188 * frees memory resources for this WPACKET.
b7273855 189 */
0217dd19 190int WPACKET_finish(WPACKET *pkt)
b7273855 191{
0217dd19
MC
192 int ret;
193
194 if (pkt->subs == NULL || pkt->subs->parent != NULL)
195 return 0;
196
197 ret = wpacket_intern_close(pkt);
198
199 /* We free up memory no matter whether |ret| is zero or not */
200 OPENSSL_free(pkt->subs);
201 pkt->subs = NULL;
202 return ret;
b7273855
MC
203}
204
205/*
0217dd19
MC
206 * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated
207 * at the start of the sub-packet to store its length once we know it.
b7273855 208 */
0217dd19 209int WPACKET_start_sub_packet_len(WPACKET *pkt, size_t lenbytes)
b7273855 210{
0217dd19 211 WPACKET_SUB *sub;
b7273855 212
0217dd19 213 if (pkt->subs == NULL)
b7273855
MC
214 return 0;
215
0217dd19
MC
216 sub = OPENSSL_zalloc(sizeof(*sub));
217 if (sub == NULL)
b7273855
MC
218 return 0;
219
0217dd19
MC
220 sub->parent = pkt->subs;
221 pkt->subs = sub;
222 sub->pwritten = pkt->written + lenbytes;
223 sub->lenbytes = lenbytes;
224
225 if (lenbytes == 0) {
226 sub->packet_len = NULL;
227 return 1;
228 }
229
230 if (!WPACKET_allocate_bytes(pkt, lenbytes, &sub->packet_len)) {
231 return 0;
232 }
b7273855
MC
233
234 return 1;
235}
236
0217dd19
MC
237/*
238 * Same as WPACKET_get_sub_packet_len() except no bytes are pre-allocated for
239 * the sub-packet length.
240 */
241int WPACKET_start_sub_packet(WPACKET *pkt)
242{
243 return WPACKET_start_sub_packet_len(pkt, 0);
244}
245
b7273855 246/*
ae2f7b37 247 * Write the value stored in |val| into the WPACKET. The value will consome
b7273855
MC
248 * |bytes| amount of storage. An error will occur if |val| cannot be accommdated
249 * in |bytes| storage, e.g. attempting to write the value 256 into 1 byte will
250 * fail.
251 */
ae2f7b37 252int WPACKET_put_bytes(WPACKET *pkt, unsigned int val, size_t bytes)
b7273855
MC
253{
254 unsigned char *data;
255
256 if (bytes > sizeof(unsigned int)
ae2f7b37 257 || !WPACKET_allocate_bytes(pkt, bytes, &data))
b7273855
MC
258 return 0;
259
260 data += bytes - 1;
261 for (; bytes > 0; bytes--) {
262 *data = (unsigned char)(val & 0xff);
263 data--;
264 val >>= 8;
265 }
266
267 /* Check whether we could fit the value in the assigned number of bytes */
268 if (val > 0)
269 return 0;
270
271 return 1;
272}
273
274/*
ae2f7b37 275 * Set a maximum size that we will not allow the WPACKET to grow beyond. If not
b7273855
MC
276 * set then there is no maximum.
277 */
ae2f7b37 278int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
b7273855 279{
0217dd19 280 pkt->maxsize = maxsize;
b7273855
MC
281
282 return 1;
283}
284
285/*
ae2f7b37 286 * Copy |len| bytes of data from |*src| into the WPACKET.
b7273855 287 */
ae2f7b37 288int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
b7273855
MC
289{
290 unsigned char *dest;
291
292 if (len == 0)
293 return 1;
294
ae2f7b37 295 if (!WPACKET_allocate_bytes(pkt, len, &dest))
b7273855
MC
296 return 0;
297
298 memcpy(dest, src, len);
299
300 return 1;
301}
302
303/*
304 * Return the total number of bytes written so far to the underlying buffer.
ae2f7b37 305 * This might includes bytes written by a parent WPACKET.
b7273855 306 */
ae2f7b37 307int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
b7273855 308{
0217dd19 309 if (pkt->subs == NULL || written == NULL)
b7273855
MC
310 return 0;
311
0217dd19 312 *written = pkt->written;
b7273855
MC
313
314 return 1;
315}
316
317/*
0217dd19 318 * Returns the length of the last sub-packet. This excludes any bytes allocated
b7273855
MC
319 * for the length itself.
320 */
ae2f7b37 321int WPACKET_get_length(WPACKET *pkt, size_t *len)
b7273855 322{
0217dd19 323 if (pkt->subs == NULL || len == NULL)
b7273855
MC
324 return 0;
325
0217dd19 326 *len = pkt->written - pkt->subs->pwritten;
b7273855
MC
327
328 return 1;
329}