Coverage Report

Created: 2025-07-23 06:59

/src/wolfssl-heapmath/src/ssl_misc.c
Line
Count
Source (jump to first uncovered line)
1
/* ssl_misc.c
2
 *
3
 * Copyright (C) 2006-2025 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#if !defined(WOLFSSL_SSL_MISC_INCLUDED)
25
    #ifndef WOLFSSL_IGNORE_FILE_WARN
26
        #warning ssl_misc.c does not need to be compiled separately from ssl.c
27
    #endif
28
#else
29
30
#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
31
#ifndef NO_BIO
32
33
/* Amount of memory to allocate/add. */
34
#define READ_BIO_FILE_CHUNK     128
35
36
/* Read a file in chunks.
37
 *
38
 * Allocates a chunk and reads into it until it is full.
39
 *
40
 * @param [in, out] bio   BIO object to read with.
41
 * @param [out]     data  Read data in a new buffer.
42
 * @return  Negative on error.
43
 * @return  Number of bytes read on success.
44
 */
45
static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data)
46
{
47
    int ret = 0;
48
    char* mem;
49
    char* p;
50
51
    /* Allocate buffer to hold a chunk of data. */
52
    mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, NULL, DYNAMIC_TYPE_TMP_BUFFER);
53
    if (mem == NULL) {
54
        WOLFSSL_ERROR_MSG("Memory allocation error");
55
        ret = MEMORY_E;
56
    }
57
58
    if (ret == 0) {
59
        int sz;
60
61
        /* ret is the number of bytes read and is zero. */
62
63
        /* p is where to read in next chunk. */
64
        p = mem;
65
        /* Memory available to read into is one chunk. */
66
        sz = READ_BIO_FILE_CHUNK;
67
        /* Keep reading in chunks until no more or an error. */
68
        while ((sz = wolfSSL_BIO_read(bio, p, sz)) > 0) {
69
            int remaining;
70
71
            /* Update total read. */
72
            ret += sz;
73
            /* Calculate remaining unused memory. */
74
            remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
75
            /* Check for space remaining. */
76
            if (remaining != READ_BIO_FILE_CHUNK) {
77
                /* Update where data is read into. */
78
                p += sz;
79
                /* Maximum possible size is the remaining buffer size. */
80
                sz = remaining;
81
            }
82
            else {
83
                /* No space left for more data to be read - add a chunk. */
84
                p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL,
85
                    DYNAMIC_TYPE_TMP_BUFFER);
86
                if (p == NULL) {
87
                    sz = MEMORY_E;
88
                    break;
89
                }
90
91
                /* Set mem to new pointer. */
92
                mem = p;
93
                /* Set p to where to read in next chunk. */
94
                p += ret;
95
                /* Read in a new chunk. */
96
                sz = READ_BIO_FILE_CHUNK;
97
            }
98
        }
99
        if ((sz < 0) || (ret == 0)) {
100
            /* Dispose of memory on error or no data read. */
101
            XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
102
            mem = NULL;
103
            /* Return error. */
104
            ret = sz;
105
        }
106
    }
107
108
    *data = mem;
109
    return ret;
110
}
111
112
/* Read exactly the required amount into a newly allocated buffer.
113
 *
114
 * @param [in, out] bio   BIO object to read with.
115
 * @param [in       sz    Amount of data to read.
116
 * @param [out]     data  Read data in a new buffer.
117
 * @return  Negative on error.
118
 * @return  Number of bytes read on success.
119
 */
