mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 16:10:48 +02:00
845a3a93b5
wolfSSL_BIO_write rejected negative lengths but allowed a large positive length through to wolfSSL_BIO_MEMORY_write. On a fresh buffer an INT_MAX length overflowed the 4/3 buffer growth calculation, so the grow reported success with a short allocation and the following copy read far past the small source buffer. Add an upper bound check that rejects lengths large enough to overflow the growth math before any allocation or copy, and add a regression test that drives a huge length through the public BIO_write entry point.
1904 lines
62 KiB
C
1904 lines
62 KiB
C
/* test_ossl_bio.c
|
|
*
|
|
* Copyright (C) 2006-2026 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) && !defined(NO_FILESYSTEM)
|
|
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);
|
|
|
|
|
|
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);
|
|
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);
|
|
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()) {
|
|
/* 192.168.192.168 -- invalid for loopback interface. */
|
|
sin2.sin_addr.s_addr = htonl(0xc0a8c0a8);
|
|
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();
|
|
}
|
|
|
|
/* A negative length must never defeat the memory-BIO read bounds check and
|
|
* reach XMEMCPY with (size_t)-1. This exercises the public BIO_read() boundary
|
|
* (which rejects a negative length before dispatch); the matching guard in the
|
|
* static wolfSSL_BIO_MEMORY_read() sink is defense-in-depth and not separately
|
|
* reachable through the public API. Verify a negative length is rejected with
|
|
* an error without copying, a zero length reads nothing, and the pending data
|
|
* is left intact and still readable. */
|
|
int test_wolfSSL_BIO_read_negative_len(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO* bio = NULL;
|
|
char msg[] = "negative length test";
|
|
int msgLen = (int)XSTRLEN(msg);
|
|
char out[64];
|
|
|
|
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
|
|
ExpectIntEQ(BIO_write(bio, msg, msgLen), msgLen);
|
|
|
|
/* Negative length: must be rejected with an error, not a wild copy and not
|
|
* a silent 0-byte read. */
|
|
XMEMSET(out, 0, sizeof(out));
|
|
ExpectIntLT(BIO_read(bio, out, -1), 0);
|
|
/* Data must be untouched - still all pending. */
|
|
ExpectIntEQ(BIO_pending(bio), msgLen);
|
|
|
|
/* Zero length: nothing read, data still pending. */
|
|
ExpectIntEQ(BIO_read(bio, out, 0), 0);
|
|
ExpectIntEQ(BIO_pending(bio), msgLen);
|
|
|
|
/* A normal read still returns the intact message. */
|
|
ExpectIntEQ(BIO_read(bio, out, (int)sizeof(out)), msgLen);
|
|
ExpectIntEQ(XMEMCMP(out, msg, msgLen), 0);
|
|
|
|
BIO_free(bio);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* A length larger than the source buffer must never reach XMEMCPY in the
|
|
* memory-BIO write path. A huge positive length on a fresh buffer would
|
|
* otherwise overflow the buffer growth calculation, allocate a short
|
|
* destination, and copy far past the small source. Verify such a length is
|
|
* rejected with an error, nothing is buffered, and normal writes still work. */
|
|
int test_wolfSSL_BIO_write_large_len(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO* bio = NULL;
|
|
char msg[] = "large length test";
|
|
int msgLen = (int)XSTRLEN(msg);
|
|
char out[64];
|
|
|
|
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
|
|
|
|
/* Oversized length on a fresh buffer: must be rejected with an error, not
|
|
* a wild copy from the small source buffer. */
|
|
ExpectIntLT(BIO_write(bio, msg, (int)0x7FFFFFFF), 0);
|
|
/* Nothing should have been buffered. */
|
|
ExpectIntEQ(BIO_pending(bio), 0);
|
|
|
|
/* A normal write then read still returns the intact message. */
|
|
ExpectIntEQ(BIO_write(bio, msg, msgLen), msgLen);
|
|
XMEMSET(out, 0, sizeof(out));
|
|
ExpectIntEQ(BIO_read(bio, out, (int)sizeof(out)), msgLen);
|
|
ExpectIntEQ(XMEMCMP(out, msg, msgLen), 0);
|
|
|
|
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), WOLFSSL_BIO_ERROR);
|
|
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) && !defined(NO_FILESYSTEM)
|
|
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();
|
|
}
|
|
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_BIO)
|
|
static long bioCallback(BIO *bio, int cmd, const char* argp, int argi,
|
|
long argl, long ret)
|
|
{
|
|
(void)bio;
|
|
(void)cmd;
|
|
(void)argp;
|
|
(void)argi;
|
|
(void)argl;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_BIO(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_BIO)
|
|
const unsigned char* p = NULL;
|
|
byte buff[20];
|
|
BIO* bio1 = NULL;
|
|
BIO* bio2 = NULL;
|
|
BIO* bio3 = NULL;
|
|
char* bufPt = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < 20; i++) {
|
|
buff[i] = i;
|
|
}
|
|
/* test BIO_free with NULL */
|
|
ExpectIntEQ(BIO_free(NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
|
|
/* Creating and testing type BIO_s_bio */
|
|
ExpectNotNull(bio1 = BIO_new(BIO_s_bio()));
|
|
ExpectNotNull(bio2 = BIO_new(BIO_s_bio()));
|
|
ExpectNotNull(bio3 = BIO_new(BIO_s_bio()));
|
|
|
|
/* read/write before set up */
|
|
ExpectIntEQ(BIO_read(bio1, buff, 2), WOLFSSL_BIO_UNSET);
|
|
ExpectIntEQ(BIO_write(bio1, buff, 2), WOLFSSL_BIO_UNSET);
|
|
|
|
ExpectIntEQ(BIO_set_nbio(bio1, 1), 1);
|
|
ExpectIntEQ(BIO_set_write_buf_size(bio1, 20), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_set_write_buf_size(bio2, 8), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_make_bio_pair(bio1, bio2), WOLFSSL_SUCCESS);
|
|
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 10), 10);
|
|
ExpectNotNull(XMEMCPY(bufPt, buff, 10));
|
|
ExpectIntEQ(BIO_write(bio1, buff + 10, 10), 10);
|
|
/* write buffer full */
|
|
ExpectIntEQ(BIO_write(bio1, buff, 10), WOLFSSL_BIO_ERROR);
|
|
ExpectIntEQ(BIO_flush(bio1), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio1), 0);
|
|
|
|
/* write the other direction with pair */
|
|
ExpectIntEQ((int)BIO_nwrite(bio2, &bufPt, 10), 8);
|
|
ExpectNotNull(XMEMCPY(bufPt, buff, 8));
|
|
ExpectIntEQ(BIO_write(bio2, buff, 10), WOLFSSL_BIO_ERROR);
|
|
|
|
/* try read */
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio1), 8);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio2), 20);
|
|
|
|
/* try read using ctrl function */
|
|
ExpectIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_WPENDING, 0, NULL), 8);
|
|
ExpectIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_PENDING, 0, NULL), 8);
|
|
ExpectIntEQ((int)BIO_ctrl(bio2, BIO_CTRL_WPENDING, 0, NULL), 20);
|
|
ExpectIntEQ((int)BIO_ctrl(bio2, BIO_CTRL_PENDING, 0, NULL), 20);
|
|
|
|
ExpectIntEQ(BIO_nread(bio2, &bufPt, (int)BIO_ctrl_pending(bio2)), 20);
|
|
for (i = 0; i < 20; i++) {
|
|
ExpectIntEQ((int)bufPt[i], i);
|
|
}
|
|
ExpectIntEQ(BIO_nread(bio2, &bufPt, 1), 0);
|
|
ExpectIntEQ(BIO_nread(bio1, &bufPt, (int)BIO_ctrl_pending(bio1)), 8);
|
|
for (i = 0; i < 8; i++) {
|
|
ExpectIntEQ((int)bufPt[i], i);
|
|
}
|
|
ExpectIntEQ(BIO_nread(bio1, &bufPt, 1), 0);
|
|
ExpectIntEQ(BIO_ctrl_reset_read_request(bio1), 1);
|
|
|
|
/* new pair */
|
|
ExpectIntEQ(BIO_make_bio_pair(bio1, bio3),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
BIO_free(bio2); /* free bio2 and automatically remove from pair */
|
|
bio2 = NULL;
|
|
ExpectIntEQ(BIO_make_bio_pair(bio1, bio3), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio3), 0);
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 10), 0);
|
|
|
|
/* test wrap around... */
|
|
ExpectIntEQ(BIO_reset(bio1), 1);
|
|
ExpectIntEQ(BIO_reset(bio3), 1);
|
|
|
|
/* fill write buffer, read only small amount then write again */
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20);
|
|
ExpectNotNull(XMEMCPY(bufPt, buff, 20));
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 4), 4);
|
|
for (i = 0; i < 4; i++) {
|
|
ExpectIntEQ(bufPt[i], i);
|
|
}
|
|
|
|
/* try writing over read index */
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 5), 4);
|
|
ExpectNotNull(XMEMSET(bufPt, 0, 4));
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio3), 20);
|
|
|
|
/* read and write 0 bytes */
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 0), 0);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 0), 0);
|
|
|
|
/* should read only to end of write buffer then need to read again */
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 20), 16);
|
|
for (i = 0; i < 16; i++) {
|
|
ExpectIntEQ(bufPt[i], buff[4 + i]);
|
|
}
|
|
|
|
ExpectIntEQ(BIO_nread(bio3, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(BIO_nread0(bio3, &bufPt), 4);
|
|
for (i = 0; i < 4; i++) {
|
|
ExpectIntEQ(bufPt[i], 0);
|
|
}
|
|
|
|
/* read index should not have advanced with nread0 */
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 5), 4);
|
|
for (i = 0; i < 4; i++) {
|
|
ExpectIntEQ(bufPt[i], 0);
|
|
}
|
|
|
|
/* write and fill up buffer checking reset of index state */
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20);
|
|
ExpectNotNull(XMEMCPY(bufPt, buff, 20));
|
|
|
|
/* test reset on data in bio1 write buffer */
|
|
ExpectIntEQ(BIO_reset(bio1), 1);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio3), 0);
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 3), 0);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20);
|
|
ExpectIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_INFO, 0, &p), 20);
|
|
ExpectNotNull(p);
|
|
ExpectNotNull(XMEMCPY(bufPt, buff, 20));
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 6), 6);
|
|
for (i = 0; i < 6; i++) {
|
|
ExpectIntEQ(bufPt[i], i);
|
|
}
|
|
|
|
/* test case of writing twice with offset read index */
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 3), 3);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 4), 3); /* try overwriting */
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR);
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 0), 0);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR);
|
|
ExpectIntEQ(BIO_nread(bio3, &bufPt, 1), 1);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 4), 1);
|
|
ExpectIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR);
|
|
|
|
BIO_free(bio1);
|
|
bio1 = NULL;
|
|
BIO_free(bio3);
|
|
bio3 = NULL;
|
|
|
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)
|
|
{
|
|
BIO* bioA = NULL;
|
|
BIO* bioB = NULL;
|
|
ExpectIntEQ(BIO_new_bio_pair(NULL, 256, NULL, 256),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(BIO_new_bio_pair(&bioA, 256, &bioB, 256), WOLFSSL_SUCCESS);
|
|
BIO_free(bioA);
|
|
bioA = NULL;
|
|
BIO_free(bioB);
|
|
bioB = NULL;
|
|
}
|
|
#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
|
|
|
|
/* BIOs with file pointers */
|
|
#if !defined(NO_FILESYSTEM)
|
|
{
|
|
XFILE f1 = XBADFILE;
|
|
XFILE f2 = XBADFILE;
|
|
BIO* f_bio1 = NULL;
|
|
BIO* f_bio2 = NULL;
|
|
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\n"
|
|
"created by tests/unit.test\n\n";
|
|
|
|
ExpectNotNull(f_bio1 = BIO_new(BIO_s_file()));
|
|
ExpectNotNull(f_bio2 = BIO_new(BIO_s_file()));
|
|
|
|
/* Failure due to wrong BIO type */
|
|
ExpectIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0);
|
|
ExpectIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0);
|
|
|
|
ExpectTrue((f1 = XFOPEN(svrCertFile, "rb+")) != XBADFILE);
|
|
ExpectIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_write_filename(f_bio2, testFile),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
ExpectIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert));
|
|
ExpectIntEQ(BIO_tell(f_bio1),sizeof(cert));
|
|
ExpectIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg));
|
|
ExpectIntEQ(BIO_tell(f_bio2),sizeof(msg));
|
|
ExpectIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert));
|
|
ExpectIntEQ(BIO_tell(f_bio2),sizeof(cert) + sizeof(msg));
|
|
|
|
ExpectIntEQ((int)BIO_get_fp(f_bio2, &f2), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_reset(f_bio2), 1);
|
|
ExpectIntEQ(BIO_tell(NULL),-1);
|
|
ExpectIntEQ(BIO_tell(f_bio2),0);
|
|
ExpectIntEQ(BIO_seek(f_bio2, 4), 0);
|
|
ExpectIntEQ(BIO_tell(f_bio2),4);
|
|
|
|
BIO_free(f_bio1);
|
|
f_bio1 = NULL;
|
|
BIO_free(f_bio2);
|
|
f_bio2 = NULL;
|
|
|
|
ExpectNotNull(f_bio1 = BIO_new_file(svrCertFile, "rb+"));
|
|
ExpectIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0);
|
|
ExpectIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert));
|
|
BIO_free(f_bio1);
|
|
f_bio1 = NULL;
|
|
}
|
|
#endif /* !defined(NO_FILESYSTEM) */
|
|
|
|
/* BIO info callback */
|
|
{
|
|
const char* testArg = "test";
|
|
BIO* cb_bio = NULL;
|
|
ExpectNotNull(cb_bio = BIO_new(BIO_s_mem()));
|
|
|
|
BIO_set_callback(cb_bio, bioCallback);
|
|
ExpectNotNull(BIO_get_callback(cb_bio));
|
|
BIO_set_callback(cb_bio, NULL);
|
|
ExpectNull(BIO_get_callback(cb_bio));
|
|
|
|
BIO_set_callback_arg(cb_bio, (char*)testArg);
|
|
ExpectStrEQ(BIO_get_callback_arg(cb_bio), testArg);
|
|
ExpectNull(BIO_get_callback_arg(NULL));
|
|
|
|
BIO_free(cb_bio);
|
|
cb_bio = NULL;
|
|
}
|
|
|
|
/* BIO_vfree */
|
|
ExpectNotNull(bio1 = BIO_new(BIO_s_bio()));
|
|
BIO_vfree(NULL);
|
|
BIO_vfree(bio1);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_BIO_BIO_ring_read(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_ALL) && !defined(NO_BIO)
|
|
BIO* bio1 = NULL;
|
|
BIO* bio2 = NULL;
|
|
byte data[50];
|
|
byte tmp[50];
|
|
|
|
XMEMSET(data, 42, sizeof(data));
|
|
|
|
|
|
ExpectIntEQ(BIO_new_bio_pair(&bio1, sizeof(data), &bio2, sizeof(data)),
|
|
SSL_SUCCESS);
|
|
|
|
ExpectIntEQ(BIO_write(bio1, data, 40), 40);
|
|
ExpectIntEQ(BIO_read(bio1, tmp, 20), -1);
|
|
ExpectIntEQ(BIO_read(bio2, tmp, 20), 20);
|
|
ExpectBufEQ(tmp, data, 20);
|
|
ExpectIntEQ(BIO_write(bio1, data, 20), 20);
|
|
ExpectIntEQ(BIO_read(bio2, tmp, 40), 40);
|
|
ExpectBufEQ(tmp, data, 40);
|
|
|
|
BIO_free(bio1);
|
|
BIO_free(bio2);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Custom BIO backing store for test_wolfSSL_BIO_custom_method */
|
|
#if defined(OPENSSL_EXTRA)
|
|
|
|
static int custom_bio_destroyCalled = 0;
|
|
|
|
struct custom_bio_data {
|
|
char buf[256];
|
|
int len;
|
|
byte createCalled:1;
|
|
byte writeCalled:1;
|
|
byte readCalled:1;
|
|
byte putsCalled:1;
|
|
byte getsCalled:1;
|
|
byte ctrlCalled:1;
|
|
};
|
|
|
|
static int custom_bio_createCb(WOLFSSL_BIO* bio)
|
|
{
|
|
struct custom_bio_data* data;
|
|
data = (struct custom_bio_data*)XMALLOC(sizeof(*data), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (data == NULL)
|
|
return 0;
|
|
XMEMSET(data, 0, sizeof(*data));
|
|
data->createCalled = 1;
|
|
BIO_set_data(bio, data);
|
|
BIO_set_init(bio, 1);
|
|
return 1;
|
|
}
|
|
|
|
static int custom_bio_destroyCb(WOLFSSL_BIO* bio)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
if (data != NULL) {
|
|
custom_bio_destroyCalled = 1;
|
|
XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
BIO_set_data(bio, NULL);
|
|
return 1;
|
|
}
|
|
|
|
static int custom_bio_writeCb(WOLFSSL_BIO* bio, const char* in, int len)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
int avail;
|
|
if (data == NULL || in == NULL || len <= 0)
|
|
return -1;
|
|
data->writeCalled = 1;
|
|
avail = (int)sizeof(data->buf) - data->len;
|
|
if (len > avail)
|
|
len = avail;
|
|
XMEMCPY(data->buf + data->len, in, (size_t)len);
|
|
data->len += len;
|
|
return len;
|
|
}
|
|
|
|
static int custom_bio_readCb(WOLFSSL_BIO* bio, char* out, int len)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
if (data == NULL || out == NULL || len <= 0)
|
|
return -1;
|
|
data->readCalled = 1;
|
|
if (data->len == 0)
|
|
return 0;
|
|
if (len > data->len)
|
|
len = data->len;
|
|
XMEMCPY(out, data->buf, (size_t)len);
|
|
/* shift remaining data */
|
|
data->len -= len;
|
|
if (data->len > 0)
|
|
XMEMMOVE(data->buf, data->buf + len, (size_t)data->len);
|
|
return len;
|
|
}
|
|
|
|
static int custom_bio_putsCb(WOLFSSL_BIO* bio, const char* str)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
if (str == NULL || data == NULL)
|
|
return -1;
|
|
data->putsCalled = 1;
|
|
return custom_bio_writeCb(bio, str, (int)XSTRLEN(str));
|
|
}
|
|
|
|
static int custom_bio_getsCb(WOLFSSL_BIO* bio, char* buf, int sz)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
int i;
|
|
int readLen;
|
|
if (data == NULL || buf == NULL || sz <= 1)
|
|
return -1;
|
|
data->getsCalled = 1;
|
|
if (data->len == 0)
|
|
return 0;
|
|
/* read up to newline or sz-1 bytes */
|
|
readLen = (sz - 1 < data->len) ? sz - 1 : data->len;
|
|
for (i = 0; i < readLen; i++) {
|
|
buf[i] = data->buf[i];
|
|
if (data->buf[i] == '\n') {
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
buf[i] = '\0';
|
|
/* shift remaining data */
|
|
data->len -= i;
|
|
if (data->len > 0)
|
|
XMEMMOVE(data->buf, data->buf + i, (size_t)data->len);
|
|
return i;
|
|
}
|
|
|
|
static long custom_bio_ctrlCb(WOLFSSL_BIO* bio, int cmd, long larg, void* parg)
|
|
{
|
|
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
|
|
(void)larg;
|
|
if (data == NULL)
|
|
return -1;
|
|
data->ctrlCalled = 1;
|
|
switch (cmd) {
|
|
case BIO_CTRL_PENDING:
|
|
return (long)data->len;
|
|
case BIO_CTRL_RESET:
|
|
data->len = 0;
|
|
return WOLFSSL_SUCCESS;
|
|
case BIO_CTRL_FLUSH:
|
|
return 1;
|
|
case BIO_CTRL_INFO:
|
|
if (parg != NULL)
|
|
*(char**)parg = data->buf;
|
|
return (long)data->len;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#endif /* OPENSSL_EXTRA */
|
|
|
|
int test_wolfSSL_BIO_custom_method(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO_METHOD* method = NULL;
|
|
BIO* bio = NULL;
|
|
struct custom_bio_data* data = NULL;
|
|
char buf[256];
|
|
char* memPtr = NULL;
|
|
|
|
/* Create custom method and set all callbacks */
|
|
ExpectNotNull(method = BIO_meth_new(WOLFSSL_BIO_UNDEF, "custom_test"));
|
|
ExpectIntEQ(BIO_meth_set_create(method, custom_bio_createCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_destroy(method, custom_bio_destroyCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_write(method, custom_bio_writeCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_read(method, custom_bio_readCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_puts(method, custom_bio_putsCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_gets(method, custom_bio_getsCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_ctrl(method, custom_bio_ctrlCb),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* Create BIO - should invoke createCb */
|
|
ExpectNotNull(bio = BIO_new(method));
|
|
ExpectNotNull(data = (struct custom_bio_data*)BIO_get_data(bio));
|
|
ExpectTrue(data->createCalled);
|
|
|
|
/* write */
|
|
ExpectIntEQ(BIO_write(bio, "hello", 5), 5);
|
|
ExpectTrue(data->writeCalled);
|
|
|
|
/* ctrl_pending via ctrlCb */
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio), 5);
|
|
ExpectTrue(data->ctrlCalled);
|
|
|
|
/* read */
|
|
XMEMSET(buf, 0, sizeof(buf));
|
|
ExpectIntEQ(BIO_read(bio, buf, 5), 5);
|
|
ExpectBufEQ(buf, "hello", 5);
|
|
ExpectTrue(data->readCalled);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio), 0);
|
|
|
|
/* puts */
|
|
ExpectIntEQ(BIO_puts(bio, "world\nfoo"), 9);
|
|
ExpectTrue(data->putsCalled);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio), 9);
|
|
|
|
/* gets - should read up to and including first newline */
|
|
XMEMSET(buf, 0, sizeof(buf));
|
|
ExpectIntEQ(BIO_gets(bio, buf, (int)sizeof(buf)), 6);
|
|
ExpectStrEQ(buf, "world\n");
|
|
ExpectTrue(data->getsCalled);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio), 3);
|
|
|
|
/* get_mem_data via BIO_CTRL_INFO */
|
|
ExpectIntEQ(BIO_get_mem_data(bio, &memPtr), 3);
|
|
ExpectNotNull(memPtr);
|
|
|
|
/* reset via ctrlCb */
|
|
ExpectIntEQ(BIO_reset(bio), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ((int)BIO_ctrl_pending(bio), 0);
|
|
|
|
/* free - should invoke destroyCb */
|
|
custom_bio_destroyCalled = 0;
|
|
BIO_free(bio);
|
|
ExpectTrue(custom_bio_destroyCalled);
|
|
BIO_meth_free(method);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_BIO_set_conn_hostname(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO* bio = NULL;
|
|
|
|
/* NULL bio should fail */
|
|
ExpectIntEQ(BIO_set_conn_hostname(NULL, (char*)"localhost"),
|
|
WOLFSSL_FAILURE);
|
|
|
|
/* Create a bare socket BIO (ip starts as NULL) */
|
|
ExpectNotNull(bio = BIO_new(BIO_s_socket()));
|
|
|
|
/* NULL hostname should fail */
|
|
ExpectIntEQ(BIO_set_conn_hostname(bio, NULL), WOLFSSL_FAILURE);
|
|
|
|
/* Set initial hostname (ip == NULL, triggers malloc) */
|
|
ExpectIntEQ(BIO_set_conn_hostname(bio, (char*)"127.0.0.1"),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* Set same-length hostname (reuses existing buffer) */
|
|
ExpectIntEQ(BIO_set_conn_hostname(bio, (char*)"192.168.0"),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* Set shorter hostname (triggers free + malloc) */
|
|
ExpectIntEQ(BIO_set_conn_hostname(bio, (char*)"short"), WOLFSSL_SUCCESS);
|
|
|
|
/* Set longer hostname (triggers free + malloc) */
|
|
ExpectIntEQ(BIO_set_conn_hostname(bio, (char*)"a]longer.hostname.example"),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
BIO_free(bio);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(OPENSSL_EXTRA)
|
|
static long pending_ctrlCb(WOLFSSL_BIO* bio, int cmd, long larg, void* parg)
|
|
{
|
|
(void)bio;
|
|
(void)larg;
|
|
(void)parg;
|
|
if (cmd == BIO_CTRL_PENDING)
|
|
return 42;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int test_wolfSSL_BIO_ctrl_pending_chain(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO* md = NULL;
|
|
BIO* b64 = NULL;
|
|
BIO* mem = NULL;
|
|
char msg[] = "hello";
|
|
|
|
/* Build chain: md -> b64 -> mem */
|
|
ExpectNotNull(md = BIO_new(BIO_f_md()));
|
|
ExpectNotNull(b64 = BIO_new(BIO_f_base64()));
|
|
ExpectNotNull(mem = BIO_new(BIO_s_mem()));
|
|
ExpectNotNull(BIO_push(md, b64));
|
|
ExpectNotNull(BIO_push(b64, mem));
|
|
|
|
/* Write directly to mem so wrSz is set */
|
|
ExpectIntEQ(BIO_write(mem, msg, sizeof(msg)), (int)sizeof(msg));
|
|
|
|
/* ctrl_pending on mem should work */
|
|
ExpectIntEQ((int)BIO_ctrl_pending(mem), (int)sizeof(msg));
|
|
|
|
/* ctrl_pending on the head of the chain (md) should skip both wrappers
|
|
* and return mem's pending count */
|
|
ExpectIntEQ((int)BIO_ctrl_pending(md), (int)sizeof(msg));
|
|
|
|
BIO_free(md);
|
|
BIO_free(b64);
|
|
BIO_free(mem);
|
|
|
|
/* Test that ctrl_pending reaches a custom ctrlCb through a wrapper.
|
|
* Chain: md -> custom(with ctrlCb) -> mem. The custom BIO's ctrlCb
|
|
* returns 42 for BIO_CTRL_PENDING, so ctrl_pending on md should
|
|
* return 42 (stopping at custom), not fall through to mem. */
|
|
{
|
|
BIO* md2 = NULL;
|
|
BIO* custom = NULL;
|
|
BIO* mem2 = NULL;
|
|
BIO_METHOD* meth = NULL;
|
|
|
|
ExpectNotNull(meth = BIO_meth_new(0, "pending_test"));
|
|
ExpectIntEQ(BIO_meth_set_ctrl(meth, pending_ctrlCb), WOLFSSL_SUCCESS);
|
|
ExpectNotNull(md2 = BIO_new(BIO_f_md()));
|
|
ExpectNotNull(custom = BIO_new(meth));
|
|
ExpectNotNull(mem2 = BIO_new(BIO_s_mem()));
|
|
ExpectNotNull(BIO_push(md2, custom));
|
|
ExpectNotNull(BIO_push(custom, mem2));
|
|
|
|
ExpectIntEQ((int)BIO_ctrl_pending(md2), 42);
|
|
|
|
BIO_free(md2);
|
|
BIO_free(custom);
|
|
BIO_free(mem2);
|
|
BIO_meth_free(meth);
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_BIO_meth_type_large(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO_METHOD* method = NULL;
|
|
BIO* bio = NULL;
|
|
|
|
/* Type value exceeding 255, as used by applications like HAProxy (0x666) */
|
|
ExpectNotNull(method = BIO_meth_new(0x666, "large_type_test"));
|
|
ExpectNotNull(bio = BIO_new(method));
|
|
ExpectIntEQ(BIO_method_type(bio), 0x666);
|
|
|
|
BIO_free(bio);
|
|
BIO_meth_free(method);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_BIO_get_init(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA)
|
|
BIO_METHOD* method = NULL;
|
|
BIO* bio = NULL;
|
|
|
|
/* BIO_new with a custom method that calls BIO_set_init(bio, 1) */
|
|
ExpectNotNull(method = BIO_meth_new(WOLFSSL_BIO_UNDEF, "get_init_test"));
|
|
ExpectIntEQ(BIO_meth_set_create(method, custom_bio_createCb),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(BIO_meth_set_destroy(method, custom_bio_destroyCb),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
ExpectNotNull(bio = BIO_new(method));
|
|
|
|
/* createCb calls BIO_set_init(bio, 1), so get_init should return 1 */
|
|
ExpectIntEQ(BIO_get_init(bio), 1);
|
|
|
|
/* Clear init and verify it returns 0 */
|
|
BIO_set_init(bio, 0);
|
|
ExpectIntEQ(BIO_get_init(bio), 0);
|
|
|
|
/* Set init back and verify */
|
|
BIO_set_init(bio, 1);
|
|
ExpectIntEQ(BIO_get_init(bio), 1);
|
|
|
|
/* NULL should return 0 */
|
|
ExpectIntEQ(BIO_get_init(NULL), 0);
|
|
|
|
BIO_free(bio);
|
|
BIO_meth_free(method);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#endif /* !NO_BIO */
|
|
|