VirtualBox

source: vbox/trunk/src/libs/openssl-3.4.1/crypto/packet.c

Last change on this file was 109052, checked in by vboxsync, 3 weeks ago

openssl-3.4.1: Applied our changes, regenerated files, added missing files and functions. This time with a three way merge. ​bugref:10890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1/*
2 * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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 "internal/cryptlib.h"
11#include "internal/packet.h"
12#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
13# include "internal/packet_quic.h"
14#endif
15#include <openssl/err.h>
16
17#define DEFAULT_BUF_SIZE 256
18
19int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
20{
21 if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
22 return 0;
23
24 pkt->written += len;
25 pkt->curr += len;
26 return 1;
27}
28
29int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
30 unsigned char **allocbytes, size_t lenbytes)
31{
32 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
33 || !WPACKET_allocate_bytes(pkt, len, allocbytes)
34 || !WPACKET_close(pkt))
35 return 0;
36
37 return 1;
38}
39
40#define GETBUF(p) (((p)->staticbuf != NULL) \
41 ? (p)->staticbuf \
42 : ((p)->buf != NULL \
43 ? (unsigned char *)(p)->buf->data \
44 : NULL))
45
46int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
47{
48 /* Internal API, so should not fail */
49 if (!ossl_assert(pkt->subs != NULL && len != 0))
50 return 0;
51
52 if (pkt->maxsize - pkt->written < len)
53 return 0;
54
55 if (pkt->buf != NULL && (pkt->buf->length - pkt->written < len)) {
56 size_t newlen;
57 size_t reflen;
58
59 reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
60
61 if (reflen > SIZE_MAX / 2) {
62 newlen = SIZE_MAX;
63 } else {
64 newlen = reflen * 2;
65 if (newlen < DEFAULT_BUF_SIZE)
66 newlen = DEFAULT_BUF_SIZE;
67 }
68 if (BUF_MEM_grow(pkt->buf, newlen) == 0)
69 return 0;
70 }
71 if (allocbytes != NULL) {
72 *allocbytes = WPACKET_get_curr(pkt);
73 if (pkt->endfirst && *allocbytes != NULL)
74 *allocbytes -= len;
75 }
76
77 return 1;
78}
79
80int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
81 unsigned char **allocbytes, size_t lenbytes)
82{
83 if (pkt->endfirst && lenbytes > 0)
84 return 0;
85
86 if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
87 return 0;
88
89 if (*allocbytes != NULL)
90 *allocbytes += lenbytes;
91
92 return 1;
93}
94
95static size_t maxmaxsize(size_t lenbytes)
96{
97 if (lenbytes >= sizeof(size_t) || lenbytes == 0)
98 return SIZE_MAX;
99
100 return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
101}
102
103static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
104{
105 unsigned char *lenchars;
106
107 pkt->curr = 0;
108 pkt->written = 0;
109
110 if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL)
111 return 0;
112
113 if (lenbytes == 0)
114 return 1;
115
116 pkt->subs->pwritten = lenbytes;
117 pkt->subs->lenbytes = lenbytes;
118
119 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
120 OPENSSL_free(pkt->subs);
121 pkt->subs = NULL;
122 return 0;
123 }
124 pkt->subs->packet_len = 0;
125
126 return 1;
127}
128
129int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
130 size_t lenbytes)
131{
132 size_t max = maxmaxsize(lenbytes);
133
134 /* Internal API, so should not fail */
135 if (!ossl_assert(buf != NULL && len > 0))
136 return 0;
137
138 pkt->staticbuf = buf;
139 pkt->buf = NULL;
140 pkt->maxsize = (max < len) ? max : len;
141 pkt->endfirst = 0;
142
143 return wpacket_intern_init_len(pkt, lenbytes);
144}
145
146int WPACKET_init_der(WPACKET *pkt, unsigned char *buf, size_t len)
147{
148 /* Internal API, so should not fail */
149 if (!ossl_assert(buf != NULL && len > 0))
150 return 0;
151
152 pkt->staticbuf = buf;
153 pkt->buf = NULL;
154 pkt->maxsize = len;
155 pkt->endfirst = 1;
156
157 return wpacket_intern_init_len(pkt, 0);
158}
159
160int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
161{
162 /* Internal API, so should not fail */
163 if (!ossl_assert(buf != NULL))
164 return 0;
165
166 pkt->staticbuf = NULL;
167 pkt->buf = buf;
168 pkt->maxsize = maxmaxsize(lenbytes);
169 pkt->endfirst = 0;
170
171 return wpacket_intern_init_len(pkt, lenbytes);
172}
173
174int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
175{
176 return WPACKET_init_len(pkt, buf, 0);
177}
178
179int WPACKET_init_null(WPACKET *pkt, size_t lenbytes)
180{
181 pkt->staticbuf = NULL;
182 pkt->buf = NULL;
183 pkt->maxsize = maxmaxsize(lenbytes);
184 pkt->endfirst = 0;
185
186 return wpacket_intern_init_len(pkt, 0);
187}
188
189int WPACKET_init_null_der(WPACKET *pkt)
190{
191 pkt->staticbuf = NULL;
192 pkt->buf = NULL;
193 pkt->maxsize = SIZE_MAX;
194 pkt->endfirst = 1;
195
196 return wpacket_intern_init_len(pkt, 0);
197}
198
199int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
200{
201 /* Internal API, so should not fail */
202 if (!ossl_assert(pkt->subs != NULL))
203 return 0;
204
205 pkt->subs->flags = flags;
206
207 return 1;
208}
209
210/* Store the |value| of length |len| at location |data| */
211static int put_value(unsigned char *data, uint64_t value, size_t len)
212{
213 if (data == NULL)
214 return 1;
215
216 for (data += len - 1; len > 0; len--) {
217 *data = (unsigned char)(value & 0xff);
218 data--;
219 value >>= 8;
220 }
221
222 /* Check whether we could fit the value in the assigned number of bytes */
223 if (value > 0)
224 return 0;
225
226 return 1;
227}
228
229#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
230static int put_quic_value(unsigned char *data, size_t value, size_t len)
231{
232 if (data == NULL)
233 return 1;
234
235 /* Value too large for field. */
236 if (ossl_quic_vlint_encode_len(value) > len)
237 return 0;
238
239 ossl_quic_vlint_encode_n(data, value, len);
240 return 1;
241}
242#endif
243
244/*
245 * Internal helper function used by WPACKET_close(), WPACKET_finish() and
246 * WPACKET_fill_lengths() to close a sub-packet and write out its length if
247 * necessary. If |doclose| is 0 then it goes through the motions of closing
248 * (i.e. it fills in all the lengths), but doesn't actually close anything.
249 */
250static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
251{
252 size_t packlen = pkt->written - sub->pwritten;
253
254 if (packlen == 0
255 && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
256 return 0;
257
258 if (packlen == 0
259 && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
260 /* We can't handle this case. Return an error */
261 if (!doclose)
262 return 0;
263
264 /* Deallocate any bytes allocated for the length of the WPACKET */
265 if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
266 pkt->written -= sub->lenbytes;
267 pkt->curr -= sub->lenbytes;
268 }
269
270 /* Don't write out the packet length */
271 sub->packet_len = 0;
272 sub->lenbytes = 0;
273 }
274
275 /* Write out the WPACKET length if needed */
276 if (sub->lenbytes > 0) {
277 unsigned char *buf = GETBUF(pkt);
278
279 if (buf != NULL) {
280#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
281 if ((sub->flags & WPACKET_FLAGS_QUIC_VLINT) == 0) {
282 if (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes))
283 return 0;
284 } else {
285 if (!put_quic_value(&buf[sub->packet_len], packlen, sub->lenbytes))
286 return 0;
287 }
288#else
289 if (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes))
290 return 0;
291#endif
292 }
293 } else if (pkt->endfirst && sub->parent != NULL
294 && (packlen != 0
295 || (sub->flags
296 & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) == 0)) {
297 size_t tmplen = packlen;
298 size_t numlenbytes = 1;
299
300 while ((tmplen = tmplen >> 8) > 0)
301 numlenbytes++;
302 if (!WPACKET_put_bytes__(pkt, packlen, numlenbytes))
303 return 0;
304 if (packlen > 0x7f) {
305 numlenbytes |= 0x80;
306 if (!WPACKET_put_bytes_u8(pkt, numlenbytes))
307 return 0;
308 }
309 }
310
311 if (doclose) {
312 pkt->subs = sub->parent;
313 OPENSSL_free(sub);
314 }
315
316 return 1;
317}
318
319int WPACKET_fill_lengths(WPACKET *pkt)
320{
321 WPACKET_SUB *sub;
322
323 if (!ossl_assert(pkt->subs != NULL))
324 return 0;
325
326 for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
327 if (!wpacket_intern_close(pkt, sub, 0))
328 return 0;
329 }
330
331 return 1;
332}
333
334int WPACKET_close(WPACKET *pkt)
335{
336 /*
337 * Internal API, so should not fail - but we do negative testing of this
338 * so no assert (otherwise the tests fail)
339 */
340 if (pkt->subs == NULL || pkt->subs->parent == NULL)
341 return 0;
342
343 return wpacket_intern_close(pkt, pkt->subs, 1);
344}
345
346int WPACKET_finish(WPACKET *pkt)
347{
348 int ret;
349
350 /*
351 * Internal API, so should not fail - but we do negative testing of this
352 * so no assert (otherwise the tests fail)
353 */
354 if (pkt->subs == NULL || pkt->subs->parent != NULL)
355 return 0;
356
357 ret = wpacket_intern_close(pkt, pkt->subs, 1);
358 if (ret) {
359 OPENSSL_free(pkt->subs);
360 pkt->subs = NULL;
361 }
362
363 return ret;
364}
365
366int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
367{
368 WPACKET_SUB *sub;
369 unsigned char *lenchars;
370
371 /* Internal API, so should not fail */
372 if (!ossl_assert(pkt->subs != NULL))
373 return 0;
374
375 /* We don't support lenbytes greater than 0 when doing endfirst writing */
376 if (lenbytes > 0 && pkt->endfirst)
377 return 0;
378
379 if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL)
380 return 0;
381
382 sub->parent = pkt->subs;
383 pkt->subs = sub;
384 sub->pwritten = pkt->written + lenbytes;
385 sub->lenbytes = lenbytes;
386
387 if (lenbytes == 0) {
388 sub->packet_len = 0;
389 return 1;
390 }
391
392 sub->packet_len = pkt->written;
393
394 if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
395 return 0;
396
397 return 1;
398}
399
400int WPACKET_start_sub_packet(WPACKET *pkt)
401{
402 return WPACKET_start_sub_packet_len__(pkt, 0);
403}
404
405int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size)
406{
407 unsigned char *data;
408
409 /* Internal API, so should not fail */
410 if (!ossl_assert(size <= sizeof(uint64_t))
411 || !WPACKET_allocate_bytes(pkt, size, &data)
412 || !put_value(data, val, size))
413 return 0;
414
415 return 1;
416}
417
418int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
419{
420 WPACKET_SUB *sub;
421 size_t lenbytes;
422
423 /* Internal API, so should not fail */
424 if (!ossl_assert(pkt->subs != NULL))
425 return 0;
426
427 /* Find the WPACKET_SUB for the top level */
428 for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
429 continue;
430
431 lenbytes = sub->lenbytes;
432 if (lenbytes == 0)
433 lenbytes = sizeof(pkt->maxsize);
434
435 if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
436 return 0;
437
438 pkt->maxsize = maxsize;
439
440 return 1;
441}
442
443int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
444{
445 unsigned char *dest;
446
447 if (len == 0)
448 return 1;
449
450 if (!WPACKET_allocate_bytes(pkt, len, &dest))
451 return 0;
452
453 if (dest != NULL)
454 memset(dest, ch, len);
455
456 return 1;
457}
458
459int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
460{
461 unsigned char *dest;
462
463 if (len == 0)
464 return 1;
465
466 if (!WPACKET_allocate_bytes(pkt, len, &dest))
467 return 0;
468
469 if (dest != NULL)
470 memcpy(dest, src, len);
471
472 return 1;
473}
474
475int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
476 size_t lenbytes)
477{
478 if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
479 || !WPACKET_memcpy(pkt, src, len)
480 || !WPACKET_close(pkt))
481 return 0;
482
483 return 1;
484}
485
486int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
487{
488 /* Internal API, so should not fail */
489 if (!ossl_assert(written != NULL))
490 return 0;
491
492 *written = pkt->written;
493
494 return 1;
495}
496
497int WPACKET_get_length(WPACKET *pkt, size_t *len)
498{
499 /* Internal API, so should not fail */
500 if (!ossl_assert(pkt->subs != NULL && len != NULL))
501 return 0;
502
503 *len = pkt->written - pkt->subs->pwritten;
504
505 return 1;
506}
507
508unsigned char *WPACKET_get_curr(WPACKET *pkt)
509{
510 unsigned char *buf = GETBUF(pkt);
511
512 if (buf == NULL)
513 return NULL;
514
515 if (pkt->endfirst)
516 return buf + pkt->maxsize - pkt->curr;
517
518 return buf + pkt->curr;
519}
520
521int WPACKET_is_null_buf(WPACKET *pkt)
522{
523 return pkt->buf == NULL && pkt->staticbuf == NULL;
524}
525
526void WPACKET_cleanup(WPACKET *pkt)
527{
528 WPACKET_SUB *sub, *parent;
529
530 for (sub = pkt->subs; sub != NULL; sub = parent) {
531 parent = sub->parent;
532 OPENSSL_free(sub);
533 }
534 pkt->subs = NULL;
535}
536
537#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE
538
539int WPACKET_start_quic_sub_packet_bound(WPACKET *pkt, size_t max_len)
540{
541 size_t enclen = ossl_quic_vlint_encode_len(max_len);
542
543 if (enclen == 0)
544 return 0;
545
546 if (WPACKET_start_sub_packet_len__(pkt, enclen) == 0)
547 return 0;
548
549 pkt->subs->flags |= WPACKET_FLAGS_QUIC_VLINT;
550 return 1;
551}
552
553int WPACKET_start_quic_sub_packet(WPACKET *pkt)
554{
555 /*
556 * Assume no (sub)packet will exceed 4GiB, thus the 8-byte encoding need not
557 * be used.
558 */
559 return WPACKET_start_quic_sub_packet_bound(pkt, OSSL_QUIC_VLINT_4B_MIN);
560}
561
562int WPACKET_quic_sub_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
563{
564 if (!WPACKET_start_quic_sub_packet_bound(pkt, len)
565 || !WPACKET_allocate_bytes(pkt, len, allocbytes)
566 || !WPACKET_close(pkt))
567 return 0;
568
569 return 1;
570}
571
572/*
573 * Write a QUIC variable-length integer to the packet.
574 */
575int WPACKET_quic_write_vlint(WPACKET *pkt, uint64_t v)
576{
577 unsigned char *b = NULL;
578 size_t enclen = ossl_quic_vlint_encode_len(v);
579
580 if (enclen == 0)
581 return 0;
582
583 if (WPACKET_allocate_bytes(pkt, enclen, &b) == 0)
584 return 0;
585
586 ossl_quic_vlint_encode(b, v);
587 return 1;
588}
589
590#endif
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette