openssl

Need suggestions on replacing the usage of BIO_meth_get_*() functions which are marked deprecated in OpenSSL 3.5.0


Recent OpenSSL 3.5.0 has deprecated certain BIO_meth_get_*() functions, but its replacements are not provided. Below is a C++ code fragment in my project:-

BIO_METHOD *_bio = BIO_meth_new(BIO_TYPE_SOCKET, "mysslsocket");
BIO_METHOD *tbio = _bio->Bio(); //Bio() method just returns _bio object
const BIO_METHOD *biom = BIO_s_socket();
BIO_meth_set_gets(tbio, BIO_meth_get_gets(biom));
BIO_meth_set_puts(tbio, BIO_meth_get_puts(biom));
BIO_meth_set_ctrl(tbio, BIO_meth_get_ctrl(biom));
BIO_meth_set_create(tbio, BIO_meth_get_create(biom));
BIO_meth_set_destroy(tbio, BIO_meth_get_destroy(biom));
BIO_meth_set_callback_ctrl(tbio, BIO_meth_get_callback_ctrl(biom));
auto wbio = BIO_new(tbio);

As BIO_meth_get_*() functions are deprecated, can someone please suggest how to rewrite above code in OpenSSL 3.5.0 version compliant?


Solution

  • These functions were deprecated because they are considered unsafe.

    The man page has this to say about it:

    It is not safe to use BIO_meth_get_ functions to reuse the BIO implementation of BIOs implemented by OpenSSL itself with application-implemented BIOs. Instead either the applications ought to implement these functions themselves or they should implement a filter BIO.

    For more details please see https://github.com/openssl/openssl/issues/26047.

    The suggested alternative to is to use a filter BIO instead. The issue linked to above from the man page has more details about why this is unsafe and also describes an alternative approach:

    If the application is meaningfully calling into the base BIO, OpenSSL already has a notion of filter BIOs. A good solution would be to either make a filter BIO and explicitly defer to BIO_next, or just encapsulate a BIO in your custom BIO's data yourself. This would make closely align with how OOP subclassing actually works.

    There is a description of filter BIOs on this man page:

    A filter BIO takes data from one BIO and passes it through to another, or the application. The data may be left unmodified (for example a message digest BIO) or translated (for example an encryption BIO). The effect of a filter BIO may change according to the I/O operation it is performing: for example an encryption BIO will encrypt data if it is being written to and decrypt data if it is being read from.

    BIOs can be joined together to form a chain (a single BIO is a chain with one component). A chain normally consists of one source/sink BIO and one or more filter BIOs. Data read from or written to the first BIO then traverses the chain to the end (normally a source/sink BIO).

    For inspiration you might look at this implementation of a filter BIO from within the OpenSSL test suite:

    https://github.com/openssl/openssl/blob/305bbc1837ff31389e8330f14446286695e105fa/test/helpers/ssltestlib.c#L53-L254