Coverage Report

Created: 2026-02-14 07:20

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