Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-normal-math/src/ssl_misc.c
Line
Count
Source
1
/* ssl_misc.c
2
 *
3
 * Copyright (C) 2006-2026 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
            /* Cap total like the direct-file path to avoid int overflow. */
74
            if (ret > MAX_WOLFSSL_FILE_SIZE) {
75
                sz = BUFFER_E;
76
                break;
77
            }
78
            /* Calculate remaining unused memory. */
79
            remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
80
            /* Check for space remaining. */
81
            if (remaining != READ_BIO_FILE_CHUNK) {
82
                /* Update where data is read into. */
83
                p += sz;
84
                /* Maximum possible size is the remaining buffer size. */
85
                sz = remaining;
86
            }
87
            else {
88
                /* No space left for more data to be read - add a chunk. */
89
            #ifdef WOLFSSL_NO_REALLOC
90
                p = (char*)XMALLOC(ret + READ_BIO_FILE_CHUNK, NULL,
91
                    DYNAMIC_TYPE_TMP_BUFFER);
92
                if (p != NULL) {
93
                    XMEMCPY(p, mem, ret);
94
                    XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
95
                    mem = NULL;
96
                }
97
            #else
98
                p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL,
99
                    DYNAMIC_TYPE_TMP_BUFFER);
100
            #endif
101
                if (p == NULL) {
102
                    sz = MEMORY_E;
103
                    break;
104
                }
105
106
                /* Set mem to new pointer. */
107
                mem = p;
108
                /* Set p to where to read in next chunk. */
109
                p += ret;
110
                /* Read in a new chunk. */
111
                sz = READ_BIO_FILE_CHUNK;
112
            }
113
        }
114
        if ((sz < 0) || (ret == 0)) {
115
            /* Dispose of memory on error or no data read. */
116
            XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
117
            mem = NULL;
118
            /* Return error. */
119
            ret = sz;
120
        }
121
    }
122
123
    *data = mem;
124
    return ret;
125
}
126
127
/* Read exactly the required amount into a newly allocated buffer.
128
 *
129
 * @param [in, out] bio   BIO object to read with.
130
 * @param [in       sz    Amount of data to read.
131
 * @param [out]     data  Read data in a new buffer.
132
 * @return  Negative on error.
133
 * @return  Number of bytes read on success.
134
 */
135
static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data)
136
{
137
    int ret = 0;
138
    char* mem;
139
140
    /* Allocate buffer to hold data. */
141
    mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
142
    if (mem == NULL) {
143
        WOLFSSL_ERROR_MSG("Memory allocation error");
144
        ret = MEMORY_E;
145
    }
146
    else if ((ret = wolfSSL_BIO_read(bio, mem, sz)) != sz) {
147
        /* Pending data not read. */
148
        XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
149
        mem = NULL;
150
        ret = MEMORY_E;
151
    }
152
153
    *data = mem;
154
    return ret;
155
}
156
157
/* Read all the data from a BIO.
158
 *
159
 * @param [in, out] bio         BIO object to read with.
160
 * @param [out]     data        Read data in a buffer.
161
 * @param [out]     dataSz      Amount of data read in bytes.
162
 * @param [out]     memAlloced  Indicates whether return buffer was allocated.
163
 * @return  Negative on error.
164
 * @return  0 on success.
165
 */
166
static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz,
167
    int* memAlloced)
168
{
169
    int ret;
170
    int sz;
171
172
    if (bio->type == WOLFSSL_BIO_MEMORY) {
173
        ret = wolfSSL_BIO_get_mem_data(bio, data);
174
        if (ret > 0) {
175
            /* Advance the write index in the memory bio */
176
            WOLFSSL_BIO* mem_bio = bio;
177
            for (; mem_bio != NULL; mem_bio = mem_bio->next) {
178
                if (mem_bio->type == WOLFSSL_BIO_MEMORY)
179
                    break;
180
            }
181
            if (mem_bio == NULL)
182
                mem_bio = bio; /* Default to input */
183
            mem_bio->rdIdx += ret;
184
        }
185
        *memAlloced = 0;
186
    }
187
    /* Get pending or, when a file BIO, get length of file. */
188
    else if ((sz = wolfSSL_BIO_pending(bio)) > 0) {
189
        ret = wolfssl_read_bio_len(bio, sz, data);
190
        if (ret > 0) {
191
            *memAlloced = 1;
192
        }
193
    }
194
    else if (bio->type == WOLFSSL_BIO_FILE) {
195
        ret = wolfssl_read_bio_file(bio, data);
196
        if (ret > 0) {
197
            *memAlloced = 1;
198
        }
199
    }
200
    else {
201
        WOLFSSL_ERROR_MSG("No data read from bio");
202
        *memAlloced = 0;
203
        ret = NOT_COMPILED_IN;
204
    }
205
206
    if (ret >= 0) {
207
        *dataSz = ret;
208
        ret = 0;
209
    }
210
211
    return ret;
212
}
213
#endif /* !NO_BIO */
214
#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
215
216
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
217
     !defined(NO_CERTS)) && !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