120
static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data)
121
{
122
    int ret = 0;
123
    char* mem;
124
125
    /* Allocate buffer to hold data. */
126
    mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
127
    if (mem == NULL) {
128
        WOLFSSL_ERROR_MSG("Memory allocation error");
129
        ret = MEMORY_E;
130
    }
131
    else if ((ret = wolfSSL_BIO_read(bio, mem, sz)) != sz) {
132
        /* Pending data not read. */
133
        XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
134
        mem = NULL;
135
        ret = MEMORY_E;
136
    }
137
138
    *data = mem;
139
    return ret;
140
}
141
142
/* Read all the data from a BIO.
143
 *
144
 * @param [in, out] bio         BIO object to read with.
145
 * @param [out]     data        Read data in a buffer.
146
 * @param [out]     dataSz      Amount of data read in bytes.
147
 * @param [out]     memAlloced  Indicates whether return buffer was allocated.
148
 * @return  Negative on error.
149
 * @return  0 on success.
150
 */
151
static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz,
152
    int* memAlloced)
153
{
154
    int ret;
155
    int sz;
156
157
    if (bio->type == WOLFSSL_BIO_MEMORY) {
158
        ret = wolfSSL_BIO_get_mem_data(bio, data);
159
        if (ret > 0) {
160
            /* Advance the write index in the memory bio */
161
            WOLFSSL_BIO* mem_bio = bio;
162
            for (; mem_bio != NULL; mem_bio = mem_bio->next) {
163
                if (mem_bio->type == WOLFSSL_BIO_MEMORY)
164
                    break;
165
            }
166
            if (mem_bio == NULL)
167
                mem_bio = bio; /* Default to input */
168
            mem_bio->rdIdx += ret;
169
        }
170
        *memAlloced = 0;
171
    }
172
    /* Get pending or, when a file BIO, get length of file. */
173
    else if ((sz = wolfSSL_BIO_pending(bio)) > 0) {
174
        ret = wolfssl_read_bio_len(bio, sz, data);
175
        if (ret > 0) {
176
            *memAlloced = 1;
177
        }
178
    }
179
    else if (bio->type == WOLFSSL_BIO_FILE) {
180
        ret = wolfssl_read_bio_file(bio, data);
181
        if (ret > 0) {
182
            *memAlloced = 1;
183
        }
184
    }
185
    else {
186
        WOLFSSL_ERROR_MSG("No data read from bio");
187
        *memAlloced = 0;
188
        ret = NOT_COMPILED_IN;
189
    }
190
191
    if (ret >= 0) {
192
        *dataSz = ret;
193
        ret = 0;
194
    }
195
196
    return ret;
197
}
198
#endif /* !NO_BIO */
199
#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
200
201
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
202
     !defined(NO_CERTS)) && !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
203
/* Read all the data from a file.
204
 *
205
 * @param [in]  fp          File pointer to read with.
206
 * @param [out] fileSz      Amount of data remaining in file in bytes.
207
 * @return  WOLFSSL_BAD_FILE on error.
208
 * @return  0 on success.
209
 */
210
static int wolfssl_file_len(XFILE fp, long* fileSz)
211
40
{
212
40
    int ret = 0;
213
40
    long sz = 0;
214
40
    long curr = 0;
215
216
40
    if (fp == XBADFILE) {
217
0
        ret = WOLFSSL_BAD_FILE;
218
0
    }
219
40
    if (ret == 0) {
220
        /* Get file offset at end of file. */
221
40
        curr = (long)XFTELL(fp);
222
40
        if (curr < 0) {
223
0
            ret = WOLFSSL_BAD_FILE;
224
0
        }
225
40
    }
226
    /* Move to end of file. */
227
40
    if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
228
0
        ret = WOLFSSL_BAD_FILE;
229
0
    }
230
40
    if (ret == 0) {
231
        /* Get file offset at end of file and subtract current offset. */
232
40
        sz = (long)XFTELL(fp) - curr;
233
40
        if (sz < 0) {
234
0
            ret = WOLFSSL_BAD_FILE;
235
0
        }
236
40
    }
237
    /* Go back to original offset in file. */
238
40
    if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
239
0
        ret = WOLFSSL_BAD_FILE;
240
0
    }
241
    /* Validate size. */
242
40
    if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) {
243
0
        ret = WOLFSSL_BAD_FILE;
244
0
    }
