#include <wolfssl/wolfcrypt/libwolfssl_sources.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
#define READ_BIO_FILE_CHUNK 128
static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data)
{
int ret = 0;
char* mem;
char* p;
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;
p = mem;
sz = READ_BIO_FILE_CHUNK;
while ((sz = wolfSSL_BIO_read(bio, p, sz)) > 0) {
int remaining;
ret += sz;
remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
if (remaining != READ_BIO_FILE_CHUNK) {
p += sz;
sz = remaining;
}
else {
#ifdef WOLFSSL_NO_REALLOC
p = (char*)XMALLOC(ret + READ_BIO_FILE_CHUNK, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (p != NULL) {
XMEMCPY(p, mem, ret);
XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
mem = NULL;
}
#else
p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (p == NULL) {
sz = MEMORY_E;
break;
}
mem = p;
p += ret;
sz = READ_BIO_FILE_CHUNK;
}
}
if ((sz < 0) || (ret == 0)) {
XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
mem = NULL;
ret = sz;
}
}
*data = mem;
return ret;
}
static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data)
{
int ret = 0;
char* mem;
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) {
XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
mem = NULL;
ret = MEMORY_E;
}
*data = mem;
return ret;
}
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) {
WOLFSSL_BIO* mem_bio = bio;
for (; mem_bio != NULL; mem_bio = mem_bio->next) {
if (mem_bio->type == WOLFSSL_BIO_MEMORY)
break;
}
if (mem_bio == NULL)
mem_bio = bio;
mem_bio->rdIdx += ret;
}
*memAlloced = 0;
}
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;
}
}
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
#endif
#if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
!defined(NO_CERTS)) && !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
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) {
curr = (long)XFTELL(fp);
if (curr < 0) {
#ifdef ESPIPE
if (errno == ESPIPE) {
WOLFSSL_ERROR_MSG("wolfssl_file_len: file is a pipe");
*fileSz = 0;
ret = WOLFSSL_BAD_FILETYPE;
}
else
#endif
ret = WOLFSSL_BAD_FILE;
}
}
if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
ret = WOLFSSL_BAD_FILE;
}
if (ret == 0) {
sz = (long)XFTELL(fp) - curr;
if (sz < 0) {
ret = WOLFSSL_BAD_FILE;
}
}
if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
ret = WOLFSSL_BAD_FILE;
}
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)
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) {
mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (mem == NULL) {
ret = MEMORY_E;
}
}
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
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
#ifdef WOLFSSL_SMALL_STACK
typedef struct {
byte* buffer;
word32 sz;
} StaticBuffer;
static void static_buffer_init(StaticBuffer* sb)
{
sb->buffer = NULL;
sb->sz = 0;
}
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;
}
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
{
(void)heap;
(void)type;
XFREE(sb->buffer, heap, type);
}
#else
typedef struct {
byte* buffer;
word32 sz;
int dyn;
} StaticBuffer;
static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
{
sb->buffer = stackBuffer;
sb->sz = len;
sb->dyn = 0;
}
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;
}
static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
{
(void)heap;
(void)type;
if (sb->dyn) {
XFREE(sb->buffer, heap, type);
}
}
#endif
#ifndef NO_FILESYSTEM
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;
if (fname == NULL) {
ret = WOLFSSL_BAD_FILE;
}
if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
ret = WOLFSSL_BAD_FILE;
}
if (ret == 0) {
ret = wolfssl_file_len(file, &sz);
}
if (ret == 0) {
ret = static_buffer_set_size(content, (word32)sz, heap, type);
}
if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, (size_t)sz, file) !=
(size_t)sz)) {
ret = WOLFSSL_BAD_FILE;
}
if (file != XBADFILE) {
XFCLOSE(file);
}
*size = sz;
return ret;
}
#endif
#endif
#endif