Reputation: 27155
int BIO_get_new_index(void); BIO_METHOD *BIO_meth_new(int type, const char *name);
BIO_meth_new()
creates a newBIO_METHOD
structure. It should be given a unique integertype
and a string that represents itsname
. UseBIO_get_new_index()
to get the value fortype
.
But I cannot find any example code that actually uses BIO_get_new_index()
! Even OpenSSL's own examples always do ad-hoc things like
// test/sslcorrupttest.c
#define BIO_TYPE_CUSTOM_FILTER (0x80 | BIO_TYPE_FILTER)
[...]
method_tls_corrupt = BIO_meth_new(BIO_TYPE_CUSTOM_FILTER, "TLS corrupt filter");
(BIO_get_new_index()
was added to OpenSSL on 2016-08-19, with no commit message and no tests.)
In my own code, I've been using either BIO_TYPE_FILTER
or BIO_TYPE_SOURCE_SINK
directly, like this:
BIO_METHOD *meth1 = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "StringBIO");
BIO_METHOD *meth2 = BIO_meth_new(BIO_TYPE_FILTER, "EavesdropBIO");
I have verified that BIO_meth_new
does really return a new BIO_METHOD*
in each case, so it's not naïvely using the supplied type
as an index into a global table. Example:
BIO_METHOD *meth3 = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "StringBIO");
BIO_METHOD *meth4 = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "OtherBIO");
assert(meth3 != meth4);
However, it worries me that what I'm doing might be unsafe (I mean, even more unsafe than using OpenSSL to begin with ;)). So I have two sub-questions:
What could go wrong if I use BIO_meth_new(BIO_TYPE_SOURCE_SINK, ...)
? In other words, why did OpenSSL decide to add BIO_get_new_index()
in 1.1.0?
If I should use BIO_get_new_index()
, how should I use it? Is it intended to be |
ed with the existing BIO_TYPE_
macros, like this [below]? If I execute these lines repeatedly, aren't I "leaking" new indices? or does BIO_meth_free
"free" the new indices as well as freeing the BIO_METHOD
structure?
BIO_METHOD *meth1 = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK, "StringBIO");
BIO_METHOD *meth2 = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_FILTER, "EavesdropBIO");
Upvotes: 3
Views: 1038
Reputation: 2912
(I am not an OpenSSL developer, so take this answer with a grain of salt.)
What could go wrong if I use
BIO_meth_new(BIO_TYPE_SOURCE_SINK, ...)
?
Nothing today, BUT: It is possible that a future version of OpenSSL could special-case the built-in BIO types. The OpenSSL source code already special-cases certain types like BIO_TYPE_SSL
and BIO_TYPE_MEM
. Generating your own BIO type future-proofs your code against that kind of shenanigans.
If I should use
BIO_get_new_index()
, how should I use it? Is it intended to be|
ed with the existingBIO_TYPE_
macros [...]?
Yes, it is meant to be |
ed with the flags BIO_TYPE_DESCRIPTOR
, BIO_TYPE_FILTER
, and BIO_TYPE_SOURCE_SINK
. The other types (e.g. BIO_TYPE_SOCKET
) are true types, not flags. This is an incredibly bad naming decision on the part of the OpenSSL developers. Documentation-wise, BIO_find_type
mentions which "types" are secretly flags.
If I execute these lines repeatedly, aren't I "leaking" new indices? or does
BIO_meth_free
"free" the new indices as well as freeing theBIO_METHOD
structure?
Yes, you would be leaking type indexes. BIO method type indexes are a finite resource that can be acquired but not released: BIO_meth_free
does not "free" the indexes, nor does any other procedure I am aware of. (You might not have thought of type indexes as a resource since BIO_get_new_index
does not acquire other kinds of resources like memory or file handles, but I like to think of "resource" as a very general concept.)
In fact, the type indexes are an extremely limited resource. The type flags start at 0x0100
, so the maximum type index you can create before interfering with the flags is 0x00FF
(i.e. 255). Worse, indexes from BIO_get_new_index
start at 128. (It is possible that these bounds could be relaxed in future versions of OpenSSL.)
There is good news: once you have released a BIO method with BIO_meth_free
, I suspect your application is free to re-use its index for a different BIO method. However, you will need to build the free list of available indexes yourself. It is probably not worth doing this; instead, write your application such that the number of BIO methods you need is a small compile-time constant. Do not allocate new ones in a loop. If you are writing a library, it is probably worth documenting how many BIO type indexes your library consumes.
Upvotes: 2