218
/* Read all the data from a file.
219
 *
220
 * @param [in]  fp          File pointer to read with.
221
 * @param [out] fileSz      Amount of data remaining in file in bytes.
222
 * @return  WOLFSSL_BAD_FILE on error.
223
 * @return  0 on success.
224
 */
225
static int wolfssl_file_len(XFILE fp, long* fileSz)
226
40
{
227
40
    int ret = 0;
228
40
    long sz = 0;
229
40
    long curr = 0;
230
231
40
    if (fp == XBADFILE) {
232
0
        ret = WOLFSSL_BAD_FILE;
233
0
    }
234
40
    if (ret == 0) {
235
        /* Get file offset at end of file. */
236
40
        curr = (long)XFTELL(fp);
237
40
        if (curr < 0) {
238
0
#ifdef ESPIPE
239
0
            if (errno == ESPIPE) {
240
0
                WOLFSSL_ERROR_MSG("wolfssl_file_len: file is a pipe");
241
0
                *fileSz = 0;
242
0
                ret = WOLFSSL_BAD_FILETYPE;
243
0
            }
244
0
            else
245
0
#endif
246
0
                ret = WOLFSSL_BAD_FILE;
247
0
        }
248
40
    }
249
    /* Move to end of file. */
250
40
    if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
251
0
        ret = WOLFSSL_BAD_FILE;
252
0
    }
253
40
    if (ret == 0) {
254
        /* Get file offset at end of file and subtract current offset. */
255
40
        sz = (long)XFTELL(fp) - curr;
256
40
        if (sz < 0) {
257
0
            ret = WOLFSSL_BAD_FILE;
258
0
        }
259
40
    }
260
    /* Go back to original offset in file. */
261
40
    if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
262
0
        ret = WOLFSSL_BAD_FILE;
263
0
    }
264
    /* Validate size. */
265
40
    if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) {
266
0
        ret = WOLFSSL_BAD_FILE;
267
0
    }
268
40
    if (ret == 0) {
269
40
        *fileSz = sz;
270
40
    }
271
272
40
    return ret;
273
40
}
274
#endif
275
276
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
277
    !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
278
/* Read all the data from a file.
279
 *
280
 * @param [in]  fp          File pointer to read with.
281
 * @param [out] data        Read data in an allocated buffer.
282
 * @param [out] dataSz      Amount of data read in bytes.
283
 * @return  WOLFSSL_BAD_FILE when reading fails.
284
 * @return  MEMORY_E when memory allocation fails.
285
 * @return  0 on success.
286
 */
287
static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
288
{
289
    int ret = 0;
290
    long sz = 0;
291
    char* mem = NULL;
292
293
    ret = wolfssl_file_len(fp, &sz);
294
    if (ret == 0) {
295
        /* Allocate memory big enough to hold whole file. */
296
        mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
297
        if (mem == NULL) {
298
            ret = MEMORY_E;
299
        }
300
    }
301
    /* Read whole file into new buffer. */
302
    if ((ret == 0) && ((int)XFREAD(mem, 1, (size_t)sz, fp) != sz)) {
303
        ret = WOLFSSL_BAD_FILE;
304
    }
305
    if (ret == 0) {
306
        *dataSz = (int)sz;
307
        *data = mem;
308
        mem = NULL;
309
    }
310
311
    XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
312
    return ret;
313
}
314
#endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
315
        * !NO_FILESYSTEM */
316
317
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
318
319
#ifdef WOLFSSL_SMALL_STACK
320
321
/* Buffer and size with no stack buffer. */
322
typedef struct {
323
    /* Dynamically allocated buffer. */
324
    byte* buffer;
325
    /* Size of buffer in bytes. */
326
    word32 sz;
327
} StaticBuffer;
328
329
/* Initialize static buffer.
330
 *
331
 * @param [in, out] sb  Static buffer.
332
 */
333
static void static_buffer_init(StaticBuffer* sb)
334
40
{
335
40
    sb->buffer = NULL;
336
40
    sb->sz = 0;
337
40
}
338
339
/* Set the size of the buffer.
340
 *
341
 * Can only set size once.
342
 *
343
 * @param [in] sb    Static buffer.
344
 * @param [in] len   Length required.
345
 * @param [in] heap  Dynamic memory allocation hint.
346
 * @param [in] type  Type of dynamic memory.
347
 * @return  0 on success.
348
 * @return  MEMORY_E when dynamic memory allocation fails.
349
 */
350
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
351
    int type)
