123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- /* ssl_misc.c
- *
- * Copyright (C) 2006-2023 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/wolfcrypt/types.h>
- #include <wolfssl/wolfcrypt/error-crypt.h>
- #if !defined(WOLFSSL_SSL_MISC_INCLUDED)
- #ifndef WOLFSSL_IGNORE_FILE_WARN
- #warning ssl_misc.c does not need to be compiled separately from ssl.c
- #endif
- #else
- #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
- #ifndef NO_BIO
- #ifdef WOLFSSL_NO_FSEEK
- /* Amount of memory to allocate/add. */
- #define READ_BIO_FILE_CHUNK 128
- /* Read a file in chunks.
- *
- * Allocates a chunk and reads into it until it is full.
- *
- * @param [in, out] bio BIO object to read with.
- * @param [out] data Read data in a new buffer.
- * @return Negative on error.
- * @return Number of bytes read on success.
- */
- static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data)
- {
- int ret = 0;
- char* mem;
- char* p;
- /* Allocate buffer to hold a chunk of data. */
- mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation error");
- ret = MEMORY_E;
- }
- if (ret == 0) {
- int sz;
- /* ret is the number of bytes read and is zero. */
- /* p is where to read in next chunk. */
- p = mem;
- /* Memory available to read into is one chunk. */
- sz = READ_BIO_FILE_CHUNK;
- /* Keep reading in chunks until no more or an error. */
- while ((sz = wolfSSL_BIO_read(bio, p, sz)) > 0) {
- int remaining;
- /* Update total read. */
- ret += sz;
- /* Calculate remaining unused memory. */
- remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
- /* Check for space remaining. */
- if (remaining != READ_BIO_FILE_CHUNK) {
- /* Update where data is read into. */
- p += sz;
- /* Maximum possible size is the remaining buffer size. */
- sz = remaining;
- }
- else {
- /* No space left for more data to be read - add a chunk. */
- p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (p == NULL) {
- sz = MEMORY_E;
- break;
- }
- /* Set mem to new pointer. */
- mem = p;
- /* Set p to where to read in next chunk. */
- p += ret;
- /* Read in a new chunk. */
- sz = READ_BIO_FILE_CHUNK;
- }
- }
- if ((sz < 0) || (ret == 0)) {
- /* Dispose of memory on error or no data read. */
- XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- mem = NULL;
- /* Return error. */
- ret = sz;
- }
- }
- *data = mem;
- return ret;
- }
- #endif
- /* Read exactly the required amount into a newly allocated buffer.
- *
- * @param [in, out] bio BIO object to read with.
- * @param [in sz Amount of data to read.
- * @param [out] data Read data in a new buffer.
- * @return Negative on error.
- * @return Number of bytes read on success.
- */
- static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data)
- {
- int ret = 0;
- char* mem;
- /* Allocate buffer to hold data. */
- mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation error");
- ret = MEMORY_E;
- }
- else if ((ret = wolfSSL_BIO_read(bio, mem, sz)) != sz) {
- /* Pending data not read. */
- XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- mem = NULL;
- ret = MEMORY_E;
- }
- *data = mem;
- return ret;
- }
- /* Read all the data from a BIO.
- *
- * @param [in, out] bio BIO object to read with.
- * @param [out] data Read data in a buffer.
- * @param [out] dataSz Amount of data read in bytes.
- * @param [out] memAlloced Indicates whether return buffer was allocated.
- * @return Negative on error.
- * @return 0 on success.
- */
- static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz,
- int* memAlloced)
- {
- int ret;
- int sz;
- if (bio->type == WOLFSSL_BIO_MEMORY) {
- ret = wolfSSL_BIO_get_mem_data(bio, data);
- if (ret > 0) {
- bio->rdIdx += ret;
- }
- *memAlloced = 0;
- }
- #ifndef WOLFSSL_NO_FSEEK
- /* Get pending or, when a file BIO, get length of file. */
- else if ((sz = wolfSSL_BIO_get_len(bio)) > 0) {
- ret = wolfssl_read_bio_len(bio, sz, data);
- if (ret > 0) {
- *memAlloced = 1;
- }
- }
- #else
- else if ((sz = wolfSSL_BIO_pending(bio)) > 0) {
- ret = wolfssl_read_bio_len(bio, sz, data);
- if (ret > 0) {
- *memAlloced = 1;
- }
- }
- else if (bio->type == WOLFSSL_BIO_FILE) {
- ret = wolfssl_read_bio_file(bio, data);
- if (ret > 0) {
- *memAlloced = 1;
- }
- }
- #endif
- else {
- WOLFSSL_ERROR_MSG("No data read from bio");
- *memAlloced = 0;
- ret = NOT_COMPILED_IN;
- }
- if (ret >= 0) {
- *dataSz = ret;
- ret = 0;
- }
- return ret;
- }
- #endif /* !NO_BIO */
- #endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
- #if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
- !defined(NO_CERTS)) && !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
- /* Read all the data from a file.
- *
- * @param [in] fp File pointer to read with.
- * @param [out] fileSz Amount of data remaining in file in bytes.
- * @return WOLFSSL_BAD_FILE on error.
- * @return 0 on success.
- */
- static int wolfssl_file_len(XFILE fp, long* fileSz)
- {
- int ret = 0;
- long sz = 0;
- long curr = 0;
- if (fp == XBADFILE) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- /* Get file offset at end of file. */
- curr = (long)XFTELL(fp);
- if (curr < 0) {
- ret = WOLFSSL_BAD_FILE;
- }
- }
- /* Move to end of file. */
- if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- /* Get file offset at end of file and subtract current offset. */
- sz = (long)XFTELL(fp) - curr;
- if (sz < 0) {
- ret = WOLFSSL_BAD_FILE;
- }
- }
- /* Go back to original offset in file. */
- if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
- ret = WOLFSSL_BAD_FILE;
- }
- /* Validate size. */
- if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- *fileSz = sz;
- }
- return ret;
- }
- #endif
- #if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
- !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
- /* Read all the data from a file.
- *
- * @param [in] fp File pointer to read with.
- * @param [out] data Read data in an allocated buffer.
- * @param [out] dataSz Amount of data read in bytes.
- * @return WOLFSSL_BAD_FILE when reading fails.
- * @return MEMORY_E when memory allocation fails.
- * @return 0 on success.
- */
- static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
- {
- int ret = 0;
- long sz = 0;
- char* mem = NULL;
- ret = wolfssl_file_len(fp, &sz);
- if (ret == 0) {
- /* Allocate memory big enough to hold whole file. */
- mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- ret = MEMORY_E;
- }
- }
- /* Read whole file into new buffer. */
- if ((ret == 0) && ((int)XFREAD(mem, 1, (size_t)sz, fp) != sz)) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- *dataSz = (int)sz;
- *data = mem;
- mem = NULL;
- }
- XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- #endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
- * !NO_FILESYSTEM */
- #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
- #ifdef WOLFSSL_SMALL_STACK
- /* Buffer and size with no stack buffer. */
- typedef struct {
- /* Dynamically allocated buffer. */
- byte* buffer;
- /* Size of buffer in bytes. */
- word32 sz;
- } StaticBuffer;
- /* Initialize static buffer.
- *
- * @param [in, out] sb Static buffer.
- */
- static void static_buffer_init(StaticBuffer* sb)
- {
- sb->buffer = NULL;
- sb->sz = 0;
- }
- /* Set the size of the buffer.
- *
- * Can only set size once.
- *
- * @param [in] sb Static buffer.
- * @param [in] len Length required.
- * @param [in] heap Dynamic memory allocation hint.
- * @param [in] type Type of dynamic memory.
- * @return 0 on success.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
- int type)
- {
- int ret = 0;
- (void)heap;
- (void)type;
- sb->buffer = (byte*)XMALLOC(len, heap, type);
- if (sb->buffer == NULL) {
- ret = MEMORY_E;
- }
- else {
- sb->sz = len;
- }
- return ret;
- }
- /* Dispose of dynamically allocated buffer.
- *
- * @param [in] sb Static buffer.
- * @param [in] heap Dynamic memory allocation hint.
- * @param [in] type Type of dynamic memory.
- */
- static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
- {
- (void)heap;
- (void)type;
- XFREE(sb->buffer, heap, type);
- }
- #else
- /* Buffer and size with stack buffer set and option to dynamically allocate. */
- typedef struct {
- /* Stack or heap buffer. */
- byte* buffer;
- /* Size of buffer in bytes. */
- word32 sz;
- /* Indicates whether the buffer was dynamically allocated. */
- int dyn;
- } StaticBuffer;
- /* Initialize static buffer.
- *
- * @param [in, out] sb Static buffer.
- * @param [in] stackBuffer Buffer allocated on the stack.
- * @param [in] len Length of stack buffer.
- */
- static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
- {
- sb->buffer = stackBuffer;
- sb->sz = len;
- sb->dyn = 0;
- }
- /* Set the size of the buffer.
- *
- * Pre: Buffer on the stack set with its size.
- * Can only set size once.
- *
- * @param [in] sb Static buffer.
- * @param [in] len Length required.
- * @param [in] heap Dynamic memory allocation hint.
- * @param [in] type Type of dynamic memory.
- * @return 0 on success.
- * @return MEMORY_E when dynamic memory allocation fails.
- */
- static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
- int type)
- {
- int ret = 0;
- (void)heap;
- (void)type;
- if (len > sb->sz) {
- byte* buff = (byte*)XMALLOC(len, heap, type);
- if (buff == NULL) {
- ret = MEMORY_E;
- }
- else {
- sb->buffer = buff;
- sb->sz = len;
- sb->dyn = 1;
- }
- }
- return ret;
- }
- /* Dispose of dynamically allocated buffer.
- *
- * @param [in] sb Static buffer.
- * @param [in] heap Dynamic memory allocation hint.
- * @param [in] type Type of dynamic memory.
- */
- static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
- {
- (void)heap;
- (void)type;
- if (sb->dyn) {
- XFREE(sb->buffer, heap, type);
- }
- }
- #endif /* WOLFSSL_SMALL_STACK */
- #ifndef NO_FILESYSTEM
- /* Read all the data from a file into content.
- *
- * @param [in] fname File pointer to read with.
- * @param [in, out] content Read data in an allocated buffer.
- * @param [in] heap Dynamic memory allocation hint.
- * @param [in] type Type of dynamic memory.
- * @param [out] size Amount of data read in bytes.
- * @return 0 on success.
- * @return WOLFSSL_BAD_FILE when reading fails.
- * @return MEMORY_E when memory allocation fails.
- */
- static int wolfssl_read_file_static(const char* fname, StaticBuffer* content,
- void* heap, int type, long* size)
- {
- int ret = 0;
- XFILE file = XBADFILE;
- long sz = 0;
- /* Check filename is usable. */
- if (fname == NULL) {
- ret = WOLFSSL_BAD_FILE;
- }
- /* Open file for reading. */
- if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- /* Get length of file. */
- ret = wolfssl_file_len(file, &sz);
- }
- if (ret == 0) {
- /* Set the buffer to be big enough to hold all data. */
- ret = static_buffer_set_size(content, (word32)sz, heap, type);
- }
- /* Read data from file. */
- if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, sz, file) !=
- (size_t)sz)) {
- ret = WOLFSSL_BAD_FILE;
- }
- /* Close file if opened. */
- if (file != XBADFILE) {
- XFCLOSE(file);
- }
- /* Return size read. */
- *size = sz;
- return ret;
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
- #endif /* !WOLFSSL_SSL_MISC_INCLUDED */
|