245
40
    if (ret == 0) {
246
40
        *fileSz = sz;
247
40
    }
248
249
40
    return ret;
250
40
}
251
#endif
252
253
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
254
    !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
255
/* Read all the data from a file.
256
 *
257
 * @param [in]  fp          File pointer to read with.
258
 * @param [out] data        Read data in an allocated buffer.
259
 * @param [out] dataSz      Amount of data read in bytes.
260
 * @return  WOLFSSL_BAD_FILE when reading fails.
261
 * @return  MEMORY_E when memory allocation fails.
262
 * @return  0 on success.
263
 */
264
static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
265
{
266
    int ret = 0;
267
    long sz = 0;
268
    char* mem = NULL;
269
270
    ret = wolfssl_file_len(fp, &sz);
271
    if (ret == 0) {
272
        /* Allocate memory big enough to hold whole file. */
273
        mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
274
        if (mem == NULL) {
275
            ret = MEMORY_E;
276
        }
277
    }
278
    /* Read whole file into new buffer. */
279
    if ((ret == 0) && ((int)XFREAD(mem, 1, (size_t)sz, fp) != sz)) {
280
        ret = WOLFSSL_BAD_FILE;
281
    }
282
    if (ret == 0) {
283
        *dataSz = (int)sz;
284
        *data = mem;
285
        mem = NULL;
286
    }
287
288
    XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
289
    return ret;
290
}
291
#endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
292
        * !NO_FILESYSTEM */
293
294
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
295
296
#ifdef WOLFSSL_SMALL_STACK
297
298
/* Buffer and size with no stack buffer. */
299
typedef struct {
300
    /* Dynamically allocated buffer. */
301
    byte* buffer;
302
    /* Size of buffer in bytes. */
303
    word32 sz;
304
} StaticBuffer;
305
306
/* Initialize static buffer.
307
 *
308
 * @param [in, out] sb  Static buffer.
309
 */
310
static void static_buffer_init(StaticBuffer* sb)
311
40
{
312
40
    sb->buffer = NULL;
313
40
    sb->sz = 0;
314
40
}
315
316
/* Set the size of the buffer.
317
 *
318
 * Can only set size once.
319
 *
320
 * @param [in] sb    Static buffer.
321
 * @param [in] len   Length required.
322
 * @param [in] heap  Dynamic memory allocation hint.
323
 * @param [in] type  Type of dynamic memory.
324
 * @return  0 on success.
325
 * @return  MEMORY_E when dynamic memory allocation fails.
326
 */
327
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
328
    int type)
329
40
{
330
40
    int ret = 0;
331
332
40
    (void)heap;
333
40
    (void)type;
334
335
40
    sb->buffer = (byte*)XMALLOC(len, heap, type);
336
40
    if (sb->buffer == NULL) {
337
0
        ret = MEMORY_E;
338
0
    }
339
40
    else {
340
40
        sb->sz = len;
341
40
    }
342
343
40
    return ret;
344
40
}
345
346
/* Dispose of dynamically allocated buffer.
347
 *
348
 * @param [in] sb    Static buffer.
349
 * @param [in] heap  Dynamic memory allocation hint.
350
 * @param [in] type  Type of dynamic memory.
351
 */
352
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
353
40
{
354
40
    (void)heap;
355
40
    (void)type;
356
40
    XFREE(sb->buffer, heap, type);
357
40
}
358
359
#else
360
361
/* Buffer and size with stack buffer set and option to dynamically allocate. */
362
typedef struct {
363
    /* Stack or heap buffer. */
364
    byte* buffer;
365
    /* Size of buffer in bytes. */
366
    word32 sz;
367
    /* Indicates whether the buffer was dynamically allocated. */
368
    int dyn;
369
} StaticBuffer;
370
371
/* Initialize static buffer.
372
 *
373
 * @param [in, out] sb           Static buffer.
374
 * @param [in]      stackBuffer  Buffer allocated on the stack.
375
 * @param [in]      len          Length of stack buffer.
376
 */