352
40
{
353
40
    int ret = 0;
354
355
40
    (void)heap;
356
40
    (void)type;
357
358
40
    sb->buffer = (byte*)XMALLOC(len, heap, type);
359
40
    if (sb->buffer == NULL) {
360
0
        ret = MEMORY_E;
361
0
    }
362
40
    else {
363
40
        sb->sz = len;
364
40
    }
365
366
40
    return ret;
367
40
}
368
369
/* Dispose of dynamically allocated buffer.
370
 *
371
 * @param [in] sb    Static buffer.
372
 * @param [in] heap  Dynamic memory allocation hint.
373
 * @param [in] type  Type of dynamic memory.
374
 */
375
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
376
40
{
377
40
    (void)heap;
378
40
    (void)type;
379
40
    XFREE(sb->buffer, heap, type);
380
40
}
381
382
#else
383
384
/* Buffer and size with stack buffer set and option to dynamically allocate. */
385
typedef struct {
386
    /* Stack or heap buffer. */
387
    byte* buffer;
388
    /* Size of buffer in bytes. */
389
    word32 sz;
390
    /* Indicates whether the buffer was dynamically allocated. */
391
    int dyn;
392
} StaticBuffer;
393
394
/* Initialize static buffer.
395
 *
396
 * @param [in, out] sb           Static buffer.
397
 * @param [in]      stackBuffer  Buffer allocated on the stack.
398
 * @param [in]      len          Length of stack buffer.
399
 */
400
static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
401
{
402
    sb->buffer = stackBuffer;
403
    sb->sz = len;
404
    sb->dyn = 0;
405
}
406
407
/* Set the size of the buffer.
408
 *
409
 * Pre: Buffer on the stack set with its size.
410
 * Can only set size once.
411
 *
412
 * @param [in] sb    Static buffer.
413
 * @param [in] len   Length required.
414
 * @param [in] heap  Dynamic memory allocation hint.
415
 * @param [in] type  Type of dynamic memory.
416
 * @return  0 on success.
417
 * @return  MEMORY_E when dynamic memory allocation fails.
418
 */
419
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
420
    int type)
421
{
422
    int ret = 0;
423
424
    (void)heap;
425
    (void)type;
426
427
    if (len > sb->sz) {
428
        byte* buff = (byte*)XMALLOC(len, heap, type);
429
        if (buff == NULL) {
430
            ret = MEMORY_E;
431
        }
432
        else {
433
            sb->buffer = buff;
434
            sb->sz = len;
435
            sb->dyn = 1;
436
        }
437
    }
438
439
    return ret;
440
}
441
442
/* Dispose of dynamically allocated buffer.
443
 *
444
 * @param [in] sb    Static buffer.
445
 * @param [in] heap  Dynamic memory allocation hint.
446
 * @param [in] type  Type of dynamic memory.
447
 */
448
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
449
{
450
    (void)heap;
451
    (void)type;
452
453
    if (sb->dyn) {
454
        XFREE(sb->buffer, heap, type);
455
    }
456
}
457
458
#endif /* WOLFSSL_SMALL_STACK */
459
460
#ifndef NO_FILESYSTEM
461
462
/* Read all the data from a file into content.
463
 *
464
 * @param [in]      fname    File pointer to read with.
465
 * @param [in, out] content  Read data in an allocated buffer.
466
 * @param [in]      heap     Dynamic memory allocation hint.
467
 * @param [in]      type     Type of dynamic memory.
468
 * @param [out]     size     Amount of data read in bytes.
469
 * @return  0 on success.
470
 * @return  WOLFSSL_BAD_FILE when reading fails.
471
 * @return  MEMORY_E when memory allocation fails.
472
 */
473
static int wolfssl_read_file_static(const char* fname, StaticBuffer* content,
474
    void* heap, int type, long* size)
475
40
{
476
40
    int ret = 0;
477
40
    XFILE file = XBADFILE;
478
40
    long sz = 0;
479
480
    /* Check filename is usable. */
481
40
    if (fname == NULL) {
482
0
        ret = WOLFSSL_BAD_FILE;
483
0
    }
484
    /* Open file for reading. */
485
40
    if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
486
0
        ret = WOLFSSL_BAD_FILE;
487
0
    }
488
40
    if (ret == 0) {
489
        /* Get length of file. */
490
40
        ret = wolfssl_file_len(file, &sz);
491
40
    }
492
40
    if (ret == 0) {
493
        /* Set the buffer to be big enough to hold all data. */
494
40
        ret = static_buffer_set_size(content, (word32)sz, heap, type);
495
40
    }
496
    /* Read data from file. */
497
40
    if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, (size_t)sz, file) !=
498
40
            (size_t)sz)) {
499
0
        ret = WOLFSSL_BAD_FILE;
500
0
    }
501
502
    /* Close file if opened. */
503
40
    if (file != XBADFILE) {
504
40
        XFCLOSE(file);
505
40
    }
506
    /* Return size read. */
507
40
    *size = sz;
508
40
    return ret;
509
40
}
510
511
#endif /* !NO_FILESYSTEM */
512
513
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
514
515
#endif /* !WOLFSSL_SSL_MISC_INCLUDED */
516