From 5c762afb94bb96fd5c7e38e98ee7b8f754f3d22a Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 22 Mar 2021 10:36:39 -0700 Subject: [PATCH 01/10] Fix for BIO with callbacks not called after PR #3824 (was always returning WANT_READ). --- src/bio.c | 81 ++++++++++++++++++++++++++++----------------------- src/wolfio.c | 5 ---- wolfssl/ssl.h | 1 + 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/bio.c b/src/bio.c index 6509efcd2..c1df59159 100644 --- a/src/bio.c +++ b/src/bio.c @@ -213,46 +213,47 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (bio->method && bio->method->readCb) { ret = bio->method->readCb(bio, (char*)buf, len); } + else { + /* formatting data */ + if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { + ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + } - /* formatting data */ - if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { - ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); - } + /* write BIOs */ + if (bio && bio->type == WOLFSSL_BIO_BIO) { + ret = wolfSSL_BIO_BIO_read(bio, buf, len); + } - /* write BIOs */ - if (bio && bio->type == WOLFSSL_BIO_BIO) { - ret = wolfSSL_BIO_BIO_read(bio, buf, len); - } + if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); + } - if (bio && bio->type == WOLFSSL_BIO_MEMORY) { - ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); - } - - #ifndef NO_FILESYSTEM - if (bio && bio->type == WOLFSSL_BIO_FILE) { - if (bio->ptr) - ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ - && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - else - ret = (int)XREAD(bio->num, buf, len); + #ifndef NO_FILESYSTEM + if (bio && bio->type == WOLFSSL_BIO_FILE) { + if (bio->ptr) + ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + else + ret = (int)XREAD(bio->num, buf, len); + #endif + } #endif - } - #endif - #ifndef WOLFCRYPT_ONLY - if (bio && bio->type == WOLFSSL_BIO_SSL) { - ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); - } + #ifndef WOLFCRYPT_ONLY + if (bio && bio->type == WOLFSSL_BIO_SSL) { + ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); + } - /* data passing through BIO MD wrapper */ - if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { - ret = wolfSSL_BIO_MD_read(bio, buf, ret); - } - #endif + /* data passing through BIO MD wrapper */ + if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { + ret = wolfSSL_BIO_MD_read(bio, buf, ret); + } + #endif - if (bio->type == WOLFSSL_BIO_SOCKET) { - ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + if (bio->type == WOLFSSL_BIO_SOCKET) { + ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + } } /* case where front of list is done */ @@ -263,6 +264,12 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (ret > 0) { sz = ret; /* adjust size for formatting */ } + else { + if (wolfSSL_BIO_supports_pending(bio) && + wolfSSL_BIO_ctrl_pending(bio) == 0) { + ret = WOLFSSL_CBIO_ERR_WANT_READ; + } + } /* previous WOLFSSL_BIO in list working towards head of list */ bio = bio->prev; @@ -1144,7 +1151,7 @@ int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } b->readRq = 0; @@ -1194,7 +1201,7 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) } if (bio->type == WOLFSSL_BIO_MEMORY) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->pair != NULL) { @@ -1246,7 +1253,7 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) } if (bio->type != WOLFSSL_BIO_BIO) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->pair != NULL) { @@ -1414,7 +1421,7 @@ long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) } if (bio->type != WOLFSSL_BIO_FILE) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } *fp = (XFILE)bio->ptr; diff --git a/src/wolfio.c b/src/wolfio.c index cff63d3e2..89ec0cdf8 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -133,11 +133,6 @@ int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - if (wolfSSL_BIO_supports_pending(ssl->biord) && - wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { - WOLFSSL_MSG("BIO want read"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); if (recvd <= 0) { if (ssl->biord->type == WOLFSSL_BIO_SOCKET) { diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index de42e4c78..a6a7d87c3 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3625,6 +3625,7 @@ WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +/* non-standard API to determine if BIO supports "pending" */ WOLFSSL_API int wolfSSL_BIO_supports_pending(const WOLFSSL_BIO *bio); WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); From 072e6e010ceaadb56c9056b33e9749b72212c5ff Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 Mar 2021 09:01:42 -0700 Subject: [PATCH 02/10] Handle the BIO want read in BioReceive. --- src/bio.c | 6 ------ src/wolfio.c | 6 +++++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/bio.c b/src/bio.c index c1df59159..240fb2f5c 100644 --- a/src/bio.c +++ b/src/bio.c @@ -264,12 +264,6 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (ret > 0) { sz = ret; /* adjust size for formatting */ } - else { - if (wolfSSL_BIO_supports_pending(bio) && - wolfSSL_BIO_ctrl_pending(bio) == 0) { - ret = WOLFSSL_CBIO_ERR_WANT_READ; - } - } /* previous WOLFSSL_BIO in list working towards head of list */ bio = bio->prev; diff --git a/src/wolfio.c b/src/wolfio.c index 89ec0cdf8..041e43577 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -135,7 +135,11 @@ int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); if (recvd <= 0) { - if (ssl->biord->type == WOLFSSL_BIO_SOCKET) { + if (wolfSSL_BIO_supports_pending(ssl->biord) && + wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (ssl->biord->type == WOLFSSL_BIO_SOCKET) { int err; if (recvd == 0) { From 8984ce03e9ababa2530aad719408ca76a3a088da Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 24 Mar 2021 10:20:16 -0700 Subject: [PATCH 03/10] Refactor BIO read/write to use switch. --- doc/dox_comments/header_files/asn_public.h | 4 +- src/bio.c | 279 ++++++++++----------- 2 files changed, 139 insertions(+), 144 deletions(-) diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index e4f2cf69d..2d24e804e 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -1210,7 +1210,7 @@ int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz); and storing it as a pem file \return MEMORY_E Returned if there is an error allocating memory with XMALLOC - \return ASN_INPUT_E Returned in the case of a base 64 encoding error + \return ASN_INPUT_E Returned in the case of a base64 encoding error \return BUFFER_E May be returned if the output buffer is too small to store the pem formatted certificate @@ -1253,7 +1253,7 @@ WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, and storing it as a pem file \return MEMORY_E Returned if there is an error allocating memory with XMALLOC - \return ASN_INPUT_E Returned in the case of a base 64 encoding error + \return ASN_INPUT_E Returned in the case of a base64 encoding error \return BUFFER_E May be returned if the output buffer is too small to store the pem formatted certificate diff --git a/src/bio.c b/src/bio.c index 240fb2f5c..0c6e5b96f 100644 --- a/src/bio.c +++ b/src/bio.c @@ -40,7 +40,7 @@ static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) if (Base64_Decode((const byte*)buf, (word32)len, (byte*)buf, &frmtSz) !=0) { WOLFSSL_MSG("Err doing base64 decode"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } (void)bio; @@ -146,7 +146,7 @@ static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf, front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) { front->eof = 1; } else { @@ -187,9 +187,9 @@ static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) */ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { - int ret = 0; + int ret = 0; WOLFSSL_BIO* front = bio; - int sz = 0; + int sz = 0; WOLFSSL_ENTER("wolfSSL_BIO_read"); @@ -214,46 +214,44 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) ret = bio->method->readCb(bio, (char*)buf, len); } else { - /* formatting data */ - if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { - ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); - } - - /* write BIOs */ - if (bio && bio->type == WOLFSSL_BIO_BIO) { + switch (bio->type) { + case WOLFSSL_BIO_BASE64: /* formatting data */ + if (sz > 0) + ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + break; + case WOLFSSL_BIO_BIO: /* read BIOs */ ret = wolfSSL_BIO_BIO_read(bio, buf, len); - } - - if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + break; + case WOLFSSL_BIO_MEMORY: ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); - } - - #ifndef NO_FILESYSTEM - if (bio && bio->type == WOLFSSL_BIO_FILE) { - if (bio->ptr) + break; + case WOLFSSL_BIO_FILE: + #ifndef NO_FILESYSTEM + if (bio->ptr) { ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ - && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - else + } + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + else { ret = (int)XREAD(bio->num, buf, len); - #endif - } - #endif - - #ifndef WOLFCRYPT_ONLY - if (bio && bio->type == WOLFSSL_BIO_SSL) { + } + #endif + #endif /* !NO_FILESYSTEM */ + break; + case WOLFSSL_BIO_SSL: + #ifndef WOLFCRYPT_ONLY ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); - } - - /* data passing through BIO MD wrapper */ - if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { + #endif + break; + case WOLFSSL_BIO_MD: /* data passing through BIO MD wrapper */ + #ifndef WOLFCRYPT_ONLY ret = wolfSSL_BIO_MD_read(bio, buf, ret); - } - #endif - - if (bio->type == WOLFSSL_BIO_SOCKET) { + #endif + break; + case WOLFSSL_BIO_SOCKET: ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); - } + break; + } /* switch */ } /* case where front of list is done */ @@ -280,6 +278,7 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } +#ifdef WOLFSSL_BASE64_ENCODE /* Converts data into base64 output * * returns the resulting buffer size on success. @@ -296,7 +295,6 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return BAD_FUNC_ARG; } -#if defined(WOLFSSL_BASE64_ENCODE) tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { return WOLFSSL_FATAL_ERROR; @@ -322,18 +320,10 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, } XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); -#else - (void)bio; - (void)data; - (void)inLen; - (void)out; - (void)outLen; - (void)tmp; - WOLFSSL_MSG("BASE64 encoding not compiled in"); -#endif + return ret; } - +#endif /* WOLFSSL_BASE64_ENCODE */ #ifndef WOLFCRYPT_ONLY /* Helper function for writing to a WOLFSSL_BIO_SSL type @@ -357,7 +347,7 @@ static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data, front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) { front->eof = 1; } else { @@ -506,10 +496,10 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) */ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { - int ret = 0; - int retB64 = 0; + int ret = 0; + int retB64 = 0; WOLFSSL_BIO* front = bio; - void* frmt = NULL; + void* frmt = NULL; word32 frmtSz = 0; WOLFSSL_ENTER("wolfSSL_BIO_write"); @@ -528,109 +518,114 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (bio->method && bio->method->writeCb) { ret = bio->method->writeCb(bio, (const char*)data, len); } + else { + switch (bio->type) { + case WOLFSSL_BIO_BASE64: + { + #ifdef WOLFSSL_BASE64_ENCODE + word32 sz = 0; - /* check for formatting */ - if (bio->type == WOLFSSL_BIO_BASE64) { -#if defined(WOLFSSL_BASE64_ENCODE) - word32 sz = 0; - - if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { - if (Base64_Encode_NoNl((const byte*)data, len, NULL, - &sz) != LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base 64 get length"); - ret = SSL_FATAL_ERROR; + /* get the encoded length */ + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, len, NULL, + &sz) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + ret = WOLFSSL_FATAL_ERROR; + } } - } - else { - if (Base64_Encode((const byte*)data, len, NULL, &sz) != - LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base 64 get length"); - ret = SSL_FATAL_ERROR; + else { + if (Base64_Encode((const byte*)data, len, NULL, &sz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + ret = WOLFSSL_FATAL_ERROR; + } } - } - if (frmt == NULL && sz > 0 && ret != SSL_FATAL_ERROR) { - frmt = (void*)XMALLOC(sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = SSL_FATAL_ERROR; + /* allocate buffer for encoded output */ + if (frmt == NULL && sz > 0 && ret != WOLFSSL_FATAL_ERROR) { + frmt = (void*)XMALLOC(sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = WOLFSSL_FATAL_ERROR; + } + frmtSz = sz; } - frmtSz = sz; - } - else if (sz > frmtSz) { - frmt = (void*)XREALLOC(frmt, sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = SSL_FATAL_ERROR; + else if (sz > frmtSz) { + frmt = (void*)XREALLOC(frmt, sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = WOLFSSL_FATAL_ERROR; + } + /* since frmt already existed then data should point to + new formatted buffer */ + data = frmt; + len = frmtSz; + frmtSz = sz; } - /* since frmt already existed then data should point to knew - formatted buffer */ - data = frmt; - len = frmtSz; - frmtSz = sz; + + if (ret >= 0) { + /* change so that data is formatted buffer */ + retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte*)frmt, &frmtSz); + data = frmt; + len = frmtSz; + } + #endif /* WOLFSSL_BASE64_ENCODE */ + break; } -#endif /* defined(WOLFSSL_BASE64_ENCODE) */ - - if (ret >= 0) { - /* change so that data is formatted buffer */ - retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, - (byte*)frmt, &frmtSz); - data = frmt; - len = frmtSz; - } - } - - /* write bios */ - if (bio->type == WOLFSSL_BIO_BIO) { - ret = wolfSSL_BIO_BIO_write(bio, data, len); - } - - if (bio->type == WOLFSSL_BIO_MEMORY) { - ret = wolfSSL_BIO_MEMORY_write(bio, data, len); - } - - #ifndef NO_FILESYSTEM - if (bio && bio->type == WOLFSSL_BIO_FILE) { - if (bio->ptr) - ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ - && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - else - ret = (int)XWRITE(bio->num, data, len); - #endif - } - #endif - - #ifndef WOLFCRYPT_ONLY - if (bio->type == WOLFSSL_BIO_SSL) { - /* already got eof, again is error */ - if (front->eof) { - ret = SSL_FATAL_ERROR; - } - else { - ret = wolfSSL_BIO_SSL_write(bio, data, len, front); - } - /* Rest of chain is taken care of inside call */ - break; - } - - if (bio->type == WOLFSSL_BIO_MD) { - if (bio->next != NULL) { /* data passing through MD BIO */ - ret = wolfSSL_BIO_MD_write(bio, data, len); - } - } - #endif /* WOLFCRYPT_ONLY */ - - if (bio->type == WOLFSSL_BIO_SOCKET) { - ret = wolfIO_Send(bio->num, (char*)data, len, 0); + case WOLFSSL_BIO_BIO: /* write bios */ + ret = wolfSSL_BIO_BIO_write(bio, data, len); + break; + case WOLFSSL_BIO_MEMORY: + ret = wolfSSL_BIO_MEMORY_write(bio, data, len); + break; + case WOLFSSL_BIO_FILE: + #ifndef NO_FILESYSTEM + if (bio->ptr) { + ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); + } + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + else { + ret = (int)XWRITE(bio->num, data, len); + } + #endif + #endif /* !NO_FILESYSTEM */ + break; + case WOLFSSL_BIO_SSL: + #ifndef WOLFCRYPT_ONLY + /* already got eof, again is error */ + if (front->eof) { + ret = WOLFSSL_FATAL_ERROR; + } + else { + ret = wolfSSL_BIO_SSL_write(bio, data, len, front); + } + /* Rest of chain is taken care of inside call */ + goto exit_chain; + #endif + break; + case WOLFSSL_BIO_MD: + #ifndef WOLFCRYPT_ONLY + if (bio->next != NULL) { /* data passing through MD BIO */ + ret = wolfSSL_BIO_MD_write(bio, data, len); + } + #endif + break; + case WOLFSSL_BIO_SOCKET: + ret = wolfIO_Send(bio->num, (char*)data, len, 0); + break; + } /* switch */ } /* advance to the next bio in list */ bio = bio->next; } +exit_chain: + /* info cb, user can override return value */ if (front != NULL && front->infoCb != NULL) { ret = (int)front->infoCb(front, From 5b751d9eaab7836c6aebb884a953a6d939d28f1b Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 25 Mar 2021 12:24:30 -0700 Subject: [PATCH 04/10] Fix for possible unused label "exit_chain". --- src/bio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bio.c b/src/bio.c index 0c6e5b96f..e630a8c6c 100644 --- a/src/bio.c +++ b/src/bio.c @@ -624,7 +624,9 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) bio = bio->next; } +#ifndef WOLFCRYPT_ONLY exit_chain: +#endif /* info cb, user can override return value */ if (front != NULL && front->infoCb != NULL) { From d257cf50032aaab9c8d714f7484f9c79c7a18d41 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 29 Mar 2021 18:17:58 +0200 Subject: [PATCH 05/10] Return error when using not compiled in BIO Refactor base64 BIO write into static function --- src/bio.c | 146 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 59 deletions(-) diff --git a/src/bio.c b/src/bio.c index e630a8c6c..75c008783 100644 --- a/src/bio.c +++ b/src/bio.c @@ -235,17 +235,29 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) else { ret = (int)XREAD(bio->num, buf, len); } + #else + WOLFSSL_MSG("No file pointer and XREAD not enabled"); + ret = NOT_COMPILED_IN; #endif + #else + WOLFSSL_MSG("WOLFSSL_BIO_FILE used with NO_FILESYSTEM"); + ret = NOT_COMPILED_IN; #endif /* !NO_FILESYSTEM */ break; case WOLFSSL_BIO_SSL: #ifndef WOLFCRYPT_ONLY ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); + #else + WOLFSSL_MSG("WOLFSSL_BIO_SSL used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; #endif break; case WOLFSSL_BIO_MD: /* data passing through BIO MD wrapper */ #ifndef WOLFCRYPT_ONLY ret = wolfSSL_BIO_MD_read(bio, buf, ret); + #else + WOLFSSL_MSG("WOLFSSL_BIO_MD used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; #endif break; case WOLFSSL_BIO_SOCKET: @@ -283,11 +295,15 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) * * returns the resulting buffer size on success. */ +/** + * `out` buffer is allocated here and the caller is responsible + * for free'ing it + */ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, - word32 inLen, byte* out, word32* outLen) + word32 inLen, byte** out, word32* outLen, WOLFSSL_BIO* front) { + word32 sz = 0; byte* tmp = NULL; - int ret = 0; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); @@ -295,33 +311,69 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return BAD_FUNC_ARG; } - tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + /* get the encoded length */ + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, + &sz) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + return WOLFSSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, inLen, NULL, &sz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + return WOLFSSL_FATAL_ERROR; + } + } + + /* allocate buffer for encoded output */ + if (*out == NULL && sz > 0) { + *out = (void*)XMALLOC(sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (*out == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FATAL_ERROR; + } + } + else if (sz > *outLen) { + tmp = (void*)XREALLOC(*out, sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FATAL_ERROR; + } + *out = tmp; + } + *outLen = sz; + + /* Allocate temporary buffer since base64 functions can't work in place */ + tmp = (byte*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); return WOLFSSL_FATAL_ERROR; } - if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) == - WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, tmp, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } else { if (Base64_Encode((const byte*)data, inLen, tmp, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } - if (ret != WOLFSSL_FATAL_ERROR) { - ret = (int) inLen; - XMEMCPY(out, tmp, *outLen); - - } + XMEMCPY(*out, tmp, *outLen); XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + /* Encode successful */ + return inLen; } #endif /* WOLFSSL_BASE64_ENCODE */ @@ -497,6 +549,8 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { int ret = 0; + /* Use extra return var as we want to return how much of input we have + * written, not how big the base64 encoding ended up being */ int retB64 = 0; WOLFSSL_BIO* front = bio; void* frmt = NULL; @@ -523,55 +577,17 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) case WOLFSSL_BIO_BASE64: { #ifdef WOLFSSL_BASE64_ENCODE - word32 sz = 0; - - /* get the encoded length */ - if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { - if (Base64_Encode_NoNl((const byte*)data, len, NULL, - &sz) != LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base64 get length"); - ret = WOLFSSL_FATAL_ERROR; - } - } - else { - if (Base64_Encode((const byte*)data, len, NULL, &sz) != - LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base64 get length"); - ret = WOLFSSL_FATAL_ERROR; - } - } - - /* allocate buffer for encoded output */ - if (frmt == NULL && sz > 0 && ret != WOLFSSL_FATAL_ERROR) { - frmt = (void*)XMALLOC(sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = WOLFSSL_FATAL_ERROR; - } - frmtSz = sz; - } - else if (sz > frmtSz) { - frmt = (void*)XREALLOC(frmt, sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = WOLFSSL_FATAL_ERROR; - } - /* since frmt already existed then data should point to - new formatted buffer */ - data = frmt; - len = frmtSz; - frmtSz = sz; - } - - if (ret >= 0) { + ret = retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte**)&frmt, &frmtSz, front); + if (ret > 0) { /* change so that data is formatted buffer */ - retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, - (byte*)frmt, &frmtSz); data = frmt; len = frmtSz; } + #else + WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " + "WOLFSSL_BASE64_ENCODE"); + ret = NOT_COMPILED_IN; #endif /* WOLFSSL_BASE64_ENCODE */ break; } @@ -591,7 +607,13 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) else { ret = (int)XWRITE(bio->num, data, len); } + #else + WOLFSSL_MSG("No file pointer and XWRITE not enabled"); + ret = NOT_COMPILED_IN; #endif + #else + WOLFSSL_MSG("WOLFSSL_BIO_FILE used with NO_FILESYSTEM"); + ret = NOT_COMPILED_IN; #endif /* !NO_FILESYSTEM */ break; case WOLFSSL_BIO_SSL: @@ -605,6 +627,9 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) } /* Rest of chain is taken care of inside call */ goto exit_chain; + #else + WOLFSSL_MSG("WOLFSSL_BIO_SSL used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; #endif break; case WOLFSSL_BIO_MD: @@ -612,6 +637,9 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (bio->next != NULL) { /* data passing through MD BIO */ ret = wolfSSL_BIO_MD_write(bio, data, len); } + #else + WOLFSSL_MSG("WOLFSSL_BIO_MD used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; #endif break; case WOLFSSL_BIO_SOCKET: @@ -639,7 +667,7 @@ exit_chain: XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER); } - if (retB64 != 0) + if (retB64 > 0 && ret > 0) return retB64; else return ret; From 1a9d59c185c7f7570df6e680dc9a0ba8a8648f50 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 1 Apr 2021 21:01:51 +0200 Subject: [PATCH 06/10] `front` may be unused and generate a warning --- src/bio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bio.c b/src/bio.c index 75c008783..79e792949 100644 --- a/src/bio.c +++ b/src/bio.c @@ -311,6 +311,9 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return BAD_FUNC_ARG; } + /* Potentially unused when memory functions ignore heap hints */ + (void)front; + /* get the encoded length */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, From 5ebe5d071f1c31d52cfb793c93c0903d843869fd Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 5 Apr 2021 14:35:41 -0700 Subject: [PATCH 07/10] Fixes for `wolfSSL_BIO_BASE64_write` changes. --- src/bio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bio.c b/src/bio.c index 79e792949..c2b2f2027 100644 --- a/src/bio.c +++ b/src/bio.c @@ -332,7 +332,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, /* allocate buffer for encoded output */ if (*out == NULL && sz > 0) { - *out = (void*)XMALLOC(sz, front->heap, + *out = (byte*)XMALLOC(sz, front->heap, DYNAMIC_TYPE_TMP_BUFFER); if (*out == NULL) { WOLFSSL_MSG("Memory error"); @@ -340,7 +340,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, } } else if (sz > *outLen) { - tmp = (void*)XREALLOC(*out, sz, front->heap, + tmp = (byte*)XREALLOC(*out, sz, front->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { WOLFSSL_MSG("Memory error"); @@ -372,7 +372,9 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, } } - XMEMCPY(*out, tmp, *outLen); + if (*out) { + XMEMCPY(*out, tmp, *outLen); + } XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); /* Encode successful */ From 4747ba9ccba9b59758d6917378d4ab1f913f48d7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 7 Apr 2021 09:46:57 -0700 Subject: [PATCH 08/10] Fix for BIO base64 write valgrind issue. --- src/bio.c | 65 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/bio.c b/src/bio.c index c2b2f2027..d600ff304 100644 --- a/src/bio.c +++ b/src/bio.c @@ -300,10 +300,11 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) * for free'ing it */ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, - word32 inLen, byte** out, word32* outLen, WOLFSSL_BIO* front) + word32 inLen, byte** out, word32* outLen, void* heap) { - word32 sz = 0; + int ret = WOLFSSL_FATAL_ERROR; byte* tmp = NULL; + word32 sz = 0; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); @@ -311,9 +312,6 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return BAD_FUNC_ARG; } - /* Potentially unused when memory functions ignore heap hints */ - (void)front; - /* get the encoded length */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, @@ -330,55 +328,60 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, } } + if (sz == 0) { + return 0; /* nothing to do */ + } + /* allocate buffer for encoded output */ - if (*out == NULL && sz > 0) { - *out = (byte*)XMALLOC(sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); + if (*out == NULL) { + *out = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (*out == NULL) { WOLFSSL_MSG("Memory error"); return WOLFSSL_FATAL_ERROR; - } } - else if (sz > *outLen) { - tmp = (byte*)XREALLOC(*out, sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FATAL_ERROR; - } - *out = tmp; + tmp = *out; } - *outLen = sz; - - /* Allocate temporary buffer since base64 functions can't work in place */ - tmp = (byte*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { + else { + if (sz > *outLen) { + /* use existing buffer as input */ + *out = (byte*)XREALLOC(*out, sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (*out == NULL) { WOLFSSL_MSG("Memory error"); return WOLFSSL_FATAL_ERROR; } + } + data = *out; + inLen = *outLen; + /* allocate temp buffer, since base64 encode does not allow inline */ + tmp = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + *outLen = sz; + ret = inLen; /* For successful Encode return inLen */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, tmp, outLen) < 0) { - XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FATAL_ERROR; + ret = WOLFSSL_FATAL_ERROR; } } else { if (Base64_Encode((const byte*)data, inLen, tmp, outLen) < 0) { - XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FATAL_ERROR; + ret = WOLFSSL_FATAL_ERROR; } } - if (*out) { + /* free temp */ + if (tmp != *out) { XMEMCPY(*out, tmp, *outLen); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); } - XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + /* out is free'd by caller */ - /* Encode successful */ - return inLen; + (void)heap; + + return ret; } #endif /* WOLFSSL_BASE64_ENCODE */ @@ -583,7 +586,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { #ifdef WOLFSSL_BASE64_ENCODE ret = retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, - (byte**)&frmt, &frmtSz, front); + (byte**)&frmt, &frmtSz, front->heap); if (ret > 0) { /* change so that data is formatted buffer */ data = frmt; From f298bb9f22ccdb4026fd4d560663fdd2bc85a755 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Apr 2021 08:06:45 -0700 Subject: [PATCH 09/10] Peer review feedback. --- src/bio.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/bio.c b/src/bio.c index d600ff304..186dbbe5f 100644 --- a/src/bio.c +++ b/src/bio.c @@ -329,6 +329,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, } if (sz == 0) { + *outLen = 0; return 0; /* nothing to do */ } @@ -338,18 +339,19 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, if (*out == NULL) { WOLFSSL_MSG("Memory error"); return WOLFSSL_FATAL_ERROR; - } + } tmp = *out; } else { if (sz > *outLen) { /* use existing buffer as input */ - *out = (byte*)XREALLOC(*out, sz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (*out == NULL) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FATAL_ERROR; - } - + tmp = (byte*)XREALLOC(*out, sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + /* out is free'd by caller */ + WOLFSSL_MSG("Realloc memory error"); + return WOLFSSL_FATAL_ERROR; + } + *out = tmp; } data = *out; inLen = *outLen; @@ -357,22 +359,24 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, tmp = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); } - *outLen = sz; - ret = inLen; /* For successful Encode return inLen */ + ret = inLen; /* For successful encode return inLen */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, - tmp, outLen) < 0) { + tmp, &sz) < 0) { ret = WOLFSSL_FATAL_ERROR; } } else { if (Base64_Encode((const byte*)data, inLen, - tmp, outLen) < 0) { + tmp, &sz) < 0) { ret = WOLFSSL_FATAL_ERROR; } } + if (ret >= 0) { + *outLen = sz; + } - /* free temp */ + /* if temp used, copy and free */ if (tmp != *out) { XMEMCPY(*out, tmp, *outLen); XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); From beff4daf7ecc1cd9eac7602bef4e67673f77efc4 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 8 Apr 2021 19:11:55 +0200 Subject: [PATCH 10/10] Refactor wolfSSL_BIO_BASE64_write to simplify its logic --- src/bio.c | 56 ++++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/bio.c b/src/bio.c index 186dbbe5f..c82702e18 100644 --- a/src/bio.c +++ b/src/bio.c @@ -298,11 +298,12 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) /** * `out` buffer is allocated here and the caller is responsible * for free'ing it + * `data` and `out` can be the same in which case `data` should + * always be set to `out` after this function call succeeds */ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, word32 inLen, byte** out, word32* outLen, void* heap) { - int ret = WOLFSSL_FATAL_ERROR; byte* tmp = NULL; word32 sz = 0; @@ -333,59 +334,38 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return 0; /* nothing to do */ } - /* allocate buffer for encoded output */ - if (*out == NULL) { - *out = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (*out == NULL) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FATAL_ERROR; - } - tmp = *out; + /* allocate temp buffer, since base64 encode does not allow inline */ + tmp = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FATAL_ERROR; } - else { - if (sz > *outLen) { - /* use existing buffer as input */ - tmp = (byte*)XREALLOC(*out, sz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - /* out is free'd by caller */ - WOLFSSL_MSG("Realloc memory error"); - return WOLFSSL_FATAL_ERROR; - } - *out = tmp; - } - data = *out; - inLen = *outLen; - /* allocate temp buffer, since base64 encode does not allow inline */ - tmp = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); - } - - ret = inLen; /* For successful encode return inLen */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, tmp, &sz) < 0) { - ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_MSG("Base64_Encode_NoNl error"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } else { if (Base64_Encode((const byte*)data, inLen, tmp, &sz) < 0) { - ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_MSG("Base64_Encode error"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } - if (ret >= 0) { - *outLen = sz; - } - /* if temp used, copy and free */ - if (tmp != *out) { - XMEMCPY(*out, tmp, *outLen); - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); - } + if (*out != NULL) + XFREE(*out, heap, DYNAMIC_TYPE_TMP_BUFFER); + *out = tmp; + *outLen = sz; /* out is free'd by caller */ (void)heap; - return ret; + return inLen; } #endif /* WOLFSSL_BASE64_ENCODE */