d1_pkt.c:dtls1_get_record() processes DTLS records which it gets from 
the wire. At the same time, this function performs replay protection: It 
memorizes the (explicit) sequence numbers of the records and drops 
records that have already been processed.

The sequence numbers of the processed records are saved in a sliding 
bitmap window. The corresponding bit in the window is set to 1, if a 
specific sequence number is processed. The key point is that the MAC of 
the record is usually verified *before* the bitmap of sequence numbers 
is updated. This requires the receiving end to be in possession of the 
symmetric key used for integrity control.

With every renegotiation, the keys are renewed and a new epoch begins.

Due to reordering on the network, it may happen that a record from a
future epoch arrives during renegotiation. Because the keying material 
is not yet available, the integrity of these records can not be verified.

The aspect I'm complaining about is that OpenSSL updates the record 
bitmap *without* prior verification of the integrity of the record *iff* 
the record is from a future epoch.

Here's the code:

/* If this record is from the next epoch (either HM or ALERT),
  * buffer it since it cannot be processed at this time. Records
  * from the next epoch are marked as received even though they
  * are not processed, so as to prevent any potential resource
  * DoS attack */
if (is_next_epoch)
        {
        dtls1_record_bitmap_update(s, bitmap);
        dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
        rr->length = 0;
        s->packet_length = 0;
        goto again;
        }

In my opinion, there's no potential for resource DoS attacks because 
dtls1_buffer_record() limits the number of buffered records to 100.

However, as the code stands today, there is a potential for a DoS 
attack. An attacker might guess the source and destination UDP port as 
well as the number of the next epoch. They then send a faked DTLS record 
with a high sequence number, say n. As a result, OpenSSL moves forward 
the bitmap window and will drop any future record carrying a sequence 
number that is smaller than (n-64) i.e. which lies outside the window.

I suggest to improve on that situation by doing the following:

- Do *not* update the record bitmap if the record belongs to the next 
epoch. As a result, two records carrying the same sequence number may be 
buffered at the same time. However, one of these records might be 
invalid or faked.

- Buffer records from the next epoch only if a re-handshake is currently 
in progress.

Does that make sense?
Please let me know your opinions.

-Daniel

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to