Coverage Report

Created: 2024-08-27 12:20

/src/openssl/crypto/packet.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2015-2018 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
#include <openssl/sslerr.h>
13
14
0
#define DEFAULT_BUF_SIZE    256
15
16
int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
17
0
{
18
0
    if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
19
0
        return 0;
20
21
0
    pkt->written += len;
22
0
    pkt->curr += len;
23
0
    return 1;
24
0
}
25
26
int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
27
                                 unsigned char **allocbytes, size_t lenbytes)
28
0
{
29
0
    if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
30
0
            || !WPACKET_allocate_bytes(pkt, len, allocbytes)
31
0
            || !WPACKET_close(pkt))
32
0
        return 0;
33
34
0
    return 1;
35
0
}
36
37
0
#define GETBUF(p)   (((p)->staticbuf != NULL) \
38
0
                     ? (p)->staticbuf \
39
0
                     : ((p)->buf != NULL \
40
0
                        ? (unsigned char *)(p)->buf->data \
41
0
                        : NULL))
42
43
int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
44
0
{
45
    /* Internal API, so should not fail */
46
0
    if (!ossl_assert(pkt->subs != NULL && len != 0))
47
0
        return 0;
48
49
0
    if (pkt->maxsize - pkt->written < len)
50
0
        return 0;
51
52
0
    if (pkt->buf != NULL && (pkt->buf->length - pkt->written < len)) {
53
0
        size_t newlen;
54
0
        size_t reflen;
55
56
0
        reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
57
58
0
        if (reflen > SIZE_MAX / 2) {
59
0
            newlen = SIZE_MAX;
60
0
        } else {
61
0
            newlen = reflen * 2;
62
0
            if (newlen < DEFAULT_BUF_SIZE)
63
0
                newlen = DEFAULT_BUF_SIZE;
64
0
        }
65
0
        if (BUF_MEM_grow(pkt->buf, newlen) == 0)
66
0
            return 0;
67
0
    }
68
0
    if (allocbytes != NULL)
69
0
        *allocbytes = WPACKET_get_curr(pkt);
70
71
0
    return 1;
72
0
}
73
74
int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
75
                                unsigned char **allocbytes, size_t lenbytes)
76
0
{
77
0
    if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
78
0
        return 0;
79
80
0
    if (*allocbytes != NULL)
81
0
        *allocbytes += lenbytes;
82
83
0
    return 1;
84
0
}
85
86
static size_t maxmaxsize(size_t lenbytes)
87
0
{
88
0
    if (lenbytes >= sizeof(size_t) || lenbytes == 0)
89
0
        return SIZE_MAX;
90
91
0
    return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
92
0
}
93
94
static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
95
0
{
96
0
    unsigned char *lenchars;
97
98
0
    pkt->curr = 0;
99
0
    pkt->written = 0;
100
101
0
    if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) {
102
0
        SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE);
103
0
        return 0;
104
0
    }
105
106
0
    if (lenbytes == 0)
107
0
        return 1;
108
109
0
    pkt->subs->pwritten = lenbytes;
110
0
    pkt->subs->lenbytes = lenbytes;
111
112
0
    if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
113
0
        OPENSSL_free(pkt->subs);
114
0
        pkt->subs = NULL;
115
0
        return 0;
116
0
    }
117
0
    pkt->subs->packet_len = 0;
118
119
0
    return 1;
120
0
}
121
122
int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
123
                            size_t lenbytes)
