1fb9fdc302
The DTLS implementation provides some protection against replay attacks in accordance with RFC6347 section 4.1.2.6. A sliding "window" of valid record sequence numbers is maintained with the "right" hand edge of the window set to the highest sequence number we have received so far. Records that arrive that are off the "left" hand edge of the window are rejected. Records within the window are checked against a list of records received so far. If we already received it then we also reject the new record. If we have not already received the record, or the sequence number is off the right hand edge of the window then we verify the MAC of the record. If MAC verification fails then we discard the record. Otherwise we mark the record as received. If the sequence number was off the right hand edge of the window, then we slide the window along so that the right hand edge is in line with the newly received sequence number. Records may arrive for future epochs, i.e. a record from after a CCS being sent, can arrive before the CCS does if the packets get re-ordered. As we have not yet received the CCS we are not yet in a position to decrypt or validate the MAC of those records. OpenSSL places those records on an unprocessed records queue. It additionally updates the window immediately, even though we have not yet verified the MAC. This will only occur if currently in a handshake/renegotiation. This could be exploited by an attacker by sending a record for the next epoch (which does not have to decrypt or have a valid MAC), with a very large sequence number. This means the right hand edge of the window is moved very far to the right, and all subsequent legitimate packets are dropped causing a denial of service. A similar effect can be achieved during the initial handshake. In this case there is no MAC key negotiated yet. Therefore an attacker can send a message for the current epoch with a very large sequence number. The code will process the record as normal. If the hanshake message sequence number (as opposed to the record sequence number that we have been talking about so far) is in the future then the injected message is bufferred to be handled later, but the window is still updated. Therefore all subsequent legitimate handshake records are dropped. This aspect is not considered a security issue because there are many ways for an attacker to disrupt the initial handshake and prevent it from completing successfully (e.g. injection of a handshake message will cause the Finished MAC to fail and the handshake to be aborted). This issue comes about as a result of trying to do replay protection, but having no integrity mechanism in place yet. Does it even make sense to have replay protection in epoch 0? That issue isn't addressed here though. This addressed an OCAP Audit issue. CVE-2016-2181 Reviewed-by: Richard Levitte <levitte@openssl.org>
114 lines
6.1 KiB
C
114 lines
6.1 KiB
C
/*
|
|
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* The following macros/functions are PRIVATE to the record layer. They *
|
|
* should NOT be used outside of the record layer. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
/* Functions/macros provided by the RECORD_LAYER component */
|
|
|
|
#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
|
|
#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
|
|
#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec)
|
|
#define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p))
|
|
#define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0)
|
|
#define RECORD_LAYER_get_rstate(rl) ((rl)->rstate)
|
|
#define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st))
|
|
#define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence)
|
|
#define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence)
|
|
#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes)
|
|
#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n))
|
|
#define RECORD_LAYER_inc_empty_record_count(rl) ((rl)->empty_record_count++)
|
|
#define RECORD_LAYER_reset_empty_record_count(rl) \
|
|
((rl)->empty_record_count = 0)
|
|
#define RECORD_LAYER_get_empty_record_count(rl) ((rl)->empty_record_count)
|
|
#define RECORD_LAYER_is_first_record(rl) ((rl)->is_first_record)
|
|
#define RECORD_LAYER_set_first_record(rl) ((rl)->is_first_record = 1)
|
|
#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
|
|
#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)
|
|
|
|
__owur int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold);
|
|
|
|
void RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, const unsigned char *ws);
|
|
DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
|
|
unsigned int *is_next_epoch);
|
|
int dtls1_process_buffered_records(SSL *s);
|
|
int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue);
|
|
int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority);
|
|
void ssl3_record_sequence_update(unsigned char *seq);
|
|
|
|
/* Functions provided by the DTLS1_BITMAP component */
|
|
|
|
int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
|
|
void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
|
|
|
|
/* Macros/functions provided by the SSL3_BUFFER component */
|
|
|
|
#define SSL3_BUFFER_get_buf(b) ((b)->buf)
|
|
#define SSL3_BUFFER_set_buf(b, n) ((b)->buf = (n))
|
|
#define SSL3_BUFFER_get_len(b) ((b)->len)
|
|
#define SSL3_BUFFER_set_len(b, l) ((b)->len = (l))
|
|
#define SSL3_BUFFER_get_left(b) ((b)->left)
|
|
#define SSL3_BUFFER_set_left(b, l) ((b)->left = (l))
|
|
#define SSL3_BUFFER_add_left(b, l) ((b)->left += (l))
|
|
#define SSL3_BUFFER_get_offset(b) ((b)->offset)
|
|
#define SSL3_BUFFER_set_offset(b, o) ((b)->offset = (o))
|
|
#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
|
|
#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
|
|
#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
|
|
|
|
void SSL3_BUFFER_clear(SSL3_BUFFER *b);
|
|
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
|
|
void SSL3_BUFFER_release(SSL3_BUFFER *b);
|
|
__owur int ssl3_setup_read_buffer(SSL *s);
|
|
__owur int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len);
|
|
int ssl3_release_read_buffer(SSL *s);
|
|
int ssl3_release_write_buffer(SSL *s);
|
|
|
|
/* Macros/functions provided by the SSL3_RECORD component */
|
|
|
|
#define SSL3_RECORD_get_type(r) ((r)->type)
|
|
#define SSL3_RECORD_set_type(r, t) ((r)->type = (t))
|
|
#define SSL3_RECORD_get_length(r) ((r)->length)
|
|
#define SSL3_RECORD_set_length(r, l) ((r)->length = (l))
|
|
#define SSL3_RECORD_add_length(r, l) ((r)->length += (l))
|
|
#define SSL3_RECORD_sub_length(r, l) ((r)->length -= (l))
|
|
#define SSL3_RECORD_get_data(r) ((r)->data)
|
|
#define SSL3_RECORD_set_data(r, d) ((r)->data = (d))
|
|
#define SSL3_RECORD_get_input(r) ((r)->input)
|
|
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
|
|
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
|
|
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
|
|
#define SSL3_RECORD_get_off(r) ((r)->off)
|
|
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
|
|
#define SSL3_RECORD_add_off(r, o) ((r)->off += (o))
|
|
#define SSL3_RECORD_get_epoch(r) ((r)->epoch)
|
|
#define SSL3_RECORD_is_sslv2_record(r) \
|
|
((r)->rec_version == SSL2_VERSION)
|
|
#define SSL3_RECORD_is_read(r) ((r)->read)
|
|
#define SSL3_RECORD_set_read(r) ((r)->read = 1)
|
|
|
|
void SSL3_RECORD_clear(SSL3_RECORD *r, unsigned int num_recs);
|
|
void SSL3_RECORD_release(SSL3_RECORD *r, unsigned int num_recs);
|
|
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
|
|
int ssl3_get_record(SSL *s);
|
|
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
|
|
__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
|
|
void ssl3_cbc_copy_mac(unsigned char *out,
|
|
const SSL3_RECORD *rec, unsigned md_size);
|
|
__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
|
|
unsigned block_size, unsigned mac_size);
|
|
__owur int tls1_cbc_remove_padding(const SSL *s,
|
|
SSL3_RECORD *rec,
|
|
unsigned block_size, unsigned mac_size);
|
|
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
|
|
__owur int dtls1_get_record(SSL *s);
|