Coverage Report

Created: 2026-05-18 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-math-all-8bit/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
            /* 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
#ifdef ESPIPE
234
0
            if (errno == ESPIPE) {
235
0
                WOLFSSL_ERROR_MSG("wolfssl_file_len: file is a pipe");
236
0
                *fileSz = 0;
237
0
                ret = WOLFSSL_BAD_FILETYPE;
238
0
            }
239
0
            else
240
0
#endif
241
0
                ret = WOLFSSL_BAD_FILE;
242
0
        }
243
40
    }
244
    /* Move to end of file. */
245
40
    if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
246
0
        ret = WOLFSSL_BAD_FILE;
247
0
    }
248
40
    if (ret == 0) {
249
        /* Get file offset at end of file and subtract current offset. */
250
40
        sz = (long)XFTELL(fp) - curr;
251
40
        if (sz < 0) {
252
0
            ret = WOLFSSL_BAD_FILE;
253
0
        }
254
40
    }
255
    /* Go back to original offset in file. */
256
40
    if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
257
0
        ret = WOLFSSL_BAD_FILE;
258
0
    }
259
    /* Validate size. */
260
40
    if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) {
261
0
        ret = WOLFSSL_BAD_FILE;
262
0
    }
263
40
    if (ret == 0) {
264
40
        *fileSz = sz;
265
40
    }
266
267
40
    return ret;
268
40
}
269
#endif
270
271
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
272
    !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
273
/* Read all the data from a file.
274
 *
275
 * @param [in]  fp          File pointer to read with.
276
 * @param [out] data        Read data in an allocated buffer.
277
 * @param [out] dataSz      Amount of data read in bytes.
278
 * @return  WOLFSSL_BAD_FILE when reading fails.
279
 * @return  MEMORY_E when memory allocation fails.
280
 * @return  0 on success.
281
 */
282
static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
283
{
284
    int ret = 0;
285
    long sz = 0;
286
    char* mem = NULL;
287
288
    ret = wolfssl_file_len(fp, &sz);
289
    if (ret == 0) {
290
        /* Allocate memory big enough to hold whole file. */
291
        mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
292
        if (mem == NULL) {
293
            ret = MEMORY_E;
294
        }
295
    }
296
    /* Read whole file into new buffer. */
297
    if ((ret == 0) && ((int)XFREAD(mem, 1, (size_t)sz, fp) != sz)) {
298
        ret = WOLFSSL_BAD_FILE;
299
    }
300
    if (ret == 0) {
301
        *dataSz = (int)sz;
302
        *data = mem;
303
        mem = NULL;
304
    }
305
306
    XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
307
    return ret;
308
}
309
#endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
310
        * !NO_FILESYSTEM */
311
312
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
313
314
#ifdef WOLFSSL_SMALL_STACK
315
316
/* Buffer and size with no stack buffer. */
317
typedef struct {
318
    /* Dynamically allocated buffer. */
319
    byte* buffer;
320
    /* Size of buffer in bytes. */
321
    word32 sz;
322
} StaticBuffer;
323
324
/* Initialize static buffer.
325
 *
326
 * @param [in, out] sb  Static buffer.
327
 */
328
static void static_buffer_init(StaticBuffer* sb)
329
40
{
330
40
    sb->buffer = NULL;
331
40
    sb->sz = 0;
332
40
}
333
334
/* Set the size of the buffer.
335
 *
336
 * Can only set size once.
337
 *
338
 * @param [in] sb    Static buffer.
339
 * @param [in] len   Length required.
340
 * @param [in] heap  Dynamic memory allocation hint.
341
 * @param [in] type  Type of dynamic memory.
342
 * @return  0 on success.
343
 * @return  MEMORY_E when dynamic memory allocation fails.
344
 */
345
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
346
    int type)
347
40
{
348
40
    int ret = 0;
349
350
40
    (void)heap;
351
40
    (void)type;
352
353
40
    sb->buffer = (byte*)XMALLOC(len, heap, type);
354
40
    if (sb->buffer == NULL) {
355
0
        ret = MEMORY_E;
356
0
    }
357
40
    else {
358
40
        sb->sz = len;
359
40
    }
360
361
40
    return ret;
362
40
}
363
364
/* Dispose of dynamically allocated buffer.
365
 *
366
 * @param [in] sb    Static buffer.
367
 * @param [in] heap  Dynamic memory allocation hint.
368
 * @param [in] type  Type of dynamic memory.
369
 */
