From e68c7bb74d7e30255e54ea915bf23e6a06cd35e2 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 21 Oct 2022 10:11:06 +1000 Subject: [PATCH] Move file and BIO reading out to ssl_misc.c --- src/bio.c | 19 +--- src/include.am | 1 + src/pk.c | 235 --------------------------------------- src/ssl.c | 3 + src/ssl_misc.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 301 insertions(+), 252 deletions(-) create mode 100644 src/ssl_misc.c diff --git a/src/bio.c b/src/bio.c index d90b2d18f..6e2f42d5f 100644 --- a/src/bio.c +++ b/src/bio.c @@ -1612,7 +1612,7 @@ int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio) { int len; #ifndef NO_FILESYSTEM - long memSz = 0, curr = 0; + long memSz = 0; XFILE file; #endif @@ -1628,26 +1628,11 @@ int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio) else if (bio->type == WOLFSSL_BIO_FILE) { if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS) len = BAD_FUNC_ARG; - if (file == NULL) - len = WOLFSSL_BAD_FILE; if (len == 0) { - curr = XFTELL(file); - if (curr < 0) { - len = WOLFSSL_BAD_FILE; - } - if (XFSEEK(file, 0, XSEEK_END) != 0) - len = WOLFSSL_BAD_FILE; + len = wolfssl_file_len(file, &memSz); } if (len == 0) { - memSz = XFTELL(file); - if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) - len = WOLFSSL_BAD_FILE; - } - if (len == 0) { - memSz -= curr; len = (int)memSz; - if (XFSEEK(file, curr, SEEK_SET) != 0) - len = WOLFSSL_BAD_FILE; } } #endif diff --git a/src/include.am b/src/include.am index 8aeafb477..309ee2815 100644 --- a/src/include.am +++ b/src/include.am @@ -18,6 +18,7 @@ MAINTAINERCLEANFILES+= $(FIPS_FILES) EXTRA_DIST += src/bio.c EXTRA_DIST += src/conf.c +EXTRA_DIST += src/ssl_misc.c EXTRA_DIST += src/pk.c EXTRA_DIST += src/x509.c EXTRA_DIST += src/x509_str.c diff --git a/src/pk.c b/src/pk.c index 7585fb3ad..c1773fb80 100644 --- a/src/pk.c +++ b/src/pk.c @@ -51,241 +51,6 @@ static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key); #if defined(OPENSSL_EXTRA) -#if !defined(NO_DH) || !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] pem 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** pem) -{ - int ret = 0; - char* mem; - char* p; - - /* Allocate buffer to hold a chunk of data. */ - mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, bio->heap, DYNAMIC_TYPE_OPENSSL); - 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, bio->heap, - DYNAMIC_TYPE_OPENSSL); - 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, bio->heap, DYNAMIC_TYPE_OPENSSL); - mem = NULL; - /* Return error. */ - ret = sz; - } - } - - *pem = 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] pem 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** pem) -{ - int ret = 0; - char* mem; - - /* Allocate buffer to hold data. */ - mem = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL); - 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, bio->heap, DYNAMIC_TYPE_OPENSSL); - mem = NULL; - ret = MEMORY_E; - } - - *pem = mem; - return ret; -} - -/* Read all the data from a BIO. - * - * @param [in, out] bio BIO object to read with. - * @param [out] pem Read data in a buffer. - * @param [out] pemSz 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** pem, int* pemSz, - int* memAlloced) -{ - int ret; - int sz; - - if (bio->type == WOLFSSL_BIO_MEMORY) { - ret = wolfSSL_BIO_get_mem_data(bio, pem); - 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, pem); - if (ret > 0) { - *memAlloced = 1; - } - } -#else - else if ((sz = wolfSSL_BIO_pending(bio)) > 0) { - ret = wolfssl_read_bio_len(bio, sz, pem); - if (ret > 0) { - *memAlloced = 1; - } - } - else if (bio->type == WOLFSSL_BIO_FILE) { - ret = wolfssl_read_bio_file(bio, pem); - if (ret > 0) { - *memAlloced = 1; - } - } -#endif - else { - WOLFSSL_ERROR_MSG("No data read from bio"); - *memAlloced = 0; - ret = NOT_COMPILED_IN; - } - - if (ret >= 0) { - *pemSz = ret; - ret = 0; - } - - return ret; -} -#endif /* !NO_BIO */ - -#if !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 on error. - * @return 0 on success. - */ -static int wolfssl_read_file(XFILE fp, char** data, int* dataSz) -{ - int ret = 0; - int sz = 0; - char* mem = NULL; - - if (fp == XBADFILE) { - ret = WOLFSSL_BAD_FILE; - } - if (ret == 0) { - /* Move to end of file. */ - if (XFSEEK(fp, 0, SEEK_END) != 0) { - ret = WOLFSSL_BAD_FILE; - } - } - if (ret == 0) { - /* Get file offset at end of file. */ - sz = (int)XFTELL(fp); - if (sz < 0) { - ret = WOLFSSL_BAD_FILE; - } - } - /* Go back to start of file. */ - if ((ret == 0) && (XFSEEK(fp, 0, 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) { - /* Allocate memory to big enough to hold whole file. */ - mem = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM); - if (mem == NULL) { - ret = WOLFSSL_BAD_FILE; - } - } - /* Read whole file into new buffer. */ - if ((ret == 0) && ((int)XFREAD(mem, 1, sz, fp) != sz)) { - ret = WOLFSSL_BAD_FILE; - } - if (ret == 0) { - *dataSz = sz; - *data = mem; - mem = NULL; - } - - XFREE(mem, NULL, DYNAMIC_TYPE_PEM); - return ret; -} -#endif /* !NO_FILESYSTEM */ -#endif /* !NO_DH || !WOLFCRYPT_ONLY */ - #if (!defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \ defined(OPENSSL_ALL))) || (!defined(NO_BIO) && defined(OPENSSL_EXTRA)) /* Convert the PEM encoding in the buffer to DER. diff --git a/src/ssl.c b/src/ssl.c index 9fb8fe1f8..df029e121 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -189,6 +189,9 @@ * wolfSSL_CTX_load_system_CA_certs. */ +#define WOLFSSL_SSL_MISC_INCLUDED +#include "src/ssl_misc.c" + #define WOLFSSL_EVP_INCLUDED #include "wolfcrypt/src/evp.c" diff --git a/src/ssl_misc.c b/src/ssl_misc.c new file mode 100644 index 000000000..785a8e974 --- /dev/null +++ b/src/ssl_misc.c @@ -0,0 +1,295 @@ +/* ssl_misc.c + * + * Copyright (C) 2006-2022 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 +#endif + +#include + +#if !defined(WOLFSSL_SSL_MISC_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning 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] pem 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** pem) +{ + int ret = 0; + char* mem; + char* p; + + /* Allocate buffer to hold a chunk of data. */ + mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, bio->heap, DYNAMIC_TYPE_OPENSSL); + 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, bio->heap, + DYNAMIC_TYPE_OPENSSL); + 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, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + /* Return error. */ + ret = sz; + } + } + + *pem = 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] pem 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** pem) +{ + int ret = 0; + char* mem; + + /* Allocate buffer to hold data. */ + mem = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL); + 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, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + ret = MEMORY_E; + } + + *pem = mem; + return ret; +} + +/* Read all the data from a BIO. + * + * @param [in, out] bio BIO object to read with. + * @param [out] pem Read data in a buffer. + * @param [out] pemSz 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** pem, int* pemSz, + int* memAlloced) +{ + int ret; + int sz; + + if (bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_get_mem_data(bio, pem); + 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, pem); + if (ret > 0) { + *memAlloced = 1; + } + } +#else + else if ((sz = wolfSSL_BIO_pending(bio)) > 0) { + ret = wolfssl_read_bio_len(bio, sz, pem); + if (ret > 0) { + *memAlloced = 1; + } + } + else if (bio->type == WOLFSSL_BIO_FILE) { + ret = wolfssl_read_bio_file(bio, pem); + if (ret > 0) { + *memAlloced = 1; + } + } +#endif + else { + WOLFSSL_ERROR_MSG("No data read from bio"); + *memAlloced = 0; + ret = NOT_COMPILED_IN; + } + + if (ret >= 0) { + *pemSz = ret; + ret = 0; + } + + return ret; +} +#endif /* !NO_BIO */ + +#if !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 (sz < 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; +} + +/* 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 on error. + * @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 to big enough to hold whole file. */ + mem = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM); + if (mem == NULL) { + ret = WOLFSSL_BAD_FILE; + } + } + /* Read whole file into new buffer. */ + if ((ret == 0) && ((int)XFREAD(mem, 1, sz, fp) != sz)) { + ret = WOLFSSL_BAD_FILE; + } + if (ret == 0) { + *dataSz = (int)sz; + *data = mem; + mem = NULL; + } + + XFREE(mem, NULL, DYNAMIC_TYPE_PEM); + return ret; +} +#endif /* !NO_FILESYSTEM */ +#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */ +#endif /* !WOLFSSL_SSL_MISC_INCLUDED */ +