[openssl-users] DTLS fragmentation and mem BIO

Lorenzo Miniero lminiero at gmail.com
Fri Jun 5 11:16:03 UTC 2015


2015-06-05 12:34 GMT+02:00 Alfred E. Heggestad <aeh at db.org>:

>
>
> On 05/06/15 11:20, Lorenzo Miniero wrote:
>
>> 2015-06-05 10:31 GMT+02:00 Matt Caswell <matt at openssl.org <mailto:
>> matt at openssl.org>>:
>>
>>
>>
>>
>>     On 05/06/15 08:09, Lorenzo Miniero wrote:
>>      > Hi all,
>>      >
>>      > first of all, apologies if this has been asked before. I've
>> searched
>>      > archives pretty much everywhere, and only came to partial
>> indications as
>>      > to how this should be dealt with.
>>      >
>>      > The problem I'm facing deals with using DTLS with mem BIOs, as I
>> have to
>>      > take care of transport myself. Specifically, I've implemented a
>> WebRTC
>>      > gateway called Janus, which means all the connectivity related
>> stuff is
>>      > delegated to another library (libnice in this case). This mostly
>> works
>>      > great (kudos to you guys!), but I have problems as soon as packets
>>      > exceed the MTU, which can easily happen whenever, for instance,
>> you try
>>      > to handshake with certificates larger than 1024 bits. I read
>> around that
>>      > the DTLS stack in OpenSSL automatically deals with this, and in
>> fact
>>      > this seems to be happening: what isn't working is the BIO mem part
>> of this.
>>      >
>>      > More specifically, OpenSSL does indeed take care of fragmenting the
>>      > packets according to what is assumed to be the MTU (1472 by
>> default, or
>>      > the value as set in s->d1->mtu). The problem is that the mem BIO
>> ignores
>>      > that fragmentation info completely, and so, when you do an
>> BIO_read,
>>      > makes available at the application the whole packet anyway. This
>> results
>>      > in the whole buffer being passed to nice_agent_send (the method
>> libnice
>>      > exposes to send packets), which means it's just as not fragmenting
>>      > anything: the packet is too large and the network drops it. You can
>>      > verify this by using, e.g., a 4096 bits certificate, and capture
>> the
>>      > DTLS traffic with Wireshark: you'll see that the message is
>> recognized
>>      > as composed of not only multiple messages, but also fragments.
>>      >
>>      > Is there any way I can force the BIO to return the invididual
>>      > fragments/messages when I do a BIO_read, so that I can send
>> properly
>>      > sized packets? I've tried looking around but found no insight on
>> how to
>>      > do that. The only approach that came to my mind was to manually
>> inspect
>>      > the buffer that is returned, and split messages/fragments myself,
>> but
>>      > I'd rather avoid delving within the specifics of the protocol if
>> possible.
>>      >
>>      > Thanks in advance for any help you may provide me with!
>>
>>     Hmmmm. An interesting problem.
>>
>>     The issue is that a mem BIO has no knowledge of datagram semantics
>>     (perhaps we need to add something for OpenSSL 1.1.0).
>>
>>     In a dgram BIO each BIO_write translates to a single datagram being
>>     produced. In a mem BIO you just have a big bucket of memory, and every
>>     time you get a BIO_write you just add the data onto the end of
>>     everything that we've go so far, and so the packet boundaries are not
>>     respected.
>>
>>     How about you create a custom filter BIO? All it would need to do is
>>     proxy all calls down to the underlying mem BIO. Along the way though
>> it
>>     could take note of where the packet boundaries are, so when you call
>>     BIO_read it only gives it to you a datagram at a time.
>>
>>     Matt
>>
>>
>>
>> Thanks for the very quick answer!
>>
>> Your suggestion does indeed make much more sense that manually inspecting
>> the buffer as I thought of, as you don't need to know anything about the
>> protocol but
>> only to be ready to index the packets you see passing by. I never tried
>> writing a BIO filter but there's a first time for everything :-)
>>
>> Just one quick question about this: are messages/packets passed to the
>> BIO actually splitted, and then just queued by the mem BIO in the buffer,
>> or can there be
>> cases where a larger than normal buffer is passed to the BIO anyway,
>> meaning a manual splitting could be needed nevertheless from time to time?
>>
>>
>
> hey,
>
>
> I just want to point out that we have been using OpenSSL in the libre
> stack for
> a long time, with successful deployment.
>
>
> the DTLS code is here:
>
> http://www.creytiv.com/doxygen/re-dox/html/tls__udp_8c_source.html
>
>
> we are using 2 different BIOs; one for outgoing, one for incoming:
>
>
>
>         tc->sbio_in = BIO_new(BIO_s_mem());
>         if (!tc->sbio_in) {
>                 ERR_clear_error();
>                 err = ENOMEM;
>                 goto out;
>         }
>
>         tc->sbio_out = BIO_new(&bio_udp_send);
>         if (!tc->sbio_out) {
>                 ERR_clear_error();
>                 BIO_free(tc->sbio_in);
>                 err = ENOMEM;
>                 goto out;
>         }
>
>
>
Hi Alfred,

thanks for sharing this. So you've basically created a new BIO source/sink
type, and you use that one instead of a mem BIO for sending, right? That
might be an interesting approach (e.g., creating a custom BIO based on BIO
mem), especially if it turns out that implementing a filter will prove
harder than I hope.

Lorenzo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-users/attachments/20150605/5cc68ba9/attachment-0001.html>


More information about the openssl-users mailing list