From 3137312911269ab29084700ba92ec1968f5458e3 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 15 Jan 2020 16:20:02 -0700 Subject: [PATCH] update to implementation of BIO_MD type --- src/bio.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl.c | 19 ++++++++++-- tests/api.c | 19 +++++++++--- 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/src/bio.c b/src/bio.c index 1f00af782..b7c6c5fe2 100644 --- a/src/bio.c +++ b/src/bio.c @@ -154,6 +154,23 @@ static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf, } #endif /* WOLFCRYPT_ONLY */ +static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) +{ + int ret = sz; + + if (wolfSSL_EVP_MD_CTX_type(bio->ptr) == (NID_hmac & 0xFF)) { + if (wolfSSL_EVP_DigestSignUpdate(bio->ptr, buf, sz) != WOLFSSL_SUCCESS) + { + ret = WOLFSSL_FATAL_ERROR; + } + } + else { + if (wolfSSL_EVP_DigestUpdate(bio->ptr, buf, ret) != WOLFSSL_SUCCESS) { + ret = WOLFSSL_FATAL_ERROR; + } + } + return ret; +} /* Used to read data from a WOLFSSL_BIO structure @@ -218,6 +235,11 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } #endif + /* data passing through BIO MD wrapper */ + if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { + ret = wolfSSL_BIO_MD_read(bio, buf, ret); + } + /* case where front of list is done */ if (bio == front) { break; /* at front of list so be done */ @@ -423,6 +445,33 @@ static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data, } +/* Helper function for writing to a WOLFSSL_BIO_MD type + * + * returns the amount written in bytes on success (0) + */ +static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) +{ + int ret = 0; + + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + if (wolfSSL_EVP_MD_CTX_type(bio->ptr) == (NID_hmac & 0xFF)) { + if (wolfSSL_EVP_DigestSignUpdate(bio->ptr, data, len) != + WOLFSSL_SUCCESS) { + ret = WOLFSSL_BIO_ERROR; + } + } + else { + if (wolfSSL_EVP_DigestUpdate(bio->ptr, data, len) != WOLFSSL_SUCCESS) { + ret = WOLFSSL_BIO_ERROR; + } + } + return ret; +} + + /* Writes data to a WOLFSSL_BIO structure * * bio structure to write to @@ -536,6 +585,12 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) } #endif /* WOLFCRYPT_ONLY */ + if (bio && bio->type == WOLFSSL_BIO_MD) { + if (bio->next != NULL) { /* data passing through MD BIO */ + ret = wolfSSL_BIO_MD_write(bio, data, len); + } + } + /* advance to the next bio in list */ bio = bio->next; } @@ -740,6 +795,22 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) break; } + /* call final on hash */ + case WOLFSSL_BIO_MD: + if (wolfSSL_EVP_MD_CTX_size(bio->ptr) > sz) { + WOLFSSL_MSG("Output buffer was too small for digest"); + ret = WOLFSSL_FAILURE; + } + else { + unsigned int szOut = 0; + ret = wolfSSL_EVP_DigestFinal(bio->ptr, (unsigned char*)buf, + &szOut); + if (ret == WOLFSSL_SUCCESS) { + ret = szOut; + } + } + break; + default: WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets"); } @@ -855,6 +926,16 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) return 0; } + if (bio->type == WOLFSSL_BIO_MD) { + /* MD is a wrapper only get next bio */ + while (bio->next != NULL) { + bio = bio->next; + if (bio->type != WOLFSSL_BIO_MD) { + break; + } + } + } + #ifndef WOLFCRYPT_ONLY if (bio->type == WOLFSSL_BIO_SSL && bio->ptr != NULL) { return (long)wolfSSL_pending((WOLFSSL*)bio->ptr); @@ -1205,6 +1286,14 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) } return 0; + case WOLFSSL_BIO_MD: + if (bio->ptr != NULL) { + const WOLFSSL_EVP_MD* md = wolfSSL_EVP_MD_CTX_md(bio->ptr); + wolfSSL_EVP_MD_CTX_init(bio->ptr); + wolfSSL_EVP_DigestInit(bio->ptr, md); + } + return 0; + default: WOLFSSL_MSG("Unknown BIO type needs added to reset function"); } diff --git a/src/ssl.c b/src/ssl.c index 0128073bb..727a1dbcc 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15162,8 +15162,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if ((bio != NULL) && (mdcp != NULL)) { *mdcp = bio->ptr; - - /* TODO: reset bio */ + ret = WOLFSSL_SUCCESS; } return ret; @@ -15318,7 +15317,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) bio->shutdown = BIO_CLOSE; /* default to close things */ bio->init = 1; if (method->type != WOLFSSL_BIO_FILE && - method->type != WOLFSSL_BIO_SOCKET) { + method->type != WOLFSSL_BIO_SOCKET && + method->type != WOLFSSL_BIO_MD) { bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), 0, DYNAMIC_TYPE_OPENSSL); if (bio->mem_buf == NULL) { @@ -15329,6 +15329,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) bio->mem_buf->data = (char*)bio->ptr; } + if (method->type == WOLFSSL_BIO_MD) { + bio->ptr = wolfSSL_EVP_MD_CTX_new(); + if (bio->ptr == NULL) { + WOLFSSL_MSG("Memory error"); + wolfSSL_BIO_free(bio); + return NULL; + } + } + /* check if is custom method */ if (method->createCb) { method->createCb(bio); @@ -15433,6 +15442,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } } + if (bio->type == WOLFSSL_BIO_MD) { + wolfSSL_EVP_MD_CTX_free(bio->ptr); + } + XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); } return 1; diff --git a/tests/api.c b/tests/api.c index 85e1128b8..139cbf93e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -24023,8 +24023,6 @@ static void test_wolfSSL_BIO_printf(void) static void test_wolfSSL_BIO_f_md(void) { -/* tests not passing */ -#if 0 #if defined(OPENSSL_ALL) && !defined(NO_SHA256) BIO *bio, *mem; char msg[] = "message to hash"; @@ -24051,6 +24049,13 @@ static void test_wolfSSL_BIO_f_md(void) 0x70, 0x5A, 0xF6, 0xD7, 0xC4, 0x1F, 0x1A, 0xE4, 0x2D, 0xA6, 0xFD, 0xD1, 0x29, 0x7D, 0x60, 0x0D }; + const unsigned char emptyHash[] = + { + 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, + 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, + 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, + 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55 + }; unsigned char check[sizeof(testResult) + 1]; size_t checkSz = -1; EVP_PKEY* key; @@ -24064,10 +24069,15 @@ static void test_wolfSSL_BIO_f_md(void) AssertIntEQ(BIO_get_md_ctx(bio, &ctx), 1); AssertIntEQ(EVP_DigestInit(ctx, EVP_sha256()), 1); - /* should not be able to write/read yet since just digest wrapper */ - AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), 0); + /* should not be able to write/read yet since just digest wrapper and no + * data is passing through the bio */ + AssertIntEQ(BIO_write(bio, msg, 0), 0); AssertIntEQ(BIO_pending(bio), 0); AssertIntEQ(BIO_read(bio, out, sizeof(out)), 0); + AssertIntEQ(BIO_gets(bio, out, 3), 0); + AssertIntEQ(BIO_gets(bio, out, sizeof(out)), 32); + AssertIntEQ(XMEMCMP(emptyHash, out, 32), 0); + BIO_reset(bio); /* append BIO mem to bio in order to read/write */ AssertNotNull(bio = BIO_push(bio, mem)); @@ -24110,7 +24120,6 @@ static void test_wolfSSL_BIO_f_md(void) printf(resultFmt, passed); #endif -#endif }