Merge pull request #10004 from julek-wolfssl/zd/21318

Add custom BIO callback dispatching
This commit is contained in:
David Garske
2026-03-23 09:54:30 -07:00
committed by GitHub
3 changed files with 238 additions and 11 deletions
+23 -10
View File
@@ -1303,6 +1303,13 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
return 0;
}
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
long ret;
WOLFSSL_MSG("Calling custom BIO ctrl pending callback");
ret = bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_PENDING, 0, NULL);
return (ret < 0) ? 0 : (size_t)ret;
}
if (bio->type == WOLFSSL_BIO_MD ||
bio->type == WOLFSSL_BIO_BASE64) {
/* these are wrappers only, get next bio */
@@ -1713,6 +1720,11 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
return WOLFSSL_BIO_ERROR;
}
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
WOLFSSL_MSG("Calling custom BIO reset callback");
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_RESET, 0, NULL);
}
switch (bio->type) {
#ifndef NO_FILESYSTEM
case WOLFSSL_BIO_FILE:
@@ -2016,6 +2028,13 @@ void* wolfSSL_BIO_get_data(WOLFSSL_BIO* bio)
return NULL;
}
void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
{
WOLFSSL_ENTER("wolfSSL_BIO_set_init");
if (bio != NULL)
bio->init = (byte)(init != 0);
}
/* If flag is 0 then blocking is set, if 1 then non blocking.
* Always returns WOLFSSL_SUCCESS.
*/
@@ -2184,7 +2203,10 @@ int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
if (bio == NULL)
return WOLFSSL_FATAL_ERROR;
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
WOLFSSL_MSG("Calling custom BIO get mem data callback");
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_INFO, 0, p);
}
mem_bio = bio;
/* Return pointer from last memory BIO in chain */
while (bio->next) {
@@ -3620,15 +3642,6 @@ int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
#ifdef OPENSSL_ALL
#ifndef NO_WOLFSSL_STUB
void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
{
WOLFSSL_STUB("wolfSSL_BIO_set_init");
(void)bio;
(void)init;
}
#endif /* NO_WOLFSSL_STUB */
void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO* bio, int shut)
{
WOLFSSL_ENTER("wolfSSL_BIO_set_shutdown");
+212
View File
@@ -1466,5 +1466,217 @@ int test_wolfSSL_BIO_BIO_ring_read(void)
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();
}
#endif /* !NO_BIO */
+3 -1
View File
@@ -42,6 +42,7 @@ int test_wolfSSL_BIO_reset(void);
int test_wolfSSL_BIO_get_len(void);
int test_wolfSSL_BIO(void);
int test_wolfSSL_BIO_BIO_ring_read(void);
int test_wolfSSL_BIO_custom_method(void);
#define TEST_OSSL_BIO_DECLS \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_gets), \
@@ -56,7 +57,8 @@ int test_wolfSSL_BIO_BIO_ring_read(void);
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_reset), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_len), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_BIO_ring_read)
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_BIO_ring_read), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_custom_method)
#define TEST_OSSL_BIO_TLS_DECLS \
TEST_DECL_GROUP("ossl_bio_tls", test_wolfSSL_BIO_connect), \