377
static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
378
{
379
    sb->buffer = stackBuffer;
380
    sb->sz = len;
381
    sb->dyn = 0;
382
}
383
384
/* Set the size of the buffer.
385
 *
386
 * Pre: Buffer on the stack set with its size.
387
 * Can only set size once.
388
 *
389
 * @param [in] sb    Static buffer.
390
 * @param [in] len   Length required.
391
 * @param [in] heap  Dynamic memory allocation hint.
392
 * @param [in] type  Type of dynamic memory.
393
 * @return  0 on success.
394
 * @return  MEMORY_E when dynamic memory allocation fails.
395
 */
396
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
397
    int type)
398
{
399
    int ret = 0;
400
401
    (void)heap;
402
    (void)type;
403
404
    if (len > sb->sz) {
405
        byte* buff = (byte*)XMALLOC(len, heap, type);
406
        if (buff == NULL) {
407
            ret = MEMORY_E;
408
        }
409
        else {
410
            sb->buffer = buff;
411
            sb->sz = len;
412
            sb->dyn = 1;
413
        }
414
    }
415
416
    return ret;
417
}
418
419
/* Dispose of dynamically allocated buffer.
420
 *
421
 * @param [in] sb    Static buffer.
422
 * @param [in] heap  Dynamic memory allocation hint.
423
 * @param [in] type  Type of dynamic memory.
424
 */
425
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
426
{
427
    (void)heap;
428
    (void)type;
429
430
    if (sb->dyn) {
431
        XFREE(sb->buffer, heap, type);
432
    }
433
}
434
435
#endif /* WOLFSSL_SMALL_STACK */
436
437
#ifndef NO_FILESYSTEM
438
439
/* Read all the data from a file into content.
440
 *
441
 * @param [in]      fname    File pointer to read with.
442
 * @param [in, out] content  Read data in an allocated buffer.
443
 * @param [in]      heap     Dynamic memory allocation hint.
444
 * @param [in]      type     Type of dynamic memory.
445
 * @param [out]     size     Amount of data read in bytes.
446
 * @return  0 on success.
447
 * @return  WOLFSSL_BAD_FILE when reading fails.
448
 * @return  MEMORY_E when memory allocation fails.
449
 */
450
static int wolfssl_read_file_static(const char* fname, StaticBuffer* content,
451
    void* heap, int type, long* size)
452
40
{
453
40
    int ret = 0;
454
40
    XFILE file = XBADFILE;
455
40
    long sz = 0;
456
457
    /* Check filename is usable. */
458
40
    if (fname == NULL) {
459
0
        ret = WOLFSSL_BAD_FILE;
460
0
    }
461
    /* Open file for reading. */
462
40
    if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
463
0
        ret = WOLFSSL_BAD_FILE;
464
0
    }
465
40
    if (ret == 0) {
466
        /* Get length of file. */
467
40
        ret = wolfssl_file_len(file, &sz);
468
40
    }
469
40
    if (ret == 0) {
470
        /* Set the buffer to be big enough to hold all data. */
471
40
        ret = static_buffer_set_size(content, (word32)sz, heap, type);
472
40
    }
473
    /* Read data from file. */
474
40
    if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, (size_t)sz, file) !=
475
40
            (size_t)sz)) {
476
0
        ret = WOLFSSL_BAD_FILE;
477
0
    }
478
479
    /* Close file if opened. */
480
40
    if (file != XBADFILE) {
481
40
        XFCLOSE(file);
482
40
    }
483
    /* Return size read. */
484
40
    *size = sz;
485
40
    return ret;
486
40
}
487
488
#endif /* !NO_FILESYSTEM */
489
490
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
491
492
#endif /* !WOLFSSL_SSL_MISC_INCLUDED */
493