Skip to content

Commit 056ed9e

Browse files
committed
Add custom BIO callback dispatching
- Route BIO_ctrl_pending, BIO_reset, and BIO_get_mem_data through the custom method's ctrlCb when set, enabling fully custom BIO types to handle these operations. - Add test_wolfSSL_BIO_custom_method that exercises a custom BIO with all callbacks (create, destroy, read, write, puts, gets, ctrl) and verifies each callback is invoked via bitfield tracking.
1 parent 8169780 commit 056ed9e

3 files changed

Lines changed: 226 additions & 2 deletions

File tree

src/bio.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,11 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
13031303
return 0;
13041304
}
13051305

1306+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
1307+
WOLFSSL_MSG("Calling custom BIO ctrl pending callback");
1308+
return (size_t)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_PENDING, 0, NULL);
1309+
}
1310+
13061311
if (bio->type == WOLFSSL_BIO_MD ||
13071312
bio->type == WOLFSSL_BIO_BASE64) {
13081313
/* these are wrappers only, get next bio */
@@ -1713,6 +1718,11 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
17131718
return WOLFSSL_BIO_ERROR;
17141719
}
17151720

1721+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
1722+
WOLFSSL_MSG("Calling custom BIO reset callback");
1723+
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_RESET, 0, NULL);
1724+
}
1725+
17161726
switch (bio->type) {
17171727
#ifndef NO_FILESYSTEM
17181728
case WOLFSSL_BIO_FILE:
@@ -2184,7 +2194,10 @@ int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
21842194

21852195
if (bio == NULL)
21862196
return WOLFSSL_FATAL_ERROR;
2187-
2197+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
2198+
WOLFSSL_MSG("Calling custom BIO get mem data callback");
2199+
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_INFO, 0, p);
2200+
}
21882201
mem_bio = bio;
21892202
/* Return pointer from last memory BIO in chain */
21902203
while (bio->next) {

tests/api/test_ossl_bio.c

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,5 +1466,214 @@ int test_wolfSSL_BIO_BIO_ring_read(void)
14661466
return EXPECT_RESULT();
14671467
}
14681468

