From f7737fdc5593d410bc586fb1ffb3a32a47c4c48a Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 8 Dec 2016 09:10:54 -0700 Subject: [PATCH] expand BIO compatibility --- .gitignore | 3 +- src/bio.c | 450 +++++++++++++++++++++++++++++++++--------- src/ssl.c | 119 ++++++++--- tests/api.c | 177 ++++++++++++++++- wolfcrypt/src/evp.c | 3 +- wolfssl/internal.h | 23 ++- wolfssl/openssl/ssl.h | 6 + wolfssl/ssl.h | 38 ++-- 8 files changed, 678 insertions(+), 141 deletions(-) diff --git a/.gitignore b/.gitignore index b22328702..cd9de3c0f 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ testsuite/testsuite tests/unit testsuite/testsuite.test tests/unit.test +tests/bio_write_test.txt testsuite/*.der testsuite/*.pem testsuite/*.raw @@ -188,4 +189,4 @@ wolfcrypt/user-crypto/lib/libusercrypto.* wrapper/CSharp/x64/ # Visual Studio Code Workspace Files -*.vscode \ No newline at end of file +*.vscode diff --git a/src/bio.c b/src/bio.c index 5210f40ce..39f160a63 100644 --- a/src/bio.c +++ b/src/bio.c @@ -31,12 +31,38 @@ WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *pa return 1; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b) + +/* Return the number of pending bytes in read and write buffers */ +size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) { - (void) b; WOLFSSL_ENTER("BIO_ctrl_pending"); - return 0; + if (bio == NULL) { + return 0; + } + + if (bio->ssl != NULL) { + return (long)wolfSSL_pending(bio->ssl); + } + + if (bio->type == BIO_MEMORY) { + return bio->memLen; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) { + /* in wrap around state where begining of buffer is being + * overwritten */ + return pair->wrSz - pair->rdIdx + pair->wrIdx; + } + else { + /* simple case where has not wrapped around */ + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; } @@ -63,115 +89,355 @@ WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int i return 0; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size) + +int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) { - (void) b; - (void) size; - WOLFSSL_ENTER("BIO_set_write_buf_size"); + WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); + + if (bio == NULL || bio->type != BIO_BIO || size < 0) { + return SSL_FAILURE; + } + + /* if already in pair then do not change size */ + if (bio->pair != NULL) { + WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing"); + return SSL_FAILURE; + } + + bio->wrSz = (int)size; + if (bio->wrSz < 0) { + WOLFSSL_MSG("Unexpected negative size value"); + return SSL_FAILURE; + } + + if (bio->mem != NULL) { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + } + + bio->mem = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Memory allocation error"); + return SSL_FAILURE; + } + bio->wrIdx = 0; + bio->rdIdx = 0; + + return SSL_SUCCESS; +} + + +/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vise + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. */ +int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) +{ + WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair"); + + if (b1 == NULL || b2 == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + /* both are expected to be of type BIO and not already paired */ + if (b1->type != BIO_BIO || b2->type != BIO_BIO || + b1->pair != NULL || b2->pair != NULL) { + WOLFSSL_MSG("Expected type BIO and not already paired"); + return SSL_FAILURE; + } + + /* set default write size if not already set */ + if (b1->mem == NULL && wolfSSL_BIO_set_write_buf_size(b1, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + if (b2->mem == NULL && wolfSSL_BIO_set_write_buf_size(b2, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + b1->pair = b2; + b2->pair = b1; + + return SSL_SUCCESS; +} + + +int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); + + if (b == NULL) { + return SSL_FAILURE; + } + + b->readRq = 0; + + return SSL_SUCCESS; +} + + +/* Does not advance read index pointer */ +int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) +{ + WOLFSSL_ENTER("wolfSSL_BIO_nread0"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + /* if paired read from pair */ + if (bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + + /* case where have wrapped around write buffer */ + *buf = (char*)pair->mem + pair->rdIdx; + if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) { + return pair->wrSz - pair->rdIdx; + } + else { + return pair->wrIdx - pair->rdIdx; + } + } + return 0; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) + +/* similar to wolfSSL_BIO_nread0 but advances the read index */ +int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) { - (void) b1; - (void) b2; - WOLFSSL_ENTER("BIO_make_bio_pair"); - return 0; + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nread"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + /* special case if asking to read 0 bytes */ + if (num == 0) { + *buf = (char*)bio->pair->mem + bio->pair->rdIdx; + return 0; + } + + /* get amount able to read and set buffer pointer */ + sz = wolfSSL_BIO_nread0(bio, buf); + if (sz == 0) { + return WOLFSSL_BIO_ERROR; + } + + if (num < sz) { + sz = num; + } + bio->pair->rdIdx += sz; + + /* check if have read to the end of the buffer and need to reset */ + if (bio->pair->rdIdx == bio->pair->wrSz) { + bio->pair->rdIdx = 0; + if (bio->pair->wrIdx == bio->pair->wrSz) { + bio->pair->wrIdx = 0; + } + } + + /* check if read up to write index, if so then reset indexs */ + if (bio->pair->rdIdx == bio->pair->wrIdx) { + bio->pair->rdIdx = 0; + bio->pair->wrIdx = 0; + } + } + + return sz; } -/*** TBD ***/ -WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) + +int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) { - (void) b; - WOLFSSL_ENTER("BIO_ctrl_reset_read_request"); - return 0; + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nwrite"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + if (bio->pair != NULL) { + if (num == 0) { + *buf = (char*)bio->mem + bio->wrIdx; + return 0; + } + + if (bio->wrIdx < bio->rdIdx) { + /* if wrapped around only write up to read index. In this case + * rdIdx is always greater then wrIdx so sz will not be negative. */ + sz = bio->rdIdx - bio->wrIdx; + } + else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) { + return WOLFSSL_BIO_ERROR; /* no more room to write */ + } + else { + /* write index is past read index so write to end of buffer */ + sz = bio->wrSz - bio->wrIdx; + + if (sz <= 0) { + /* either an error has occured with write index or it is at the + * end of the write buffer. */ + if (bio->rdIdx == 0) { + /* no more room, nothing has been read */ + return WOLFSSL_BIO_ERROR; + } + + bio->wrIdx = 0; + + /* check case where read index is not at 0 */ + if (bio->rdIdx > 0) { + sz = bio->rdIdx; /* can write up to the read index */ + } + else { + sz = bio->wrSz; /* no restriction other then buffer size */ + } + } + } + + if (num < sz) { + sz = num; + } + *buf = (char*)bio->mem + bio->wrIdx; + bio->wrIdx += sz; + + /* if at the end of the buffer and space for wrap around then set + * write index back to 0 */ + if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) { + bio->wrIdx = 0; + } + } + + return sz; } -/*** TBD ***/ -WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) + +/* Reset BIO to initial state */ +int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) { - (void) bio; - (void) buf; - WOLFSSL_ENTER("BIO_nread0"); - return 0; + WOLFSSL_ENTER("wolfSSL_BIO_reset"); + + if (bio == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + /* -1 is consistent failure even for FILE type */ + return WOLFSSL_BIO_ERROR; + } + + switch (bio->type) { + case BIO_FILE: + XREWIND(bio->file); + return 0; + + case BIO_BIO: + bio->rdIdx = 0; + bio->wrIdx = 0; + return 0; + + default: + WOLFSSL_MSG("Unknown BIO type needs added to reset function"); + } + + return WOLFSSL_BIO_ERROR; } -/*** TBD ***/ -WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) -{ - (void) bio; - (void) buf; - (void) num; - WOLFSSL_ENTER("BIO_nread"); - return 0; -} - -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) -{ - (void) bio; - (void) buf; - (void) num; - WOLFSSL_ENTER("BIO_nwrite"); - return 0; -} - -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_reset(WOLFSSL_BIO *bio) -{ - (void) bio; - WOLFSSL_ENTER("BIO_reset"); - return 0; -} - -#if 0 #ifndef NO_FILESYSTEM -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) +long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) { - (void) bio; - (void) fp; - (void) c; - WOLFSSL_ENTER("BIO_set_fp"); + WOLFSSL_ENTER("wolfSSL_BIO_set_fp"); + + if (bio == NULL || fp == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + bio->close = (byte)c; + bio->file = fp; + + return SSL_SUCCESS; +} + + +long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); + + if (bio == NULL || fp == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + *fp = bio->file; + + return SSL_SUCCESS; +} + +/* overwrites file */ +int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) +{ + WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); + + if (bio == NULL || name == NULL) { + return SSL_FAILURE; + } + + if (bio->type == BIO_FILE) { + if (bio->file != NULL && bio->close == BIO_CLOSE) { + XFCLOSE(bio->file); + } + + bio->file = XFOPEN(name, "w"); + if (bio->file == NULL) { + return SSL_FAILURE; + } + bio->close = BIO_CLOSE; + + return SSL_SUCCESS; + } + + return SSL_FAILURE; +} +#endif /* NO_FILESYSTEM */ + +int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +{ + WOLFSSL_ENTER("wolfSSL_BIO_seek"); + + if (bio == NULL) { + return -1; + } + + /* offset ofs from begining of file */ + if (bio->type == BIO_FILE && XFSEEK(bio->file, ofs, SEEK_SET) < 0) { + return -1; + } + return 0; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE fp) -{ - (void) bio; - (void) fp; - WOLFSSL_ENTER("BIO_get_fp"); - return 0; -} -#endif -#endif -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) { - (void) bio; - (void) ofs; - WOLFSSL_ENTER("BIO_seek"); - return 0; -} + WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return"); -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) -{ - (void) bio; - (void) name; - WOLFSSL_ENTER("BIO_write_filename"); - return 0; -} + if (bio != NULL) { + bio->eof = v; + } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) -{ - (void) bio; - (void) v; - WOLFSSL_ENTER("BIO_set_mem_eof_return"); return 0; } diff --git a/src/ssl.c b/src/ssl.c index 9d09cc085..c31de34ff 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -10044,6 +10044,28 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void) + { + static WOLFSSL_BIO_METHOD bio_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_bio"); + bio_meth.type = BIO_BIO; + + return &bio_meth; + } + + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) + { + static WOLFSSL_BIO_METHOD file_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_file"); + file_meth.type = BIO_FILE; + + return &file_meth; + } + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) { static WOLFSSL_BIO_METHOD meth; @@ -10073,15 +10095,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("BIO_new_socket"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = BIO_SOCKET; bio->close = (byte)closeF; - bio->eof = 0; - bio->ssl = 0; bio->fd = sfd; - bio->prev = 0; - bio->next = 0; bio->mem = NULL; - bio->memLen = 0; } return bio; } @@ -10124,13 +10142,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) DYNAMIC_TYPE_OPENSSL); WOLFSSL_ENTER("BIO_new"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = method->type; - bio->close = 0; - bio->eof = 0; bio->ssl = NULL; bio->mem = NULL; - bio->memLen = 0; - bio->fd = 0; bio->prev = NULL; bio->next = NULL; } @@ -10184,17 +10199,29 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_BIO_free(WOLFSSL_BIO* bio) { /* unchain?, doesn't matter in goahead since from free all */ - WOLFSSL_ENTER("BIO_free"); + WOLFSSL_ENTER("wolfSSL_BIO_free"); if (bio) { + /* remove from pair by setting the paired bios pair to NULL */ + if (bio->pair != NULL) { + bio->pair->pair = NULL; + } + if (bio->close) { if (bio->ssl) wolfSSL_free(bio->ssl); if (bio->fd) CloseSocket(bio->fd); } + + if (bio->type == BIO_FILE && bio->close == BIO_CLOSE) { + if (bio->file) { + XFCLOSE(bio->file); + } + } + if (bio->mem) - XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + XFREE(bio, bio->heap, DYNAMIC_TYPE_OPENSSL); } return 0; } @@ -10212,13 +10239,37 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) + { + int sz; + char* pt; + + sz = wolfSSL_BIO_nread(bio, &pt, len); + + if (sz > 0) { + XMEMCPY(buf, pt, sz); + } + + return sz; + } + + int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; - WOLFSSL_ENTER("BIO_read"); + WOLFSSL_ENTER("wolfSSL_BIO_read"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_read(bio, buf, len); + } + + if (bio && bio->type == BIO_FILE) { + return (int)XFREAD(buf, 1, len, bio->file); + } + /* already got eof, again is error */ if (front->eof) return SSL_FATAL_ERROR; @@ -10240,13 +10291,43 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, + int len) + { + /* internal function where arguments have already been sanity checked */ + int sz; + char* buf; + + sz = wolfSSL_BIO_nwrite(bio, &buf, len); + + /* test space for write */ + if (sz <= 0) { + WOLFSSL_MSG("No room left to write"); + return sz; + } + + XMEMCPY(buf, data, sz); + + return sz; + } + + int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; - WOLFSSL_ENTER("BIO_write"); + WOLFSSL_ENTER("wolfSSL_BIO_write"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_write(bio, data, len); + } + + if (bio && bio->type == BIO_FILE) { + return (int)XFWRITE(data, 1, len, bio->file); + } + /* already got eof, again is error */ if (front->eof) return SSL_FATAL_ERROR; @@ -10802,7 +10883,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) { WOLFSSL_EVP_MD_CTX* ctx; WOLFSSL_ENTER("EVP_MD_CTX_new"); - ctx=XMALLOC(sizeof *ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_TMP_BUFFER); if (ctx){ wolfSSL_EVP_MD_CTX_init(ctx); } @@ -20145,13 +20227,6 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return 0; } - WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) { - WOLFSSL_ENTER("wolfSSL_BIO_s_file"); - WOLFSSL_STUB("wolfSSL_BIO_s_file"); - - return NULL; - } - #ifdef HAVE_ECC const char * wolfSSL_OBJ_nid2sn(int n) { int i; diff --git a/tests/api.c b/tests/api.c index d651f9983..a2fe23374 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1981,7 +1981,7 @@ static void test_wolfSSL_DisableExtendedMasterSecret(void) *----------------------------------------------------------------------------*/ static void test_wolfSSL_X509_NAME_get_entry(void) { -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_RSA) #if defined(OPENSSL_EXTRA) && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)) \ && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) printf(testingFmt, "wolfSSL_X509_NAME_get_entry()"); @@ -2029,7 +2029,7 @@ static void test_wolfSSL_PKCS12(void) { /* .p12 file is encrypted with DES3 */ #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ - !defined(NO_ASN) && !defined(NO_PWDBASED) + !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) byte buffer[5300]; char file[] = "./certs/test-servercert.p12"; FILE *f; @@ -2529,7 +2529,7 @@ static void test_wolfSSL_PEM_PrivateKey(void) static void test_wolfSSL_tmp_dh(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - !defined(NO_FILESYSTEM) && !defined(NO_DSA) + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) byte buffer[5300]; char file[] = "./certs/dsaparams.pem"; FILE *f; @@ -2826,6 +2826,176 @@ static void test_wolfSSL_PEM_read_bio(void) } +static void test_wolfSSL_BIO(void) +{ + #if defined(OPENSSL_EXTRA) + byte buffer[20]; + BIO* bio1; + BIO* bio2; + BIO* bio3; + char* bufPt; + int i; + + printf(testingFmt, "wolfSSL_BIO()"); + + for (i = 0; i < 20; i++) { + buffer[i] = i; + } + + /* Creating and testing type BIO_s_bio */ + AssertNotNull(bio1 = BIO_new(BIO_s_bio())); + AssertNotNull(bio2 = BIO_new(BIO_s_bio())); + AssertNotNull(bio3 = BIO_new(BIO_s_bio())); + + /* read/write before set up */ + AssertIntEQ(BIO_read(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + AssertIntEQ(BIO_write(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + + AssertIntEQ(BIO_set_write_buf_size(bio1, 20), SSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio2, 8), SSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio1, bio2), SSL_SUCCESS); + + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 10), 10); + XMEMCPY(bufPt, buffer, 10); + AssertIntEQ(BIO_write(bio1, buffer + 10, 10), 10); + /* write buffer full */ + AssertIntEQ(BIO_write(bio1, buffer, 10), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_flush(bio1), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio1), 0); + + /* write the other direction with pair */ + AssertIntEQ((int)BIO_nwrite(bio2, &bufPt, 10), 8); + XMEMCPY(bufPt, buffer, 8); + AssertIntEQ(BIO_write(bio2, buffer, 10), WOLFSSL_BIO_ERROR); + + /* try read */ + AssertIntEQ((int)BIO_ctrl_pending(bio1), 8); + AssertIntEQ((int)BIO_ctrl_pending(bio2), 20); + + AssertIntEQ(BIO_nread(bio2, &bufPt, (int)BIO_ctrl_pending(bio2)), 20); + for (i = 0; i < 20; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio2, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio1, &bufPt, (int)BIO_ctrl_pending(bio1)), 8); + for (i = 0; i < 8; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio1, &bufPt, 1), WOLFSSL_BIO_ERROR); + + /* new pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_FAILURE); + BIO_free(bio2); /* free bio2 and automaticly remove from pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 10), WOLFSSL_BIO_ERROR); + + /* test wrap around... */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ(BIO_reset(bio3), 0); + + /* fill write buffer, read only small amount then write again */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 4), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* try writing over read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 5), 4); + XMEMSET(bufPt, 0, 4); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 20); + + /* read and write 0 bytes */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 0), 0); + + /* should read only to end of write buffer then need to read again */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 20), 16); + for (i = 0; i < 16; i++) { + AssertIntEQ(bufPt[i], buffer[4 + i]); + } + + AssertIntEQ(BIO_nread(bio3, NULL, 0), SSL_FAILURE); + AssertIntEQ(BIO_nread0(bio3, &bufPt), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* read index should not have advanced with nread0 */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 5), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* write and fill up buffer checking reset of index state */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + + /* test reset on data in bio1 write buffer */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 3), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 6), 6); + for (i = 0; i < 6; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* test case of writing twice with offset read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 3), 3); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 3); /* try overwriting */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 1), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + + BIO_free(bio1); + BIO_free(bio3); + + /* BIOs with file pointers */ + #if !defined(NO_FILESYSTEM) + { + XFILE f1; + XFILE f2; + BIO* f_bio1; + BIO* f_bio2; + unsigned char cert[300]; + char testFile[] = "tests/bio_write_test.txt"; + char msg[] = "bio_write_test.txt contains the first 300 bytes of certs/server-cert.pem\ncreated by tests/unit.test\n\n"; + + AssertNotNull(f_bio1 = BIO_new(BIO_s_file())); + AssertNotNull(f_bio2 = BIO_new(BIO_s_file())); + + AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); + AssertIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0); + + f1 = XFOPEN(svrCert, "rwb"); + AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), SSL_SUCCESS); + AssertIntEQ(BIO_write_filename(f_bio2, testFile), + SSL_SUCCESS); + + AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); + AssertIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg)); + AssertIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert)); + + AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), SSL_SUCCESS); + + BIO_free(f_bio1); + BIO_free(f_bio2); + } + #endif /* !defined(NO_FILESYSTEM) */ + + + printf(resultFmt, passed); + #endif +} + + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -2883,6 +3053,7 @@ void ApiTest(void) test_wolfSSL_BN(); test_wolfSSL_set_options(); test_wolfSSL_PEM_read_bio(); + test_wolfSSL_BIO(); AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); printf(" End API Tests\n"); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 8887b969f..02b783c5e 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -57,7 +57,8 @@ WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) { - WOLFSSL_EVP_CIPHER_CTX *ctx=XMALLOC(sizeof *ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, + NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx){ WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); wolfSSL_EVP_CIPHER_CTX_init(ctx); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e4be17b18..44fdb36b4 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1249,7 +1249,9 @@ enum BIO_TYPE { BIO_BUFFER = 1, BIO_SOCKET = 2, BIO_SSL = 3, - BIO_MEMORY = 4 + BIO_MEMORY = 4, + BIO_BIO = 5, + BIO_FILE = 6 }; @@ -1261,15 +1263,22 @@ struct WOLFSSL_BIO_METHOD { /* wolfSSL BIO type */ struct WOLFSSL_BIO { - byte type; /* method type */ - byte close; /* close flag */ - byte eof; /* eof flag */ WOLFSSL* ssl; /* possible associated ssl */ - byte* mem; /* memory buffer */ - int memLen; /* memory buffer length */ - int fd; /* possible file descriptor */ + XFILE file; WOLFSSL_BIO* prev; /* previous in chain */ WOLFSSL_BIO* next; /* next in chain */ + WOLFSSL_BIO* pair; /* BIO paired with */ + void* heap; /* user heap hint */ + byte* mem; /* memory buffer */ + int wrSz; /* write buffer size (mem) */ + int wrIdx; /* current index for write buffer */ + int rdIdx; /* current read index */ + int readRq; /* read request */ + int memLen; /* memory buffer length */ + int fd; /* possible file descriptor */ + int eof; /* eof flag */ + byte type; /* method type */ + byte close; /* close flag */ }; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index f94be0a92..f26ad2cf3 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -236,7 +236,11 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define BIO_new wolfSSL_BIO_new #define BIO_free wolfSSL_BIO_free #define BIO_free_all wolfSSL_BIO_free_all +#define BIO_nread0 wolfSSL_BIO_nread0 +#define BIO_nread wolfSSL_BIO_nread #define BIO_read wolfSSL_BIO_read +#define BIO_nwrite0 wolfSSL_BIO_nwrite0 +#define BIO_nwrite wolfSSL_BIO_nwrite #define BIO_write wolfSSL_BIO_write #define BIO_push wolfSSL_BIO_push #define BIO_pop wolfSSL_BIO_pop @@ -517,6 +521,8 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define BIO_get_mem_ptr wolfSSL_BIO_get_mem_ptr #define BIO_int_ctrl wolfSSL_BIO_int_ctrl #define BIO_reset wolfSSL_BIO_reset +#define BIO_s_file wolfSSL_BIO_s_file +#define BIO_s_bio wolfSSL_BIO_s_bio #define BIO_s_socket wolfSSL_BIO_s_socket #define BIO_set_fd wolfSSL_BIO_set_fd diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 23438c677..522d6759f 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -519,29 +519,23 @@ WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag); WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); WOLFSSL_API int wolfSSL_add_all_algorithms(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); WOLFSSL_API const WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); -WOLFSSL_API long wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); -WOLFSSL_API long wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); -WOLFSSL_API long wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); +WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); +WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b); WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf); WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num); -WOLFSSL_API long wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); -WOLFSSL_API long wolfSSL_BIO_reset(WOLFSSL_BIO *bio); +WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); -#if 0 -#ifndef NO_FILESYSTEM -WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); -WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE fp); -#endif -#endif - -WOLFSSL_API long wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); -WOLFSSL_API long wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); +WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); @@ -938,6 +932,14 @@ enum { /* ERR Constants */ ERR_TXT_STRING = 1 }; +/* bio misc */ +enum { + WOLFSSL_BIO_ERROR = -1, + WOLFSSL_BIO_UNSET = -2, + WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ +}; + + WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, const char**, int *); @@ -1906,6 +1908,12 @@ WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, #endif /* WOLFSSL_MYSQL_COMPATIBLE */ #ifdef OPENSSL_EXTRA + +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); +WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); +#endif + WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); @@ -1939,6 +1947,7 @@ WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509); WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); +WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, size_t outlen); WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, @@ -1965,7 +1974,6 @@ struct WOLFSSL_X509_NAME_ENTRY { WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name); WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); -WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void); /* These are to be merged shortly */ WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);