124
0
{
125
0
    size_t max = maxmaxsize(lenbytes);
126
127
    /* Internal API, so should not fail */
128
0
    if (!ossl_assert(buf != NULL && len > 0))
129
0
        return 0;
130
131
0
    pkt->staticbuf = buf;
132
0
    pkt->buf = NULL;
133
0
    pkt->maxsize = (max < len) ? max : len;
134
135
0
    return wpacket_intern_init_len(pkt, lenbytes);
136
0
}
137
138
int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
139
0
{
140
    /* Internal API, so should not fail */
141
0
    if (!ossl_assert(buf != NULL))
142
0
        return 0;
143
144
0
    pkt->staticbuf = NULL;
145
0
    pkt->buf = buf;
146
0
    pkt->maxsize = maxmaxsize(lenbytes);
147
148
0
    return wpacket_intern_init_len(pkt, lenbytes);
149
0
}
150
151
int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
152
0
{
153
0
    return WPACKET_init_len(pkt, buf, 0);
154
0
}
155
156
int WPACKET_init_null(WPACKET *pkt, size_t lenbytes)
157
0
{
158
0
    pkt->staticbuf = NULL;
159
0
    pkt->buf = NULL;
160
0
    pkt->maxsize = maxmaxsize(lenbytes);
161
162
0
    return wpacket_intern_init_len(pkt, 0);
163
0
}
164
165
int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
166
0
{
167
    /* Internal API, so should not fail */
168
0
    if (!ossl_assert(pkt->subs != NULL))
169
0
        return 0;
170
171
0
    pkt->subs->flags = flags;
172
173
0
    return 1;
174
0
}
175
176
/* Store the |value| of length |len| at location |data| */
177
static int put_value(unsigned char *data, size_t value, size_t len)
178
0
{
179
0
    if (data == NULL)
180
0
        return 1;
181
182
0
    for (data += len - 1; len > 0; len--) {
183
0
        *data = (unsigned char)(value & 0xff);
184
0
        data--;
185
0
        value >>= 8;
186
0
    }
187
188
    /* Check whether we could fit the value in the assigned number of bytes */
189
0
    if (value > 0)
190
0
        return 0;
191
192
0
    return 1;
193
0
}
194
195
196
/*
197
 * Internal helper function used by WPACKET_close(), WPACKET_finish() and
198
 * WPACKET_fill_lengths() to close a sub-packet and write out its length if
199
 * necessary. If |doclose| is 0 then it goes through the motions of closing
200
 * (i.e. it fills in all the lengths), but doesn't actually close anything.
201
 */
202
static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
203
0
{
204
0
    size_t packlen = pkt->written - sub->pwritten;
205
206
0
    if (packlen == 0
207
0
            && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
208
0
        return 0;
209
210
0
    if (packlen == 0
211
0
            && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
212
        /* We can't handle this case. Return an error */
213
0
        if (!doclose)
214
0
            return 0;
215
216
        /* Deallocate any bytes allocated for the length of the WPACKET */
217
0
        if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
218
0
            pkt->written -= sub->lenbytes;
219
0
            pkt->curr -= sub->lenbytes;
220
0
        }
221
222
        /* Don't write out the packet length */
223
0
        sub->packet_len = 0;
224
0
        sub->lenbytes = 0;
225
0
    }
226
227
    /* Write out the WPACKET length if needed */
228
0
    if (sub->lenbytes > 0) {
229
0
        unsigned char *buf = GETBUF(pkt);
230
231
0
        if (buf != NULL
232
0
                && !put_value(&buf[sub->packet_len], packlen,
233
0
                              sub->lenbytes))
234
0
            return 0;
235
0
    }
236
237
0
    if (doclose) {
238
0
        pkt->subs = sub->parent;
239
0
        OPENSSL_free(sub);
240
0
    }
241
242
0
    return 1;
243
0
}
244
245
int WPACKET_fill_lengths(WPACKET *pkt)
246
0
{
247
0
    WPACKET_SUB *sub;
248
249
0
    if (!ossl_assert(pkt->subs != NULL))
250
0
        return 0;
251
252
0
    for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
253
0
        if (!wpacket_intern_close(pkt, sub, 0))
254
0
            return 0;
255
0
    }
256
257
0
    return 1;
258
0
}
259
260
int WPACKET_close(WPACKET *pkt)
261
0
{
262
    /*
263
     * Internal API, so should not fail - but we do negative testing of this
264
     * so no assert (otherwise the tests fail)
265
     */
266
0
    if (pkt->subs == NULL || pkt->subs->parent == NULL)
267
0
        return 0;
268
269
0
    return wpacket_intern_close(pkt, pkt->subs, 1);
270
0
}
271
272
int WPACKET_finish(WPACKET *pkt)
273
0
{
274
0
    int ret;
275
276
    /*
277
     * Internal API, so should not fail - but we do negative testing of this
278
     * so no assert (otherwise the tests fail)
279
     */
280
0
    if (pkt->subs == NULL || pkt->subs->parent != NULL)
281
0
        return 0;
282
283
0
    ret = wpacket_intern_close(pkt, pkt->subs, 1);
284
0
    if (ret) {
285
0
        OPENSSL_free(pkt->subs);
286
0
        pkt->subs = NULL;
287
0
    }
288
289
0
    return ret;
290
0
}
291
292
int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
293
0
{
294
0
    WPACKET_SUB *sub;
295
0
    unsigned char *lenchars;
296
297
    /* Internal API, so should not fail */
298
0
    if (!ossl_assert(pkt->subs != NULL))
299
0
        return 0;
300
301
0
    if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) {
302
0
        SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE);
