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 6509efcd2..c82702e18 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"); @@ -213,46 +213,57 @@ 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); } - - /* 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); - } - - 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); - #endif - } - #endif - - #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 - - if (bio->type == WOLFSSL_BIO_SOCKET) { - ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + else { + 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); + break; + case WOLFSSL_BIO_MEMORY: + ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); + 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 { + 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: + ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + break; + } /* switch */ } /* case where front of list is done */ @@ -279,15 +290,22 @@ 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. */ +/** + * `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) + word32 inLen, byte** out, word32* outLen, void* heap) { byte* tmp = NULL; - int ret = 0; + word32 sz = 0; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); @@ -295,44 +313,61 @@ 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; + /* 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; + } } - if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) == - WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (sz == 0) { + *outLen = 0; + return 0; /* nothing to do */ + } + + /* 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; + } + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, - tmp, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + tmp, &sz) < 0) { + 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, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + tmp, &sz) < 0) { + WOLFSSL_MSG("Base64_Encode error"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } - if (ret != WOLFSSL_FATAL_ERROR) { - ret = (int) inLen; - XMEMCPY(out, tmp, *outLen); + if (*out != NULL) + XFREE(*out, heap, DYNAMIC_TYPE_TMP_BUFFER); + *out = tmp; + *outLen = sz; + /* out is free'd by caller */ - } - 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; + (void)heap; + + return inLen; } - +#endif /* WOLFSSL_BASE64_ENCODE */ #ifndef WOLFCRYPT_ONLY /* Helper function for writing to a WOLFSSL_BIO_SSL type @@ -356,7 +391,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 { @@ -505,10 +540,12 @@ 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; + /* 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; + void* frmt = NULL; word32 frmtSz = 0; WOLFSSL_ENTER("wolfSSL_BIO_write"); @@ -527,109 +564,90 @@ 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); } - - /* 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; + else { + switch (bio->type) { + case WOLFSSL_BIO_BASE64: + { + #ifdef WOLFSSL_BASE64_ENCODE + ret = retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte**)&frmt, &frmtSz, front->heap); + if (ret > 0) { + /* change so that data is formatted buffer */ + data = frmt; + len = frmtSz; } + #else + WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " + "WOLFSSL_BASE64_ENCODE"); + ret = NOT_COMPILED_IN; + #endif /* WOLFSSL_BASE64_ENCODE */ + break; } - 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; + 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 (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; + #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); } - 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 + 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: + #ifndef WOLFCRYPT_ONLY + /* already got eof, again is error */ + if (front->eof) { + ret = WOLFSSL_FATAL_ERROR; } - /* since frmt already existed then data should point to knew - formatted buffer */ - data = frmt; - len = frmtSz; - frmtSz = sz; - } -#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); + else { + ret = wolfSSL_BIO_SSL_write(bio, data, len, front); + } + /* 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: + #ifndef WOLFCRYPT_ONLY + 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: + ret = wolfIO_Send(bio->num, (char*)data, len, 0); + break; + } /* switch */ } /* advance to the next bio in list */ bio = bio->next; } +#ifndef WOLFCRYPT_ONLY +exit_chain: +#endif + /* info cb, user can override return value */ if (front != NULL && front->infoCb != NULL) { ret = (int)front->infoCb(front, @@ -641,7 +659,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER); } - if (retB64 != 0) + if (retB64 > 0 && ret > 0) return retB64; else return ret; @@ -1144,7 +1162,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 +1212,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 +1264,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 +1432,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 3a5677fe2..7ca1c8744 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -133,14 +133,13 @@ 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) { + 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) { diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 7142c8bb0..0128c7871 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3724,6 +3724,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);