Coverage Report

Created: 2026-02-14 07:18

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