Skip to content

Commit 6bd1785

Browse files
authored
Merge pull request #10004 from julek-wolfssl/zd/21318
Add custom BIO callback dispatching
2 parents 15fa0b7 + 431ee9e commit 6bd1785

3 files changed

Lines changed: 238 additions & 11 deletions

File tree

src/bio.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,13 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
13031303
return 0;
13041304
}
13051305

1306+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
1307+
long ret;
1308+
WOLFSSL_MSG("Calling custom BIO ctrl pending callback");
1309+
ret = bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_PENDING, 0, NULL);
1310+
return (ret < 0) ? 0 : (size_t)ret;
1311+
}
1312+
13061313
if (bio->type == WOLFSSL_BIO_MD ||
13071314
bio->type == WOLFSSL_BIO_BASE64) {
13081315
/* these are wrappers only, get next bio */
@@ -1713,6 +1720,11 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
17131720
return WOLFSSL_BIO_ERROR;
17141721
}
17151722

1723+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
1724+
WOLFSSL_MSG("Calling custom BIO reset callback");
1725+
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_RESET, 0, NULL);
1726+
}
1727+
17161728
switch (bio->type) {
17171729
#ifndef NO_FILESYSTEM
17181730
case WOLFSSL_BIO_FILE:
@@ -2016,6 +2028,13 @@ void* wolfSSL_BIO_get_data(WOLFSSL_BIO* bio)
20162028
return NULL;
20172029
}
20182030

2031+
void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
2032+
{
2033+
WOLFSSL_ENTER("wolfSSL_BIO_set_init");
2034+
if (bio != NULL)
2035+
bio->init = (byte)(init != 0);
2036+
}
2037+
20192038
/* If flag is 0 then blocking is set, if 1 then non blocking.
20202039
* Always returns WOLFSSL_SUCCESS.
20212040
*/
@@ -2184,7 +2203,10 @@ int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
21842203

21852204
if (bio == NULL)
21862205
return WOLFSSL_FATAL_ERROR;
2187-
2206+
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
2207+
WOLFSSL_MSG("Calling custom BIO get mem data callback");
2208+
return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_INFO, 0, p);
2209+
}
21882210
mem_bio = bio;
21892211
/* Return pointer from last memory BIO in chain */
21902212
while (bio->next) {
@@ -3620,15 +3642,6 @@ int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
36203642

36213643
#ifdef OPENSSL_ALL
36223644

3623-
#ifndef NO_WOLFSSL_STUB
3624-
void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
3625-
{
3626-
WOLFSSL_STUB("wolfSSL_BIO_set_init");
3627-
(void)bio;
3628-
(void)init;
3629-
}
3630-
#endif /* NO_WOLFSSL_STUB */
3631-
36323645
void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO* bio, int shut)
36333646
{
36343647
WOLFSSL_ENTER("wolfSSL_BIO_set_shutdown");

tests/api/test_ossl_bio.c

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

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)