Coverage Report

Created: 2025-06-13 06:58

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