1469+
/* Custom BIO backing store for test_wolfSSL_BIO_custom_method */
1470+
#if defined(OPENSSL_EXTRA)
1471+
1472+
struct custom_bio_data {
1473+
char buf[256];
1474+
int len;
1475+
byte createCalled:1;
1476+
byte destroyCalled:1;
1477+
byte writeCalled:1;
1478+
byte readCalled:1;
1479+
byte putsCalled:1;
1480+
byte getsCalled:1;
1481+
byte ctrlCalled:1;
1482+
};
1483+
1484+
static int custom_bio_createCb(WOLFSSL_BIO* bio)
1485+
{
1486+
struct custom_bio_data* data;
1487+
data = (struct custom_bio_data*)XMALLOC(sizeof(*data), NULL,
1488+
DYNAMIC_TYPE_TMP_BUFFER);
1489+
if (data == NULL)
1490+
return 0;
1491+
XMEMSET(data, 0, sizeof(*data));
1492+
data->createCalled = 1;
1493+
BIO_set_data(bio, data);
1494+
BIO_set_init(bio, 1);
1495+
return 1;
1496+
}
1497+
1498+
static int custom_bio_destroyCb(WOLFSSL_BIO* bio)
1499+
{
1500+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1501+
if (data != NULL) {
1502+
data->destroyCalled = 1;
1503+
XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1504+
}
1505+
BIO_set_data(bio, NULL);
1506+
return 1;
1507+
}
1508+
1509+
static int custom_bio_writeCb(WOLFSSL_BIO* bio, const char* in, int len)
1510+
{
1511+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1512+
int avail;
1513+
if (data == NULL || in == NULL || len <= 0)
1514+
return -1;
1515+
data->writeCalled = 1;
1516+
avail = (int)sizeof(data->buf) - data->len;
1517+
if (len > avail)
1518+
len = avail;
1519+
XMEMCPY(data->buf + data->len, in, (size_t)len);
1520+
data->len += len;
1521+
return len;
1522+
}
1523+
1524+
static int custom_bio_readCb(WOLFSSL_BIO* bio, char* out, int len)
1525+
{
1526+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1527+
if (data == NULL || out == NULL || len <= 0)
1528+
return -1;
1529+
data->readCalled = 1;
1530+
if (data->len == 0)
1531+
return 0;
1532+
if (len > data->len)
1533+
len = data->len;
1534+
XMEMCPY(out, data->buf, (size_t)len);
1535+
/* shift remaining data */
1536+
data->len -= len;
1537+
if (data->len > 0)
1538+
XMEMMOVE(data->buf, data->buf + len, (size_t)data->len);
1539+
return len;
1540+
}
1541+
1542+
static int custom_bio_putsCb(WOLFSSL_BIO* bio, const char* str)
1543+
{
1544+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1545+
if (str == NULL || data == NULL)
1546+
return -1;
1547+
data->putsCalled = 1;
1548+
return custom_bio_writeCb(bio, str, (int)XSTRLEN(str));
1549+
}
1550+
1551+
static int custom_bio_getsCb(WOLFSSL_BIO* bio, char* buf, int sz)
1552+
{
1553+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1554+
int i;
1555+
int readLen;
1556+
if (data == NULL || buf == NULL || sz <= 1)
1557+
return -1;
1558+
data->getsCalled = 1;
1559+
if (data->len == 0)
1560+
return 0;
1561+
/* read up to newline or sz-1 bytes */
1562+
readLen = (sz - 1 < data->len) ? sz - 1 : data->len;
1563+
for (i = 0; i < readLen; i++) {
1564+
buf[i] = data->buf[i];
1565+
if (data->buf[i] == '\n') {
1566+
i++;
1567+
break;
1568+
}
1569+
}
1570+
buf[i] = '\0';
1571+
/* shift remaining data */
1572+
data->len -= i;
1573+
if (data->len > 0)
1574+
XMEMMOVE(data->buf, data->buf + i, (size_t)data->len);
1575+
return i;
1576+
}
1577+
1578+
static long custom_bio_ctrlCb(WOLFSSL_BIO* bio, int cmd, long larg, void* parg)
1579+
{
1580+
struct custom_bio_data* data = (struct custom_bio_data*)BIO_get_data(bio);
1581+
(void)larg;
1582+
if (data == NULL)
1583+
return -1;
1584+
data->ctrlCalled = 1;
1585+
switch (cmd) {
1586+
case BIO_CTRL_PENDING:
1587+
return (long)data->len;
1588+
case BIO_CTRL_RESET:
1589+
data->len = 0;
1590+
return WOLFSSL_SUCCESS;
1591+
case BIO_CTRL_FLUSH:
1592+
return 1;
1593+
case BIO_CTRL_INFO:
1594+
if (parg != NULL)
1595+
*(char**)parg = data->buf;
1596+
return (long)data->len;
1597+
default:
1598+
return 0;
1599+
}
1600+
}
1601+
1602+
#endif /* OPENSSL_EXTRA */
1603+
1604+
int test_wolfSSL_BIO_custom_method(void)
1605+
{
1606+
EXPECT_DECLS;
1607+
#if defined(OPENSSL_EXTRA)
1608+
BIO_METHOD* method = NULL;
1609+
BIO* bio = NULL;
1610+
struct custom_bio_data* data = NULL;
1611+
char buf[256];
1612+
char* memPtr = NULL;
1613+
1614+
/* Create custom method and set all callbacks */
1615+
ExpectNotNull(method = BIO_meth_new(WOLFSSL_BIO_UNDEF, "custom_test"));
1616+
ExpectIntEQ(BIO_meth_set_create(method, custom_bio_createCb),
1617+
WOLFSSL_SUCCESS);
1618+
ExpectIntEQ(BIO_meth_set_destroy(method, custom_bio_destroyCb),
1619+
WOLFSSL_SUCCESS);
1620+
ExpectIntEQ(BIO_meth_set_write(method, custom_bio_writeCb),
1621+
WOLFSSL_SUCCESS);
1622+
ExpectIntEQ(BIO_meth_set_read(method, custom_bio_readCb),
1623+
WOLFSSL_SUCCESS);
1624+
ExpectIntEQ(BIO_meth_set_puts(method, custom_bio_putsCb),
1625+
WOLFSSL_SUCCESS);
1626+
ExpectIntEQ(BIO_meth_set_gets(method, custom_bio_getsCb),
1627+
WOLFSSL_SUCCESS);
1628+
ExpectIntEQ(BIO_meth_set_ctrl(method, custom_bio_ctrlCb),
1629+
WOLFSSL_SUCCESS);
1630+
1631+
/* Create BIO - should invoke createCb */
1632+
ExpectNotNull(bio = BIO_new(method));
1633+
ExpectNotNull(data = (struct custom_bio_data*)BIO_get_data(bio));
1634+
ExpectTrue(data->createCalled);
1635+
1636+
/* write */
1637+
ExpectIntEQ(BIO_write(bio, "hello", 5), 5);
1638+
ExpectTrue(data->writeCalled);
1639+
1640+
/* ctrl_pending via ctrlCb */
1641+
ExpectIntEQ((int)BIO_ctrl_pending(bio), 5);
1642+
ExpectTrue(data->ctrlCalled);
1643+
1644+
/* read */
1645+
XMEMSET(buf, 0, sizeof(buf));
1646+
ExpectIntEQ(BIO_read(bio, buf, 5), 5);
1647+
ExpectBufEQ(buf, "hello", 5);
1648+
ExpectTrue(data->readCalled);
1649+
ExpectIntEQ((int)BIO_ctrl_pending(bio), 0);
1650+
1651+
/* puts */
1652+
ExpectIntEQ(BIO_puts(bio, "world\nfoo"), 9);
1653+
ExpectTrue(data->putsCalled);
1654+
ExpectIntEQ((int)BIO_ctrl_pending(bio), 9);
1655+
1656+
/* gets - should read up to and including first newline */
1657+
XMEMSET(buf, 0, sizeof(buf));
1658+
ExpectIntEQ(BIO_gets(bio, buf, (int)sizeof(buf)), 6);
1659+
ExpectStrEQ(buf, "world\n");
1660+
ExpectTrue(data->getsCalled);
1661+
ExpectIntEQ((int)BIO_ctrl_pending(bio), 3);
1662+
1663+
/* get_mem_data via BIO_CTRL_INFO */
1664+
ExpectIntEQ(BIO_get_mem_data(bio, &memPtr), 3);
1665+
ExpectNotNull(memPtr);
1666+
1667+
/* reset via ctrlCb */
1668+
ExpectIntEQ(BIO_reset(bio), WOLFSSL_SUCCESS);
1669+
ExpectIntEQ((int)BIO_ctrl_pending(bio), 0);
1670+
1671+
/* free - should invoke destroyCb */
1672+
BIO_free(bio);
1673+
BIO_meth_free(method);
1674+
#endif
1675+
return EXPECT_RESULT();
1676+
}
1677+
14691678
#endif /* !NO_BIO */
14701679

tests/api/test_ossl_bio.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int test_wolfSSL_BIO_reset(void);
4242
int test_wolfSSL_BIO_get_len(void);
4343
int test_wolfSSL_BIO(void);
4444
int test_wolfSSL_BIO_BIO_ring_read(void);
45+
int test_wolfSSL_BIO_custom_method(void);
4546

4647
#define TEST_OSSL_BIO_DECLS \
4748
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_gets), \
@@ -56,7 +57,8 @@ int test_wolfSSL_BIO_BIO_ring_read(void);
5657
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_reset), \
5758
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_len), \
5859
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO), \
59-
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_BIO_ring_read)
60+
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_BIO_ring_read), \
61+
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_custom_method)
6062

6163
#define TEST_OSSL_BIO_TLS_DECLS \
6264
TEST_DECL_GROUP("ossl_bio_tls", test_wolfSSL_BIO_connect), \

0 commit comments

Comments
 (0)