Files
wolfssl/tests/api/test_ossl_bio.c
2025-08-05 07:22:04 -07:00

1161 lines
39 KiB
C

/* test_ossl_bio.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <tests/unit.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
#include <wolfssl/openssl/buffer.h>
#include <wolfssl/wolfcrypt/types.h>
#include <tests/api/api.h>
#include <tests/api/test_ossl_bio.h>
/*******************************************************************************
* BIO OpenSSL compatibility API Testing
******************************************************************************/
#ifndef NO_BIO
int test_wolfSSL_BIO_gets(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA)
BIO* bio = NULL;
BIO* bio2 = NULL;
char msg[] = "\nhello wolfSSL\n security plus\t---...**adf\na...b.c";
char emp[] = "";
char bio_buffer[20];
int bufferSz = 20;
#ifdef OPENSSL_ALL
BUF_MEM* emp_bm = NULL;
BUF_MEM* msg_bm = NULL;
#endif
/* try with bad args */
ExpectNull(bio = BIO_new_mem_buf(NULL, sizeof(msg)));
#ifdef OPENSSL_ALL
ExpectIntEQ(BIO_set_mem_buf(bio, NULL, BIO_NOCLOSE), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
/* try with real msg */
ExpectNotNull(bio = BIO_new_mem_buf((void*)msg, -1));
XMEMSET(bio_buffer, 0, bufferSz);
ExpectNotNull(BIO_push(bio, BIO_new(BIO_s_bio())));
ExpectNull(bio2 = BIO_find_type(bio, BIO_TYPE_FILE));
ExpectNotNull(bio2 = BIO_find_type(bio, BIO_TYPE_BIO));
ExpectFalse(bio2 != BIO_next(bio));
/* make buffer filled with no terminating characters */
XMEMSET(bio_buffer, 1, bufferSz);
/* BIO_gets reads a line of data */
ExpectIntEQ(BIO_gets(bio, bio_buffer, -3), 0);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 14);
ExpectStrEQ(bio_buffer, "hello wolfSSL\n");
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 19);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 8);
ExpectIntEQ(BIO_gets(bio, bio_buffer, -1), 0);
#ifdef OPENSSL_ALL
/* test setting the mem_buf manually */
BIO_free(bio);
ExpectNotNull(bio = BIO_new_mem_buf((void*)msg, -1));
ExpectNotNull(emp_bm = BUF_MEM_new());
ExpectNotNull(msg_bm = BUF_MEM_new());
ExpectIntEQ(BUF_MEM_grow(msg_bm, sizeof(msg)), sizeof(msg));
if (EXPECT_SUCCESS()) {
XFREE(msg_bm->data, NULL, DYNAMIC_TYPE_OPENSSL);
msg_bm->data = NULL;
}
/* emp size is 1 for terminator */
ExpectIntEQ(BUF_MEM_grow(emp_bm, sizeof(emp)), sizeof(emp));
if (EXPECT_SUCCESS()) {
XFREE(emp_bm->data, NULL, DYNAMIC_TYPE_OPENSSL);
emp_bm->data = emp;
msg_bm->data = msg;
}
ExpectIntEQ(BIO_set_mem_buf(bio, emp_bm, BIO_CLOSE), WOLFSSL_SUCCESS);
/* check reading an empty string */
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1); /* just terminator */
ExpectStrEQ(emp, bio_buffer);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 0); /* Nothing to read */
/* BIO_gets reads a line of data */
ExpectIntEQ(BIO_set_mem_buf(bio, msg_bm, BIO_NOCLOSE), WOLFSSL_SUCCESS);
ExpectIntEQ(BIO_gets(bio, bio_buffer, -3), 0);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 14);
ExpectStrEQ(bio_buffer, "hello wolfSSL\n");
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 19);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 8);
ExpectIntEQ(BIO_gets(bio, bio_buffer, -1), 0);
if (EXPECT_SUCCESS())
emp_bm->data = NULL;
BUF_MEM_free(emp_bm);
if (EXPECT_SUCCESS())
msg_bm->data = NULL;
BUF_MEM_free(msg_bm);
#endif
/* check not null terminated string */
BIO_free(bio);
bio = NULL;
msg[0] = 0x33;
msg[1] = 0x33;
msg[2] = 0x33;
ExpectNotNull(bio = BIO_new_mem_buf((void*)msg, 3));
ExpectIntEQ(BIO_gets(bio, bio_buffer, 3), 2);
ExpectIntEQ(bio_buffer[0], msg[0]);
ExpectIntEQ(bio_buffer[1], msg[1]);
ExpectIntNE(bio_buffer[2], msg[2]);
BIO_free(bio);
bio = NULL;
msg[3] = 0x33;
bio_buffer[3] = 0x33;
ExpectNotNull(bio = BIO_new_mem_buf((void*)msg, 3));
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 3);
ExpectIntEQ(bio_buffer[0], msg[0]);
ExpectIntEQ(bio_buffer[1], msg[1]);
ExpectIntEQ(bio_buffer[2], msg[2]);
ExpectIntNE(bio_buffer[3], 0x33); /* make sure null terminator was set */
/* check reading an empty string */
BIO_free(bio);
bio = NULL;
ExpectNotNull(bio = BIO_new_mem_buf((void*)emp, sizeof(emp)));
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1); /* just terminator */
ExpectStrEQ(emp, bio_buffer);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 0); /* Nothing to read */
/* check error cases */
BIO_free(bio);
bio = NULL;
ExpectIntEQ(BIO_gets(NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(BIO_gets(bio, bio_buffer, 2), 0); /* nothing to read */
#if !defined(NO_FILESYSTEM)
{
BIO* f_bio = NULL;
XFILE f = XBADFILE;
ExpectNotNull(f_bio = BIO_new(BIO_s_file()));
ExpectIntLE(BIO_gets(f_bio, bio_buffer, bufferSz), 0);
ExpectTrue((f = XFOPEN(svrCertFile, "rb")) != XBADFILE);
ExpectIntEQ((int)BIO_set_fp(f_bio, f, BIO_CLOSE), SSL_SUCCESS);
if (EXPECT_FAIL() && (f != XBADFILE)) {
XFCLOSE(f);
}
ExpectIntGT(BIO_gets(f_bio, bio_buffer, bufferSz), 0);
BIO_free(f_bio);
f_bio = NULL;
}
#endif /* NO_FILESYSTEM */
BIO_free(bio);
bio = NULL;
BIO_free(bio2);
bio2 = NULL;
/* try with type BIO */
XMEMCPY(msg, "\nhello wolfSSL\n security plus\t---...**adf\na...b.c",
sizeof(msg));
ExpectNotNull(bio = BIO_new(BIO_s_bio()));
ExpectIntEQ(BIO_gets(bio, bio_buffer, 2), 0); /* nothing to read */
ExpectNotNull(bio2 = BIO_new(BIO_s_bio()));
ExpectIntEQ(BIO_set_write_buf_size(bio, 10), SSL_SUCCESS);
ExpectIntEQ(BIO_set_write_buf_size(bio2, sizeof(msg)), SSL_SUCCESS);
ExpectIntEQ(BIO_make_bio_pair(bio, bio2), SSL_SUCCESS);
ExpectIntEQ(BIO_write(bio2, msg, sizeof(msg)), sizeof(msg));
ExpectIntEQ(BIO_gets(bio, bio_buffer, -3), 0);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 14);
ExpectStrEQ(bio_buffer, "hello wolfSSL\n");
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 19);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 8);
ExpectIntEQ(BIO_gets(bio, bio_buffer, -1), 0);
BIO_free(bio);
bio = NULL;
BIO_free(bio2);
bio2 = NULL;
/* check reading an empty string */
ExpectNotNull(bio = BIO_new(BIO_s_bio()));
ExpectIntEQ(BIO_set_write_buf_size(bio, sizeof(emp)), SSL_SUCCESS);
ExpectIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 0); /* Nothing to read */
ExpectStrEQ(emp, bio_buffer);
BIO_free(bio);
bio = NULL;
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_puts(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA)
BIO* bio = NULL;
char input[] = "hello\0world\n.....ok\n\0";
char output[128];
XMEMSET(output, 0, sizeof(output));
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(BIO_puts(bio, input), 5);
ExpectIntEQ(BIO_pending(bio), 5);
ExpectIntEQ(BIO_puts(bio, input + 6), 14);
ExpectIntEQ(BIO_pending(bio), 19);
ExpectIntEQ(BIO_gets(bio, output, sizeof(output)), 11);
ExpectStrEQ(output, "helloworld\n");
ExpectIntEQ(BIO_pending(bio), 8);
ExpectIntEQ(BIO_gets(bio, output, sizeof(output)), 8);
ExpectStrEQ(output, ".....ok\n");
ExpectIntEQ(BIO_pending(bio), 0);
ExpectIntEQ(BIO_puts(bio, ""), -1);
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_dump(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA)
BIO* bio;
static const unsigned char data[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4,
0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5,
0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80,
0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA,
0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56,
0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42,
0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F,
0xB4
};
/* Generated with OpenSSL. */
static const char expected[] =
"0000 - 30 59 30 13 06 07 2a 86-48 ce 3d 02 01 06 08 2a 0Y0...*.H.=....*\n"
"0010 - 86 48 ce 3d 03 01 07 03-42 00 04 55 bf f4 0f 44 .H.=....B..U...D\n"
"0020 - 50 9a 3d ce 9b b7 f0 c5-4d f5 70 7b d4 ec 24 8e P.=.....M.p{..$.\n"
"0030 - 19 80 ec 5a 4c a2 24 03-62 2c 9b da ef a2 35 12 ...ZL.$.b,....5.\n"
"0040 - 43 84 76 16 c6 56 95 06-cc 01 a9 bd f6 75 1a 42 C.v..V.......u.B\n"
"0050 - f7 bd a9 b2 36 22 5f c7-5d 7f b4 ....6\"_.]..\n";
static const char expectedAll[] =
"0000 - 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f ................\n"
"0010 - 10 11 12 13 14 15 16 17-18 19 1a 1b 1c 1d 1e 1f ................\n"
"0020 - 20 21 22 23 24 25 26 27-28 29 2a 2b 2c 2d 2e 2f !\"#$%&'()*+,-./\n"
"0030 - 30 31 32 33 34 35 36 37-38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?\n"
"0040 - 40 41 42 43 44 45 46 47-48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO\n"
"0050 - 50 51 52 53 54 55 56 57-58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[\\]^_\n"
"0060 - 60 61 62 63 64 65 66 67-68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno\n"
"0070 - 70 71 72 73 74 75 76 77-78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~.\n"
"0080 - 80 81 82 83 84 85 86 87-88 89 8a 8b 8c 8d 8e 8f ................\n"
"0090 - 90 91 92 93 94 95 96 97-98 99 9a 9b 9c 9d 9e 9f ................\n"
"00a0 - a0 a1 a2 a3 a4 a5 a6 a7-a8 a9 aa ab ac ad ae af ................\n"
"00b0 - b0 b1 b2 b3 b4 b5 b6 b7-b8 b9 ba bb bc bd be bf ................\n"
"00c0 - c0 c1 c2 c3 c4 c5 c6 c7-c8 c9 ca cb cc cd ce cf ................\n"
"00d0 - d0 d1 d2 d3 d4 d5 d6 d7-d8 d9 da db dc dd de df ................\n"
"00e0 - e0 e1 e2 e3 e4 e5 e6 e7-e8 e9 ea eb ec ed ee ef ................\n"
"00f0 - f0 f1 f2 f3 f4 f5 f6 f7-f8 f9 fa fb fc fd fe ff ................\n";
char output[16 * 80];
int i;
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
/* Example key dumped. */
ExpectIntEQ(BIO_dump(bio, (const char*)data, (int)sizeof(data)),
sizeof(expected) - 1);
ExpectIntEQ(BIO_read(bio, output, sizeof(output)), sizeof(expected) - 1);
ExpectIntEQ(XMEMCMP(output, expected, sizeof(expected) - 1), 0);
/* Try every possible value for a character. */
for (i = 0; i < 256; i++)
output[i] = i;
ExpectIntEQ(BIO_dump(bio, output, 256), sizeof(expectedAll) - 1);
ExpectIntEQ(BIO_read(bio, output, sizeof(output)), sizeof(expectedAll) - 1);
ExpectIntEQ(XMEMCMP(output, expectedAll, sizeof(expectedAll) - 1), 0);
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
!defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \
defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(USE_WOLFSSL_IO)
static int forceWantRead(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
(void)ssl;
(void)buf;
(void)sz;
(void)ctx;
return WOLFSSL_CBIO_ERR_WANT_READ;
}
#endif
int test_wolfSSL_BIO_should_retry(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
!defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \
defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(USE_WOLFSSL_IO)
tcp_ready ready;
func_args server_args;
THREAD_TYPE serverThread;
SOCKET_T sockfd = 0;
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
char msg[64] = "hello wolfssl!";
char reply[1024];
int msgSz = (int)XSTRLEN(msg);
int ret;
BIO* bio = NULL;
XMEMSET(&server_args, 0, sizeof(func_args));
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
StartTCP();
InitTcpReady(&ready);
#if defined(USE_WINDOWS_API)
/* use RNG to get random port if using windows */
ready.port = GetRandomPort();
#endif
server_args.signal = &ready;
start_thread(test_server_nofail, &server_args, &serverThread);
wait_tcp_ready(&server_args);
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
#ifdef OPENSSL_COMPATIBLE_DEFAULTS
ExpectIntEQ(wolfSSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY), 0);
#endif
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM));
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM));
tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL);
/* force retry */
ExpectNotNull(bio = wolfSSL_BIO_new_ssl(ctx, 1));
ExpectIntEQ(BIO_get_ssl(bio, &ssl), 1);
ExpectNotNull(ssl);
ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS);
wolfSSL_SSLSetIORecv(ssl, forceWantRead);
if (EXPECT_FAIL()) {
wolfSSL_free(ssl);
ssl = NULL;
}
ExpectIntLE(BIO_write(bio, msg, msgSz), 0);
ExpectIntNE(BIO_should_retry(bio), 0);
ExpectIntEQ(BIO_should_read(bio), 0);
ExpectIntEQ(BIO_should_write(bio), 0);
/* now perform successful connection */
wolfSSL_SSLSetIORecv(ssl, EmbedReceive);
ExpectIntEQ(BIO_write(bio, msg, msgSz), msgSz);
ExpectIntNE(BIO_read(bio, reply, sizeof(reply)), 0);
ret = wolfSSL_get_error(ssl, -1);
if (ret == WOLFSSL_ERROR_WANT_READ || ret == WOLFSSL_ERROR_WANT_WRITE) {
ExpectIntNE(BIO_should_retry(bio), 0);
if (ret == WOLFSSL_ERROR_WANT_READ)
ExpectIntEQ(BIO_should_read(bio), 1);
else
ExpectIntEQ(BIO_should_read(bio), 0);
if (ret == WOLFSSL_ERROR_WANT_WRITE)
ExpectIntEQ(BIO_should_write(bio), 1);
else
ExpectIntEQ(BIO_should_write(bio), 0);
}
else {
ExpectIntEQ(BIO_should_retry(bio), 0);
ExpectIntEQ(BIO_should_read(bio), 0);
ExpectIntEQ(BIO_should_write(bio), 0);
}
ExpectIntEQ(XMEMCMP(reply, "I hear you fa shizzle!",
XSTRLEN("I hear you fa shizzle!")), 0);
BIO_free(bio);
wolfSSL_CTX_free(ctx);
CloseSocket(sockfd);
join_thread(serverThread);
FreeTcpReady(&ready);
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_connect(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
defined(HAVE_HTTP_CLIENT) && !defined(NO_WOLFSSL_CLIENT)
tcp_ready ready;
func_args server_args;
THREAD_TYPE serverThread;
BIO *tcpBio = NULL;
BIO *sslBio = NULL;
SSL_CTX* ctx = NULL;
SSL *ssl = NULL;
SSL *sslPtr;
char msg[] = "hello wolfssl!";
char reply[30];
char buff[10] = {0};
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM));
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM));
/* Setup server */
XMEMSET(&server_args, 0, sizeof(func_args));
StartTCP();
InitTcpReady(&ready);
#if defined(USE_WINDOWS_API)
/* use RNG to get random port if using windows */
ready.port = GetRandomPort();
#endif
server_args.signal = &ready;
start_thread(test_server_nofail, &server_args, &serverThread);
wait_tcp_ready(&server_args);
ExpectIntGT(XSNPRINTF(buff, sizeof(buff), "%d", ready.port), 0);
/* Start the test proper */
/* Setup the TCP BIO */
ExpectNotNull(tcpBio = BIO_new_connect(wolfSSLIP));
ExpectIntEQ(BIO_set_conn_port(tcpBio, buff), 1);
/* Setup the SSL object */
ExpectNotNull(ssl = SSL_new(ctx));
SSL_set_connect_state(ssl);
/* Setup the SSL BIO */
ExpectNotNull(sslBio = BIO_new(BIO_f_ssl()));
ExpectIntEQ(BIO_set_ssl(sslBio, ssl, BIO_CLOSE), 1);
if (EXPECT_FAIL()) {
wolfSSL_free(ssl);
}
/* Verify that BIO_get_ssl works. */
ExpectIntEQ(BIO_get_ssl(sslBio, &sslPtr), 1);
ExpectPtrEq(ssl, sslPtr);
/* Link BIO's so that sslBio uses tcpBio for IO */
ExpectPtrEq(BIO_push(sslBio, tcpBio), sslBio);
/* Do TCP connect */
ExpectIntEQ(BIO_do_connect(sslBio), 1);
/* Do TLS handshake */
ExpectIntEQ(BIO_do_handshake(sslBio), 1);
/* Test writing */
ExpectIntEQ(BIO_write(sslBio, msg, sizeof(msg)), sizeof(msg));
/* Expect length of default wolfSSL reply */
ExpectIntEQ(BIO_read(sslBio, reply, sizeof(reply)), 23);
/* Clean it all up */
BIO_free_all(sslBio);
/* Server clean up */
join_thread(serverThread);
FreeTcpReady(&ready);
/* Run the same test, but use BIO_new_ssl_connect and set the IP and port
* after. */
XMEMSET(&server_args, 0, sizeof(func_args));
StartTCP();
InitTcpReady(&ready);
#if defined(USE_WINDOWS_API)
/* use RNG to get random port if using windows */
ready.port = GetRandomPort();
#endif
server_args.signal = &ready;
start_thread(test_server_nofail, &server_args, &serverThread);
wait_tcp_ready(&server_args);
ExpectIntGT(XSNPRINTF(buff, sizeof(buff), "%d", ready.port), 0);
ExpectNotNull(sslBio = BIO_new_ssl_connect(ctx));
ExpectIntEQ(BIO_set_conn_hostname(sslBio, (char*)wolfSSLIP), 1);
ExpectIntEQ(BIO_set_conn_port(sslBio, buff), 1);
ExpectIntEQ(BIO_do_connect(sslBio), 1);
ExpectIntEQ(BIO_do_handshake(sslBio), 1);
ExpectIntEQ(BIO_write(sslBio, msg, sizeof(msg)), sizeof(msg));
ExpectIntEQ(BIO_read(sslBio, reply, sizeof(reply)), 23);
/* Attempt to close the TLS connection gracefully. */
BIO_ssl_shutdown(sslBio);
BIO_free_all(sslBio);
join_thread(serverThread);
FreeTcpReady(&ready);
SSL_CTX_free(ctx);
#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)
wc_ecc_fp_free(); /* free per thread cache */
#endif
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_tls(void)
{
EXPECT_DECLS;
#if !defined(NO_BIO) && defined(OPENSSL_EXTRA) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
SSL_CTX* ctx = NULL;
SSL *ssl = NULL;
BIO *readBio = NULL;
BIO *writeBio = NULL;
int ret;
int err = 0;
ExpectNotNull(ctx = SSL_CTX_new(SSLv23_method()));
ExpectNotNull(ssl = SSL_new(ctx));
ExpectNotNull(readBio = BIO_new(BIO_s_mem()));
ExpectNotNull(writeBio = BIO_new(BIO_s_mem()));
/* Qt reads data from write-bio,
* then writes the read data into plain packet.
* Qt reads data from plain packet,
* then writes the read data into read-bio.
*/
SSL_set_bio(ssl, readBio, writeBio);
do {
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) { break; } else if (ret == 0) { continue; }
}
#endif
ret = SSL_connect(ssl);
err = SSL_get_error(ssl, 0);
} while (err == WC_NO_ERR_TRACE(WC_PENDING_E));
ExpectIntEQ(ret, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
/* in this use case, should return WANT READ
* so that Qt will read the data from plain packet for next state.
*/
ExpectIntEQ(err, SSL_ERROR_WANT_READ);
SSL_free(ssl);
SSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_datagram(void)
{
EXPECT_DECLS;
#if !defined(NO_BIO) && defined(WOLFSSL_DTLS) && defined(WOLFSSL_HAVE_BIO_ADDR) && defined(OPENSSL_EXTRA)
int ret;
SOCKET_T fd1 = SOCKET_INVALID, fd2 = SOCKET_INVALID;
WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL;
WOLFSSL_BIO_ADDR *bio_addr1 = NULL, *bio_addr2 = NULL;
SOCKADDR_IN sin1, sin2;
socklen_t slen;
static const char test_msg[] = "I am a datagram, short and stout.";
char test_msg_recvd[sizeof(test_msg) + 10];
#ifdef USE_WINDOWS_API
static const DWORD timeout = 250; /* ms */
#else
static const struct timeval timeout = { 0, 250000 };
#endif
StartTCP();
if (EXPECT_SUCCESS()) {
fd1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ExpectIntNE(fd1, SOCKET_INVALID);
}
if (EXPECT_SUCCESS()) {
fd2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ExpectIntNE(fd2, SOCKET_INVALID);
}
if (EXPECT_SUCCESS()) {
bio1 = wolfSSL_BIO_new_dgram(fd1, 1 /* closeF */);
ExpectNotNull(bio1);
}
if (EXPECT_SUCCESS()) {
bio2 = wolfSSL_BIO_new_dgram(fd2, 1 /* closeF */);
ExpectNotNull(bio2);
}
if (EXPECT_SUCCESS()) {
sin1.sin_family = AF_INET;
sin1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sin1.sin_port = 0;
slen = (socklen_t)sizeof(sin1);
ExpectIntEQ(bind(fd1, (const struct sockaddr *)&sin1, slen), 0);
ExpectIntEQ(setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)), 0);
ExpectIntEQ(getsockname(fd1, (struct sockaddr *)&sin1, &slen), 0);
}
if (EXPECT_SUCCESS()) {
sin2.sin_family = AF_INET;
sin2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sin2.sin_port = 0;
slen = (socklen_t)sizeof(sin2);
ExpectIntEQ(bind(fd2, (const struct sockaddr *)&sin2, slen), 0);
ExpectIntEQ(setsockopt(fd2, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)), 0);
ExpectIntEQ(getsockname(fd2, (struct sockaddr *)&sin2, &slen), 0);
}
if (EXPECT_SUCCESS()) {
bio_addr1 = wolfSSL_BIO_ADDR_new();
ExpectNotNull(bio_addr1);
}
if (EXPECT_SUCCESS()) {
bio_addr2 = wolfSSL_BIO_ADDR_new();
ExpectNotNull(bio_addr2);
}
if (EXPECT_SUCCESS()) {
/* for OpenSSL compatibility, direct copying of sockaddrs into BIO_ADDRs must work right. */
XMEMCPY(&bio_addr2->sa_in, &sin2, sizeof(sin2));
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio1, BIO_CTRL_DGRAM_SET_PEER, 0, bio_addr2), WOLFSSL_SUCCESS);
wolfSSL_BIO_ADDR_clear(bio_addr2);
}
test_msg_recvd[0] = 0;
ExpectIntEQ(wolfSSL_BIO_write(bio1, test_msg, sizeof(test_msg)), (int)sizeof(test_msg));
ExpectIntEQ(wolfSSL_BIO_read(bio2, test_msg_recvd, sizeof(test_msg_recvd)), (int)sizeof(test_msg));
ExpectIntEQ(XMEMCMP(test_msg_recvd, test_msg, sizeof(test_msg)), 0);
#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
ExpectIntEQ(wolfSSL_BIO_number_written(bio1), sizeof(test_msg));
ExpectIntEQ(wolfSSL_BIO_number_read(bio2), sizeof(test_msg));
#endif
/* bio2 should now have bio1's addr stored as its peer_addr, because the
* BIOs aren't "connected" yet. use it to send a reply.
*/
test_msg_recvd[0] = 0;
ExpectIntEQ(wolfSSL_BIO_write(bio2, test_msg, sizeof(test_msg)), (int)sizeof(test_msg));
ExpectIntEQ(wolfSSL_BIO_read(bio1, test_msg_recvd, sizeof(test_msg_recvd)), (int)sizeof(test_msg));
ExpectIntEQ(XMEMCMP(test_msg_recvd, test_msg, sizeof(test_msg)), 0);
ExpectIntEQ(wolfSSL_BIO_read(bio1, test_msg_recvd, sizeof(test_msg_recvd)), WOLFSSL_BIO_ERROR);
ExpectIntNE(BIO_should_retry(bio1), 0);
ExpectIntEQ(wolfSSL_BIO_read(bio2, test_msg_recvd, sizeof(test_msg_recvd)), WOLFSSL_BIO_ERROR);
ExpectIntNE(BIO_should_retry(bio2), 0);
/* now "connect" the sockets. */
ExpectIntEQ(connect(fd1, (const struct sockaddr *)&sin2, (socklen_t)sizeof(sin2)), 0);
ExpectIntEQ(connect(fd2, (const struct sockaddr *)&sin1, (socklen_t)sizeof(sin1)), 0);
if (EXPECT_SUCCESS()) {
XMEMCPY(&bio_addr2->sa_in, &sin2, sizeof(sin2));
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio1, BIO_CTRL_DGRAM_SET_CONNECTED, 0, bio_addr2), WOLFSSL_SUCCESS);
wolfSSL_BIO_ADDR_clear(bio_addr2);
}
if (EXPECT_SUCCESS()) {
XMEMCPY(&bio_addr1->sa_in, &sin1, sizeof(sin1));
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio2, BIO_CTRL_DGRAM_SET_CONNECTED, 0, bio_addr1), WOLFSSL_SUCCESS);
wolfSSL_BIO_ADDR_clear(bio_addr1);
}
test_msg_recvd[0] = 0;
ExpectIntEQ(wolfSSL_BIO_write(bio2, test_msg, sizeof(test_msg)), (int)sizeof(test_msg));
ExpectIntEQ(wolfSSL_BIO_read(bio1, test_msg_recvd, sizeof(test_msg_recvd)), (int)sizeof(test_msg));
ExpectIntEQ(XMEMCMP(test_msg_recvd, test_msg, sizeof(test_msg)), 0);
test_msg_recvd[0] = 0;
ExpectIntEQ(wolfSSL_BIO_write(bio1, test_msg, sizeof(test_msg)), (int)sizeof(test_msg));
ExpectIntEQ(wolfSSL_BIO_read(bio2, test_msg_recvd, sizeof(test_msg_recvd)), (int)sizeof(test_msg));
ExpectIntEQ(XMEMCMP(test_msg_recvd, test_msg, sizeof(test_msg)), 0);
#ifdef __linux__
/* now "disconnect" the sockets and attempt transmits expected to fail. */
sin1.sin_family = AF_UNSPEC;
ExpectIntEQ(connect(fd1, (const struct sockaddr *)&sin1, (socklen_t)sizeof(sin1)), 0);
ExpectIntEQ(connect(fd2, (const struct sockaddr *)&sin1, (socklen_t)sizeof(sin1)), 0);
sin1.sin_family = AF_INET;
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio1, BIO_CTRL_DGRAM_SET_CONNECTED, 0, NULL), WOLFSSL_SUCCESS);
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio2, BIO_CTRL_DGRAM_SET_CONNECTED, 0, NULL), WOLFSSL_SUCCESS);
if (EXPECT_SUCCESS()) {
sin2.sin_addr.s_addr = htonl(0xc0a8c0a8); /* 192.168.192.168 -- invalid for loopback interface. */
XMEMCPY(&bio_addr2->sa_in, &sin2, sizeof(sin2));
ExpectIntEQ((int)wolfSSL_BIO_ctrl(bio1, BIO_CTRL_DGRAM_SET_PEER, 0, bio_addr2), WOLFSSL_SUCCESS);
wolfSSL_BIO_ADDR_clear(bio_addr2);
}
test_msg_recvd[0] = 0;
errno = 0;
ExpectIntEQ(wolfSSL_BIO_write(bio1, test_msg, sizeof(test_msg)), -1);
ExpectTrue((errno == EINVAL) || (errno == ENETUNREACH));
#endif /* __linux__ */
if (bio1) {
ret = wolfSSL_BIO_free(bio1);
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
} else if (fd1 != SOCKET_INVALID)
CloseSocket(fd1);
if (bio2) {
ret = wolfSSL_BIO_free(bio2);
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
} else if (fd2 != SOCKET_INVALID)
CloseSocket(fd2);
if (bio_addr1)
wolfSSL_BIO_ADDR_free(bio_addr1);
if (bio_addr2)
wolfSSL_BIO_ADDR_free(bio_addr2);
#endif /* !NO_BIO && WOLFSSL_DTLS && WOLFSSL_HAVE_BIO_ADDR && OPENSSL_EXTRA */
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_s_null(void)
{
EXPECT_DECLS;
#if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
BIO *b = NULL;
char testData[10] = {'t','e','s','t',0};
ExpectNotNull(b = BIO_new(BIO_s_null()));
ExpectIntEQ(BIO_write(b, testData, sizeof(testData)), sizeof(testData));
ExpectIntEQ(BIO_read(b, testData, sizeof(testData)), 0);
ExpectIntEQ(BIO_puts(b, testData), 4);
ExpectIntEQ(BIO_gets(b, testData, sizeof(testData)), 0);
ExpectIntEQ(BIO_pending(b), 0);
ExpectIntEQ(BIO_eof(b), 1);
BIO_free(b);
#endif
return EXPECT_RESULT();
}
#if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
defined(HAVE_HTTP_CLIENT)
static THREAD_RETURN WOLFSSL_THREAD test_wolfSSL_BIO_accept_client(void* args)
{
BIO* clientBio;
SSL* sslClient;
SSL_CTX* ctx;
char connectAddr[20]; /* IP + port */;
(void)args;
AssertIntGT(snprintf(connectAddr, sizeof(connectAddr), "%s:%d", wolfSSLIP, wolfSSLPort), 0);
clientBio = BIO_new_connect(connectAddr);
AssertNotNull(clientBio);
AssertIntEQ(BIO_do_connect(clientBio), 1);
ctx = SSL_CTX_new(SSLv23_method());
AssertNotNull(ctx);
sslClient = SSL_new(ctx);
AssertNotNull(sslClient);
AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), WOLFSSL_SUCCESS);
SSL_set_bio(sslClient, clientBio, clientBio);
AssertIntEQ(SSL_connect(sslClient), 1);
SSL_free(sslClient);
SSL_CTX_free(ctx);
#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)
wc_ecc_fp_free(); /* free per thread cache */
#endif
WOLFSSL_RETURN_FROM_THREAD(0);
}
#endif
int test_wolfSSL_BIO_accept(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
defined(HAVE_HTTP_CLIENT)
BIO* serverBindBio = NULL;
BIO* serverAcceptBio = NULL;
SSL* sslServer = NULL;
SSL_CTX* ctx = NULL;
func_args args;
THREAD_TYPE thread;
char port[10]; /* 10 bytes should be enough to store the string
* representation of the port */
ExpectIntGT(snprintf(port, sizeof(port), "%d", wolfSSLPort), 0);
ExpectNotNull(serverBindBio = BIO_new_accept(port));
/* First BIO_do_accept binds the port */
ExpectIntEQ(BIO_do_accept(serverBindBio), 1);
XMEMSET(&args, 0, sizeof(func_args));
start_thread(test_wolfSSL_BIO_accept_client, &args, &thread);
ExpectIntEQ(BIO_do_accept(serverBindBio), 1);
/* Let's plug it into SSL to test */
ExpectNotNull(ctx = SSL_CTX_new(SSLv23_method()));
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
SSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
SSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectNotNull(sslServer = SSL_new(ctx));
ExpectNotNull(serverAcceptBio = BIO_pop(serverBindBio));
SSL_set_bio(sslServer, serverAcceptBio, serverAcceptBio);
ExpectIntEQ(SSL_accept(sslServer), 1);
join_thread(thread);
BIO_free(serverBindBio);
SSL_free(sslServer);
SSL_CTX_free(ctx);
#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)
wc_ecc_fp_free(); /* free per thread cache */
#endif
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_write(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE)
BIO* bio = NULL;
BIO* bio64 = NULL;
BIO* bio_mem = NULL;
BIO* ptr = NULL;
int sz;
char msg[] = "conversion test";
char out[40];
char expected[] = "Y29udmVyc2lvbiB0ZXN0AA==\n";
void* bufPtr = NULL;
BUF_MEM* buf = NULL;
ExpectNotNull(bio64 = BIO_new(BIO_f_base64()));
ExpectNotNull(bio = BIO_push(bio64, BIO_new(BIO_s_mem())));
if (EXPECT_FAIL()) {
BIO_free(bio64);
}
/* now should convert to base64 then write to memory */
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg));
BIO_flush(bio);
/* test BIO chain */
ExpectIntEQ(SSL_SUCCESS, (int)BIO_get_mem_ptr(bio, &buf));
ExpectNotNull(buf);
ExpectIntEQ(buf->length, 25);
ExpectIntEQ(BIO_get_mem_data(bio, &bufPtr), 25);
ExpectPtrEq(buf->data, bufPtr);
ExpectNotNull(ptr = BIO_find_type(bio, BIO_TYPE_MEM));
sz = sizeof(out);
XMEMSET(out, 0, sz);
ExpectIntEQ((sz = BIO_read(ptr, out, sz)), 25);
ExpectIntEQ(XMEMCMP(out, expected, sz), 0);
/* write then read should return the same message */
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg));
sz = sizeof(out);
XMEMSET(out, 0, sz);
ExpectIntEQ(BIO_read(bio, out, sz), 16);
ExpectIntEQ(XMEMCMP(out, msg, sizeof(msg)), 0);
/* now try encoding with no line ending */
BIO_set_flags(bio64, BIO_FLAGS_BASE64_NO_NL);
#ifdef HAVE_EX_DATA
BIO_set_ex_data(bio64, 0, (void*) "data");
ExpectIntEQ(strcmp((const char*)BIO_get_ex_data(bio64, 0), "data"), 0);
#endif
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg));
BIO_flush(bio);
sz = sizeof(out);
XMEMSET(out, 0, sz);
ExpectIntEQ((sz = BIO_read(ptr, out, sz)), 24);
ExpectIntEQ(XMEMCMP(out, expected, sz), 0);
BIO_free_all(bio); /* frees bio64 also */
bio = NULL;
/* test with more than one bio64 in list */
ExpectNotNull(bio64 = BIO_new(BIO_f_base64()));
ExpectNotNull(bio = BIO_push(BIO_new(BIO_f_base64()), bio64));
if (EXPECT_FAIL()) {
BIO_free_all(bio);
bio = NULL;
bio64 = NULL;
}
ExpectNotNull(bio_mem = BIO_new(BIO_s_mem()));
ExpectNotNull(BIO_push(bio64, bio_mem));
if (EXPECT_FAIL()) {
BIO_free(bio_mem);
}
/* now should convert to base64 when stored and then decode with read */
if (bio == NULL) {
ExpectNotNull(bio = BIO_new(BIO_f_base64()));
}
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), 25);
BIO_flush(bio);
sz = sizeof(out);
XMEMSET(out, 0, sz);
ExpectIntEQ((sz = BIO_read(bio, out, sz)), 16);
ExpectIntEQ(XMEMCMP(out, msg, sz), 0);
BIO_clear_flags(bio64, ~0);
BIO_set_retry_read(bio);
BIO_free_all(bio); /* frees bio64s also */
bio = NULL;
ExpectNotNull(bio = BIO_new_mem_buf(out, 0));
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg));
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_printf(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL)
BIO* bio = NULL;
int sz = 7;
char msg[] = "TLS 1.3 for the world";
char out[60];
char expected[] = "TLS 1.3 for the world : sz = 7";
XMEMSET(out, 0, sizeof(out));
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(BIO_printf(bio, "%s : sz = %d", msg, sz), 30);
ExpectIntEQ(BIO_printf(NULL, ""), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
ExpectIntEQ(BIO_read(bio, out, sizeof(out)), 30);
ExpectIntEQ(XSTRNCMP(out, expected, sizeof(expected)), 0);
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_f_md(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) && !defined(NO_SHA256)
BIO* bio = NULL;
BIO* mem = NULL;
char msg[] = "message to hash";
char out[60];
EVP_MD_CTX* ctx = NULL;
const unsigned char testKey[] =
{
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b
};
const char testData[] = "Hi There";
const unsigned char testResult[] =
{
0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
};
const unsigned char expectedHash[] =
{
0x66, 0x49, 0x3C, 0xE8, 0x8A, 0x57, 0xB0, 0x60,
0xDC, 0x55, 0x7D, 0xFC, 0x1F, 0xA5, 0xE5, 0x07,
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 = sizeof(check);
EVP_PKEY* key = NULL;
XMEMSET(out, 0, sizeof(out));
ExpectNotNull(bio = BIO_new(BIO_f_md()));
ExpectNotNull(mem = BIO_new(BIO_s_mem()));
ExpectIntEQ(BIO_get_md_ctx(bio, &ctx), 1);
ExpectIntEQ(EVP_DigestInit(ctx, EVP_sha256()), 1);
/* should not be able to write/read yet since just digest wrapper and no
* data is passing through the bio */
ExpectIntEQ(BIO_write(bio, msg, 0), 0);
ExpectIntEQ(BIO_pending(bio), 0);
ExpectIntEQ(BIO_read(bio, out, sizeof(out)), 0);
ExpectIntEQ(BIO_gets(bio, out, 3), 0);
ExpectIntEQ(BIO_gets(bio, out, sizeof(out)), 32);
ExpectIntEQ(XMEMCMP(emptyHash, out, 32), 0);
BIO_reset(bio);
/* append BIO mem to bio in order to read/write */
ExpectNotNull(bio = BIO_push(bio, mem));
XMEMSET(out, 0, sizeof(out));
ExpectIntEQ(BIO_write(mem, msg, sizeof(msg)), 16);
ExpectIntEQ(BIO_pending(bio), 16);
/* this just reads the message and does not hash it (gets calls final) */
ExpectIntEQ(BIO_read(bio, out, sizeof(out)), 16);
ExpectIntEQ(XMEMCMP(out, msg, sizeof(msg)), 0);
/* create a message digest using BIO */
XMEMSET(out, 0, sizeof(out));
ExpectIntEQ(BIO_write(bio, msg, sizeof(msg)), 16);
ExpectIntEQ(BIO_pending(mem), 16);
ExpectIntEQ(BIO_pending(bio), 16);
ExpectIntEQ(BIO_gets(bio, out, sizeof(out)), 32);
ExpectIntEQ(XMEMCMP(expectedHash, out, 32), 0);
BIO_free(bio);
bio = NULL;
BIO_free(mem);
mem = NULL;
/* test with HMAC */
XMEMSET(out, 0, sizeof(out));
ExpectNotNull(bio = BIO_new(BIO_f_md()));
ExpectNotNull(mem = BIO_new(BIO_s_mem()));
BIO_get_md_ctx(bio, &ctx);
ExpectNotNull(key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, testKey,
(int)sizeof(testKey)));
EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, key);
ExpectNotNull(bio = BIO_push(bio, mem));
BIO_write(bio, testData, (int)strlen(testData));
checkSz = sizeof(check);
ExpectIntEQ(EVP_DigestSignFinal(ctx, NULL, &checkSz), 1);
checkSz = sizeof(check);
ExpectIntEQ(EVP_DigestSignFinal(ctx, check, &checkSz), 1);
ExpectIntEQ(XMEMCMP(check, testResult, sizeof(testResult)), 0);
EVP_PKEY_free(key);
BIO_free(bio);
BIO_free(mem);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_up_ref(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
BIO* bio = NULL;
ExpectNotNull(bio = BIO_new(BIO_f_md()));
ExpectIntEQ(BIO_up_ref(NULL), 0);
ExpectIntEQ(BIO_up_ref(bio), 1);
BIO_free(bio);
ExpectIntEQ(BIO_up_ref(bio), 1);
BIO_free(bio);
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_reset(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
BIO* bio = NULL;
byte buf[16];
ExpectNotNull(bio = BIO_new_mem_buf("secure your data",
(word32)XSTRLEN("secure your data")));
ExpectIntEQ(BIO_read(bio, buf, 6), 6);
ExpectIntEQ(XMEMCMP(buf, "secure", 6), 0);
XMEMSET(buf, 0, 16);
ExpectIntEQ(BIO_read(bio, buf, 16), 10);
ExpectIntEQ(XMEMCMP(buf, " your data", 10), 0);
/* You cannot write to MEM BIO with read-only mode. */
ExpectIntEQ(BIO_write(bio, "WriteToReadonly", 15), 0);
ExpectIntEQ(BIO_read(bio, buf, 16), -1);
XMEMSET(buf, 0, 16);
ExpectIntEQ(BIO_reset(bio), 1);
ExpectIntEQ(BIO_read(bio, buf, 16), 16);
ExpectIntEQ(XMEMCMP(buf, "secure your data", 16), 0);
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_BIO_get_len(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && !defined(NO_BIO)
BIO *bio = NULL;
const char txt[] = "Some example text to push to the BIO.";
ExpectIntEQ(wolfSSL_BIO_get_len(bio), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()));
ExpectIntEQ(wolfSSL_BIO_write(bio, txt, sizeof(txt)), sizeof(txt));
ExpectIntEQ(wolfSSL_BIO_get_len(bio), sizeof(txt));
BIO_free(bio);
bio = NULL;
ExpectNotNull(bio = BIO_new_fd(STDERR_FILENO, BIO_NOCLOSE));
ExpectIntEQ(wolfSSL_BIO_get_len(bio), WC_NO_ERR_TRACE(WOLFSSL_BAD_FILE));
BIO_free(bio);
#endif
return EXPECT_RESULT();
}
#endif /* !NO_BIO */