370
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
371
40
{
372
40
    (void)heap;
373
40
    (void)type;
374
40
    XFREE(sb->buffer, heap, type);
375
40
}
376
377
#else
378
379
/* Buffer and size with stack buffer set and option to dynamically allocate. */
380
typedef struct {
381
    /* Stack or heap buffer. */
382
    byte* buffer;
383
    /* Size of buffer in bytes. */
384
    word32 sz;
385
    /* Indicates whether the buffer was dynamically allocated. */
386
    int dyn;
387
} StaticBuffer;
388
389
/* Initialize static buffer.
390
 *
391
 * @param [in, out] sb           Static buffer.
392
 * @param [in]      stackBuffer  Buffer allocated on the stack.
393
 * @param [in]      len          Length of stack buffer.
394
 */
395
static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
396
{
397
    sb->buffer = stackBuffer;
398
    sb->sz = len;
399
    sb->dyn = 0;
400
}
401
402
/* Set the size of the buffer.
403
 *
404
 * Pre: Buffer on the stack set with its size.
405
 * Can only set size once.
406
 *
407
 * @param [in] sb    Static buffer.
408
 * @param [in] len   Length required.
409
 * @param [in] heap  Dynamic memory allocation hint.
410
 * @param [in] type  Type of dynamic memory.
411
 * @return  0 on success.
412
 * @return  MEMORY_E when dynamic memory allocation fails.
413
 */
414
static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
415
    int type)
416
{
417
    int ret = 0;
418
419
    (void)heap;
420
    (void)type;
421
422
    if (len > sb->sz) {
423
        byte* buff = (byte*)XMALLOC(len, heap, type);
424
        if (buff == NULL) {
425
            ret = MEMORY_E;
426
        }
427
        else {
428
            sb->buffer = buff;
429
            sb->sz = len;
430
            sb->dyn = 1;
431
        }
432
    }
433
434
    return ret;
435
}
436
437
/* Dispose of dynamically allocated buffer.
438
 *
439
 * @param [in] sb    Static buffer.
440
 * @param [in] heap  Dynamic memory allocation hint.
441
 * @param [in] type  Type of dynamic memory.
442
 */
443
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
444
{
445
    (void)heap;
446
    (void)type;
447
448
    if (sb->dyn) {
449
        XFREE(sb->buffer, heap, type);
450
    }
451
}
452
453
#endif /* WOLFSSL_SMALL_STACK */
454
455
#ifndef NO_FILESYSTEM
456
457
/* Read all the data from a file into content.
458
 *
459
 * @param [in]      fname    File pointer to read with.
460
 * @param [in, out] content  Read data in an allocated buffer.
461
 * @param [in]      heap     Dynamic memory allocation hint.
462
 * @param [in]      type     Type of dynamic memory.
463
 * @param [out]     size     Amount of data read in bytes.
464
 * @return  0 on success.
465
 * @return  WOLFSSL_BAD_FILE when reading fails.
466
 * @return  MEMORY_E when memory allocation fails.
467
 */
468
static int wolfssl_read_file_static(const char* fname, StaticBuffer* content,
469
    void* heap, int type, long* size)
470
40
{
471
40
    int ret = 0;
472
40
    XFILE file = XBADFILE;
473
40
    long sz = 0;
474
475
    /* Check filename is usable. */
476
40
    if (fname == NULL) {
477
0
        ret = WOLFSSL_BAD_FILE;
478
0
    }
479
    /* Open file for reading. */
480
40
    if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
481
0
        ret = WOLFSSL_BAD_FILE;
482
0
    }
483
40
    if (ret == 0) {
484
        /* Get length of file. */
485
40
        ret = wolfssl_file_len(file, &sz);
486
40
    }
487
40
    if (ret == 0) {
488
        /* Set the buffer to be big enough to hold all data. */
489
40
        ret = static_buffer_set_size(content, (word32)sz, heap, type);
490
40
    }
491
    /* Read data from file. */
492
40
    if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, (size_t)sz, file) !=
493
40
            (size_t)sz)) {
494
0
        ret = WOLFSSL_BAD_FILE;
495
0
    }
496
497
    /* Close file if opened. */
498
40
    if (file != XBADFILE) {
499
40
        XFCLOSE(file);
500
40
    }
501
    /* Return size read. */
502
40
    *size = sz;
503
40
    return ret;
504
40
}
505
506
#endif /* !NO_FILESYSTEM */
507
508
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
509
510
#endif /* !WOLFSSL_SSL_MISC_INCLUDED */
511