303
0
        return 0;
304
0
    }
305
306
0
    sub->parent = pkt->subs;
307
0
    pkt->subs = sub;
308
0
    sub->pwritten = pkt->written + lenbytes;
309
0
    sub->lenbytes = lenbytes;
310
311
0
    if (lenbytes == 0) {
312
0
        sub->packet_len = 0;
313
0
        return 1;
314
0
    }
315
316
0
    sub->packet_len = pkt->written;
317
318
0
    if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
319
0
        return 0;
320
321
0
    return 1;
322
0
}
323
324
int WPACKET_start_sub_packet(WPACKET *pkt)
325
0
{
326
0
    return WPACKET_start_sub_packet_len__(pkt, 0);
327
0
}
328
329
int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size)
330
0
{
331
0
    unsigned char *data;
332
333
    /* Internal API, so should not fail */
334
0
    if (!ossl_assert(size <= sizeof(unsigned int))
335
0
            || !WPACKET_allocate_bytes(pkt, size, &data)
336
0
            || !put_value(data, val, size))
337
0
        return 0;
338
339
0
    return 1;
340
0
}
341
342
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
343
0
{
344
0
    WPACKET_SUB *sub;
345
0
    size_t lenbytes;
346
347
    /* Internal API, so should not fail */
348
0
    if (!ossl_assert(pkt->subs != NULL))
349
0
        return 0;
350
351
    /* Find the WPACKET_SUB for the top level */
352
0
    for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
353
0
        continue;
354
355
0
    lenbytes = sub->lenbytes;
356
0
    if (lenbytes == 0)
357
0
        lenbytes = sizeof(pkt->maxsize);
358
359
0
    if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
360
0
        return 0;
361
362
0
    pkt->maxsize = maxsize;
363
364
0
    return 1;
365
0
}
366
367
int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
368
0
{
369
0
    unsigned char *dest;
370
371
0
    if (len == 0)
372
0
        return 1;
373
374
0
    if (!WPACKET_allocate_bytes(pkt, len, &dest))
375
0
        return 0;
376
377
0
    if (dest != NULL)
378
0
        memset(dest, ch, len);
379
380
0
    return 1;
381
0
}
382
383
int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
384
0
{
385
0
    unsigned char *dest;
386
387
0
    if (len == 0)
388
0
        return 1;
389
390
0
    if (!WPACKET_allocate_bytes(pkt, len, &dest))
391
0
        return 0;
392
393
0
    if (dest != NULL)
394
0
        memcpy(dest, src, len);
395
396
0
    return 1;
397
0
}
398
399
int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
400
                         size_t lenbytes)
401
0
{
402
0
    if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
403
0
            || !WPACKET_memcpy(pkt, src, len)
404
0
            || !WPACKET_close(pkt))
405
0
        return 0;
406
407
0
    return 1;
408
0
}
409
410
int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
411
0
{
412
    /* Internal API, so should not fail */
413
0
    if (!ossl_assert(written != NULL))
414
0
        return 0;
415
416
0
    *written = pkt->written;
417
418
0
    return 1;
419
0
}
420
421
int WPACKET_get_length(WPACKET *pkt, size_t *len)
422
0
{
423
    /* Internal API, so should not fail */
424
0
    if (!ossl_assert(pkt->subs != NULL && len != NULL))
425
0
        return 0;
426
427
0
    *len = pkt->written - pkt->subs->pwritten;
428
429
0
    return 1;
430
0
}
431
432
unsigned char *WPACKET_get_curr(WPACKET *pkt)
433
0
{
434
0
    unsigned char *buf = GETBUF(pkt);
435
436
0
    if (buf == NULL)
437
0
        return NULL;
438
439
0
    return buf + pkt->curr;
440
0
}
441
442
int WPACKET_is_null_buf(WPACKET *pkt)
443
0
{
444
0
    return pkt->buf == NULL && pkt->staticbuf == NULL;
445
0
}
446
447
void WPACKET_cleanup(WPACKET *pkt)
448
0
{
449
0
    WPACKET_SUB *sub, *parent;
450
451
0
    for (sub = pkt->subs; sub != NULL; sub = parent) {
452
0
        parent = sub->parent;
453
0
        OPENSSL_free(sub);
454
0
    }
455
0
    pkt->subs = NULL;
456
0
}