]> git.ipfire.org Git - thirdparty/openssl.git/blame - ssl/packet.c
Convert CKE construction to use the WPACKET API
[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
c39609aa 10#include <assert.h>
b7273855
MC
11#include "packet_locl.h"
12
871bc59b
MC
13#define DEFAULT_BUF_SIZE 256
14
0217dd19 15int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
b7273855 16{
c39609aa
MC
17 /* Internal API, so should not fail */
18 assert(pkt->subs != NULL && len != 0);
0217dd19
MC
19 if (pkt->subs == NULL || len == 0)
20 return 0;
b7273855 21
6ae4f5e0 22 if (pkt->maxsize - pkt->written < len)
b7273855
MC
23 return 0;
24
0217dd19 25 if (pkt->buf->length - pkt->written < len) {
b7273855
MC
26 size_t newlen;
27
871bc59b 28 if (pkt->buf->length > SIZE_MAX / 2) {
b7273855 29 newlen = SIZE_MAX;
871bc59b 30 } else {
de451856
MC
31 newlen = (pkt->buf->length == 0) ? DEFAULT_BUF_SIZE
32 : pkt->buf->length * 2;
871bc59b 33 }
0217dd19
MC
34 if (BUF_MEM_grow(pkt->buf, newlen) == 0)
35 return 0;
b7273855 36 }
de451856 37 *allocbytes = (unsigned char *)pkt->buf->data + pkt->curr;
c0f9e23c 38 pkt->written += len;
0217dd19 39 pkt->curr += len;
b7273855 40
0217dd19 41 return 1;
b7273855
MC
42}
43
871bc59b
MC
44static size_t maxmaxsize(size_t lenbytes)
45{
46 if (lenbytes >= sizeof(size_t) || lenbytes == 0)
47 return SIZE_MAX;
df065a2b
MC
48
49 return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
871bc59b
MC
50}
51
ae2f7b37 52int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
b7273855 53{
de451856
MC
54 unsigned char *lenchars;
55
c39609aa
MC
56 /* Internal API, so should not fail */
57 assert(buf != NULL);
b7273855
MC
58 if (buf == NULL)
59 return 0;
60
0217dd19 61 pkt->buf = buf;
de451856 62 pkt->curr = 0;
0217dd19 63 pkt->written = 0;
871bc59b 64 pkt->maxsize = maxmaxsize(lenbytes);
b7273855 65
0217dd19
MC
66 pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
67 if (pkt->subs == NULL)
68 return 0;
b7273855 69
0217dd19 70 if (lenbytes == 0)
b7273855 71 return 1;
b7273855 72
0217dd19
MC
73 pkt->subs->pwritten = lenbytes;
74 pkt->subs->lenbytes = lenbytes;
75
de451856 76 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
0217dd19
MC
77 OPENSSL_free(pkt->subs);
78 pkt->subs = NULL;
b7273855
MC
79 return 0;
80 }
de451856 81 pkt->subs->packet_len = lenchars - (unsigned char *)pkt->buf->data;
b7273855
MC
82
83 return 1;
84}
85
ae2f7b37 86int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
b7273855 87{
ae2f7b37 88 return WPACKET_init_len(pkt, buf, 0);
b7273855
MC
89}
90
ae2f7b37 91int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
b7273855 92{
c39609aa
MC
93 /* Internal API, so should not fail */
94 assert(pkt->subs != NULL);
0217dd19
MC
95 if (pkt->subs == NULL)
96 return 0;
97
98 pkt->subs->flags = flags;
b7273855
MC
99
100 return 1;
101}
102
c0f9e23c
MC
103/* Store the |value| of length |len| at location |data| */
104static int put_value(unsigned char *data, size_t value, size_t len)
82657355 105{
c0f9e23c 106 for (data += len - 1; len > 0; len--) {
82657355
MC
107 *data = (unsigned char)(value & 0xff);
108 data--;
109 value >>= 8;
110 }
111
112 /* Check whether we could fit the value in the assigned number of bytes */
113 if (value > 0)
114 return 0;
115
116 return 1;
117}
118
0217dd19 119
b7273855 120/*
0217dd19
MC
121 * Internal helper function used by WPACKET_close() and WPACKET_finish() to
122 * close a sub-packet and write out its length if necessary.
b7273855 123 */
0217dd19 124static int wpacket_intern_close(WPACKET *pkt)
b7273855 125{
0217dd19 126 WPACKET_SUB *sub = pkt->subs;
de451856 127 size_t packlen = pkt->written - sub->pwritten;
b7273855 128
0217dd19 129 if (packlen == 0
c0f9e23c 130 && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
b7273855
MC
131 return 0;
132
133 if (packlen == 0
de451856 134 && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
ae2f7b37 135 /* Deallocate any bytes allocated for the length of the WPACKET */
0217dd19
MC
136 if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
137 pkt->written -= sub->lenbytes;
138 pkt->curr -= sub->lenbytes;
b7273855
MC
139 }
140
141 /* Don't write out the packet length */
de451856
MC
142 sub->packet_len = 0;
143 sub->lenbytes = 0;
b7273855
MC
144 }
145
ae2f7b37 146 /* Write out the WPACKET length if needed */
82657355
MC
147 if (sub->lenbytes > 0
148 && !put_value((unsigned char *)&pkt->buf->data[sub->packet_len],
149 packlen, sub->lenbytes))
b7273855 150 return 0;
b7273855 151
0217dd19
MC
152 pkt->subs = sub->parent;
153 OPENSSL_free(sub);
b7273855
MC
154
155 return 1;
156}
157
0217dd19 158int WPACKET_close(WPACKET *pkt)
b7273855 159{
c39609aa
MC
160 /*
161 * Internal API, so should not fail - but we do negative testing of this
162 * so no assert (otherwise the tests fail)
163 */
0217dd19 164 if (pkt->subs == NULL || pkt->subs->parent == NULL)
b7273855
MC
165 return 0;
166
0217dd19 167 return wpacket_intern_close(pkt);
b7273855
MC
168}
169
0217dd19 170int WPACKET_finish(WPACKET *pkt)
b7273855 171{
0217dd19
MC
172 int ret;
173
c39609aa
MC
174 /*
175 * Internal API, so should not fail - but we do negative testing of this
176 * so no assert (otherwise the tests fail)
177 */
0217dd19
MC
178 if (pkt->subs == NULL || pkt->subs->parent != NULL)
179 return 0;
180
181 ret = wpacket_intern_close(pkt);
871bc59b
MC
182 if (ret) {
183 OPENSSL_free(pkt->subs);
184 pkt->subs = NULL;
185 }
de451856 186
0217dd19 187 return ret;
b7273855
MC
188}
189
0217dd19 190int WPACKET_start_sub_packet_len(WPACKET *pkt, size_t lenbytes)
b7273855 191{
0217dd19 192 WPACKET_SUB *sub;
de451856 193 unsigned char *lenchars;
b7273855 194
c39609aa
MC
195 /* Internal API, so should not fail */
196 assert(pkt->subs != NULL);
0217dd19 197 if (pkt->subs == NULL)
b7273855
MC
198 return 0;
199
0217dd19
MC
200 sub = OPENSSL_zalloc(sizeof(*sub));
201 if (sub == NULL)
b7273855
MC
202 return 0;
203
0217dd19
MC
204 sub->parent = pkt->subs;
205 pkt->subs = sub;
206 sub->pwritten = pkt->written + lenbytes;
207 sub->lenbytes = lenbytes;
208
209 if (lenbytes == 0) {
de451856 210 sub->packet_len = 0;
0217dd19
MC
211 return 1;
212 }
213
de451856 214 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
0217dd19 215 return 0;
de451856 216 sub->packet_len = lenchars - (unsigned char *)pkt->buf->data;
b7273855
MC
217
218 return 1;
219}
220
0217dd19
MC
221int WPACKET_start_sub_packet(WPACKET *pkt)
222{
223 return WPACKET_start_sub_packet_len(pkt, 0);
224}
225
de451856 226int WPACKET_put_bytes(WPACKET *pkt, unsigned int val, size_t size)
b7273855
MC
227{
228 unsigned char *data;
229
c39609aa
MC
230 /* Internal API, so should not fail */
231 assert(size <= sizeof(unsigned int));
c0f9e23c 232
de451856 233 if (size > sizeof(unsigned int)
82657355
MC
234 || !WPACKET_allocate_bytes(pkt, size, &data)
235 || !put_value(data, val, size))
b7273855
MC
236 return 0;
237
238 return 1;
239}
240
ae2f7b37 241int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
b7273855 242{
871bc59b
MC
243 WPACKET_SUB *sub;
244 size_t lenbytes;
245
c39609aa
MC
246 /* Internal API, so should not fail */
247 assert(pkt->subs != NULL);
871bc59b
MC
248 if (pkt->subs == NULL)
249 return 0;
250
251 /* Find the WPACKET_SUB for the top level */
de451856
MC
252 for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
253 continue;
871bc59b
MC
254
255 lenbytes = sub->lenbytes;
256 if (lenbytes == 0)
257 lenbytes = sizeof(pkt->maxsize);
258
259 if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
260 return 0;
261
0217dd19 262 pkt->maxsize = maxsize;
b7273855
MC
263
264 return 1;
265}
266
ae2f7b37 267int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
b7273855
MC
268{
269 unsigned char *dest;
270
271 if (len == 0)
272 return 1;
273
ae2f7b37 274 if (!WPACKET_allocate_bytes(pkt, len, &dest))
b7273855
MC
275 return 0;
276
277 memcpy(dest, src, len);
278
279 return 1;
280}
281
fb790f16
MC
282int WPACKET_sub_memcpy(WPACKET *pkt, const void *src, size_t len, size_t lenbytes)
283{
284 if (!WPACKET_start_sub_packet_len(pkt, lenbytes)
285 || !WPACKET_memcpy(pkt, src, len)
286 || !WPACKET_close(pkt))
287 return 0;
288
289 return 1;
290}
291
ae2f7b37 292int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
b7273855 293{
c39609aa
MC
294 /* Internal API, so should not fail */
295 assert(written != NULL);
871bc59b 296 if (written == NULL)
b7273855
MC
297 return 0;
298
0217dd19 299 *written = pkt->written;
b7273855
MC
300
301 return 1;
302}
303
ae2f7b37 304int WPACKET_get_length(WPACKET *pkt, size_t *len)
b7273855 305{
c39609aa
MC
306 /* Internal API, so should not fail */
307 assert(pkt->subs != NULL && len != NULL);
0217dd19 308 if (pkt->subs == NULL || len == NULL)
b7273855
MC
309 return 0;
310
0217dd19 311 *len = pkt->written - pkt->subs->pwritten;
b7273855
MC
312
313 return 1;
314}
871bc59b 315
871bc59b
MC
316void WPACKET_cleanup(WPACKET *pkt)
317{
318 WPACKET_SUB *sub, *parent;
319
320 for (sub = pkt->subs; sub != NULL; sub = parent) {
321 parent = sub->parent;
322 OPENSSL_free(sub);
323 }
324 pkt->subs = NULL;
325}