]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Move some DTLS read code into the read record layer
authorMatt Caswell <matt@openssl.org>
Thu, 2 Jun 2022 15:29:04 +0000 (16:29 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 18 Aug 2022 15:38:13 +0000 (16:38 +0100)
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18132)

19 files changed:
ssl/d1_lib.c
ssl/record/build.info
ssl/record/methods/build.info
ssl/record/methods/dtls_meth.c [new file with mode: 0644]
ssl/record/methods/ktls_meth.c
ssl/record/methods/recmethod_local.h
ssl/record/methods/ssl3_meth.c
ssl/record/methods/tls13_meth.c
ssl/record/methods/tls1_meth.c
ssl/record/methods/tls_common.c
ssl/record/methods/tlsany_meth.c
ssl/record/rec_layer_d1.c
ssl/record/rec_layer_s3.c
ssl/record/record.h
ssl/record/record_local.h
ssl/record/ssl3_record.c
ssl/ssl_lib.c
ssl/statem/statem_dtls.c
test/sslapitest.c

index dac7abd8a60260bd8878e18c9c9a627bb2b6ad18..904a19a28ad7d11ee40c44ff08599c5775bfd6d8 100644 (file)
@@ -848,6 +848,7 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
         BIO_ADDR_clear(client);
 
     /* Buffer the record in the processed_rcds queue */
+    /* TODO(RECLAYER): This is nasty and reaches inside the record layer. FIXME */
     if (!dtls_buffer_listen_record(s, reclen, seq, align))
         return -1;
 
index 3786669b00857fce704910cb3e3975de8a1df26c..15a4f8b386d84bb838a2d716fd6260ee0984c858 100644 (file)
@@ -12,7 +12,7 @@ ENDIF
 
 SOURCE[../../libssl]=\
         rec_layer_s3.c rec_layer_d1.c ssl3_buffer.c  ssl3_record.c \
-        dtls1_bitmap.c ssl3_record_tls13.c
+        ssl3_record_tls13.c
 
 # For shared builds we need to include the sources needed in providers
 # (tls_pad.c) in libssl as well.
index 2faecb138be2a2c7de2ab2a1219f0ec47590dd2c..064bcaf177a003be9134d159bac108dfa815408e 100644 (file)
@@ -5,7 +5,7 @@ ENDIF
 
 SOURCE[../../../libssl]=\
         tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c \
-        $KTLSSRC
+        dtls_meth.c $KTLSSRC
 
 # For shared builds we need to include the sources needed in providers
 # (ssl3_cbc.c) in libssl as well.
diff --git a/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c
new file mode 100644 (file)
index 0000000..3c62746
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+#include "../../ssl_local.h"
+#include "../record_local.h"
+#include "recmethod_local.h"
+
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+{
+    int64_t ret;
+    uint64_t l1, l2;
+
+    n2l8(v1, l1);
+    n2l8(v2, l2);
+
+    ret = l1 - l2;
+
+    /* We do not permit wrap-around */
+    if (l1 > l2 && ret < 0)
+        return 128;
+    else if (l2 > l1 && ret > 0)
+        return -128;
+
+    if (ret > 128)
+        return 128;
+    else if (ret < -128)
+        return -128;
+    else
+        return (int)ret;
+}
+
+static int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+    int cmp;
+    unsigned int shift;
+    const unsigned char *seq = s->rlayer.read_sequence;
+    OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+
+    cmp = satsub64be(seq, bitmap->max_seq_num);
+    if (cmp > 0) {
+        SSL3_RECORD_set_seq_num(&rl->rrec[0], seq);
+        return 1;               /* this record in new */
+    }
+    shift = -cmp;
+    if (shift >= sizeof(bitmap->map) * 8)
+        return 0;               /* stale, outside the window */
+    else if (bitmap->map & (1UL << shift))
+        return 0;               /* record previously received */
+
+    SSL3_RECORD_set_seq_num(&rl->rrec[0], seq);
+    return 1;
+}
+
+static void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+    int cmp;
+    unsigned int shift;
+    const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+    cmp = satsub64be(seq, bitmap->max_seq_num);
+    if (cmp > 0) {
+        shift = cmp;
+        if (shift < sizeof(bitmap->map) * 8)
+            bitmap->map <<= shift, bitmap->map |= 1UL;
+        else
+            bitmap->map = 1UL;
+        memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE);
+    } else {
+        shift = -cmp;
+        if (shift < sizeof(bitmap->map) * 8)
+            bitmap->map |= 1UL << shift;
+    }
+}
+
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
+                                      unsigned int *is_next_epoch)
+{
+    OSSL_RECORD_LAYER *rl = s->rrl;
+    *is_next_epoch = 0;
+
+    /* In current epoch, accept HM, CCS, DATA, & ALERT */
+    if (rr->epoch == s->rlayer.d->r_epoch)
+        return &s->rlayer.d->bitmap;
+
+    /*
+     * Only HM and ALERT messages can be from the next epoch and only if we
+     * have already processed all of the unprocessed records from the last
+     * epoch
+     */
+    else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
+             rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
+             (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+        *is_next_epoch = 1;
+        return &s->rlayer.d->next_bitmap;
+    }
+
+    return NULL;
+}
+
+static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+    int i;
+    int enc_err;
+    SSL_SESSION *sess;
+    SSL3_RECORD *rr;
+    int imac_size;
+    size_t mac_size = 0;
+    unsigned char md[EVP_MAX_MD_SIZE];
+    size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
+    SSL_MAC_BUF macbuf = { NULL, 0 };
+    int ret = 0;
+    OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+    rr = &rl->rrec[0];
+    sess = s->session;
+
+    /*
+     * At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+     * and we have that many bytes in s->rlayer.packet
+     */
+    rr->input = &(s->rrlmethod->get0_packet(s->rrl)[DTLS1_RT_HEADER_LENGTH]);
+
+    /*
+     * ok, we can now read from 's->rlayer.packet' data into 'rr'. rr->input
+     * points at rr->length bytes, which need to be copied into rr->data by
+     * either the decryption or by the decompression. When the data is 'copied'
+     * into the rr->data buffer, rr->input will be pointed at the new buffer
+     */
+
+    /*
+     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+     * bytes of encrypted compressed stuff.
+     */
+
+    /* check is not needed I believe */
+    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+        SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+        return 0;
+    }
+
+    /* decrypt in place in 'rr->input' */
+    rr->data = rr->input;
+    rr->orig_len = rr->length;
+
+    if (s->read_hash != NULL) {
+        const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
+
+        if (tmpmd != NULL) {
+            imac_size = EVP_MD_get_size(tmpmd);
+            if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+                    return 0;
+            }
+            mac_size = (size_t)imac_size;
+        }
+    }
+
+    if (SSL_READ_ETM(s) && s->read_hash) {
+        unsigned char *mac;
+
+        if (rr->orig_len < mac_size) {
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
+            return 0;
+        }
+        rr->length -= mac_size;
+        mac = rr->data + rr->length;
+        i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
+        if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
+            SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+                     SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+            return 0;
+        }
+        /*
+         * We've handled the mac now - there is no MAC inside the encrypted
+         * record
+         */
+        mac_size = 0;
+    }
+
+    /*
+     * Set a mark around the packet decryption attempt.  This is DTLS, so
+     * bad packets are just ignored, and we don't want to leave stray
+     * errors in the queue from processing bogus junk that we ignored.
+     */
+    ERR_set_mark();
+    enc_err = ssl->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
+
+    /*-
+     * enc_err is:
+     *    0: if the record is publicly invalid, or an internal error, or AEAD
+     *       decryption failed, or ETM decryption failed.
+     *    1: Success or MTE decryption failed (MAC will be randomised)
+     */
+    if (enc_err == 0) {
+        ERR_pop_to_mark();
+        if (ossl_statem_in_error(s)) {
+            /* SSLfatal() got called */
+            goto end;
+        }
+        /* For DTLS we simply ignore bad packets. */
+        rr->length = 0;
+        s->rrlmethod->reset_packet_length(s->rrl);
+        goto end;
+    }
+    ERR_clear_last_mark();
+    OSSL_TRACE_BEGIN(TLS) {
+        BIO_printf(trc_out, "dec %zd\n", rr->length);
+        BIO_dump_indent(trc_out, rr->data, rr->length, 4);
+    } OSSL_TRACE_END(TLS);
+
+    /* r->length is now the compressed data plus mac */
+    if ((sess != NULL)
+            && !SSL_READ_ETM(s)
+            && (s->enc_read_ctx != NULL)
+            && (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
+        /* s->read_hash != NULL => mac_size != -1 */
+
+        i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
+        if (i == 0 || macbuf.mac == NULL
+            || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
+            enc_err = 0;
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+            enc_err = 0;
+    }
+
+    if (enc_err == 0) {
+        /* decryption failed, silently discard message */
+        rr->length = 0;
+        s->rrlmethod->reset_packet_length(s->rrl);
+        goto end;
+    }
+
+    /* r->length is now just compressed */
+    if (s->expand != NULL) {
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+            SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
+                     SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+            goto end;
+        }
+        if (!ssl3_do_uncompress(s, rr)) {
+            SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
+            goto end;
+        }
+    }
+
+    /* use current Max Fragment Length setting if applicable */
+    if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
+        max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
+
+    /* send overflow if the plaintext is too long now it has passed MAC */
+    if (rr->length > max_plain_length) {
+        SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+        goto end;
+    }
+
+    rr->off = 0;
+    /*-
+     * So at this point the following is true
+     * ssl->s3.rrec.type   is the type of record
+     * ssl->s3.rrec.length == number of bytes in record
+     * ssl->s3.rrec.off    == offset to first valid byte
+     * ssl->s3.rrec.data   == where to take bytes from, increment
+     *                        after use :-).
+     */
+
+    /* we have pulled in a full packet so zero things */
+    s->rrlmethod->reset_packet_length(s->rrl);
+
+    /* Mark receipt of record. */
+    dtls1_record_bitmap_update(s, bitmap);
+
+    ret = 1;
+ end:
+    if (macbuf.alloced)
+        OPENSSL_free(macbuf.mac);
+    return ret;
+}
+
+static int dtls_rlayer_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
+                                     unsigned char *priority)
+{
+    DTLS_RLAYER_RECORD_DATA *rdata;
+    pitem *item;
+    OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+
+    /* Limit the size of the queue to prevent DOS attacks */
+    if (pqueue_size(queue->q) >= 100)
+        return 0;
+
+    rdata = OPENSSL_malloc(sizeof(*rdata));
+    item = pitem_new(priority, rdata);
+    if (rdata == NULL || item == NULL) {
+        OPENSSL_free(rdata);
+        pitem_free(item);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return -1;
+    }
+
+    rdata->packet = s->rrlmethod->get0_packet(s->rrl);
+    rdata->packet_length = s->rrlmethod->get_packet_length(s->rrl);
+    memcpy(&(rdata->rbuf), s->rrlmethod->get0_rbuf(s->rrl), sizeof(SSL3_BUFFER));
+    memcpy(&(rdata->rrec), &rl->rrec[0], sizeof(SSL3_RECORD));
+
+    item->data = rdata;
+
+    s->rrlmethod->set0_packet(s->rrl, NULL, 0);
+    memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
+    memset(&rl->rrec[0], 0, sizeof(rl->rrec[0]));
+
+    if (!ssl3_setup_buffers(s)) {
+        /* SSLfatal() already called */
+        OPENSSL_free(rdata->rbuf.buf);
+        OPENSSL_free(rdata);
+        pitem_free(item);
+        return -1;
+    }
+
+    if (pqueue_insert(queue->q, item) == NULL) {
+        /* Must be a duplicate so ignore it */
+        OPENSSL_free(rdata->rbuf.buf);
+        OPENSSL_free(rdata);
+        pitem_free(item);
+    }
+
+    return 1;
+}
+
+/* copy buffered record into SSL structure */
+static int dtls_copy_rlayer_record(OSSL_RECORD_LAYER *rl, pitem *item)
+{
+    DTLS_RLAYER_RECORD_DATA *rdata;
+    SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
+
+    rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+
+    SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
+
+    s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
+    memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+    memcpy(&rl->rrec[0], &(rdata->rrec), sizeof(SSL3_RECORD));
+
+    /* Set proper sequence number for mac calculation */
+    memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
+
+    return 1;
+}
+
+static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl,
+                                                record_pqueue *queue)
+{
+    pitem *item;
+
+    item = pqueue_pop(queue->q);
+    if (item) {
+        dtls_copy_rlayer_record(rl, item);
+
+        OPENSSL_free(item->data);
+        pitem_free(item);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
+{
+    pitem *item;
+    SSL3_BUFFER *rb;
+    SSL3_RECORD *rr;
+    DTLS1_BITMAP *bitmap;
+    unsigned int is_next_epoch;
+    int replayok = 1;
+    OSSL_RECORD_LAYER *rl = s->rrl;
+
+    item = pqueue_peek(rl->unprocessed_rcds.q);
+    if (item) {
+        /* Check if epoch is current. */
+        if (rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
+            return 1;         /* Nothing to do. */
+
+        rr = rl->rrec;
+
+        rb = s->rrlmethod->get0_rbuf(s->rrl);
+
+        if (SSL3_BUFFER_get_left(rb) > 0) {
+            /*
+             * We've still got data from the current packet to read. There could
+             * be a record from the new epoch in it - so don't overwrite it
+             * with the unprocessed records yet (we'll do it when we've
+             * finished reading the current packet).
+             */
+            return 1;
+        }
+
+        /* Process all the records. */
+        while (pqueue_peek(rl->unprocessed_rcds.q)) {
+            dtls_retrieve_rlayer_buffered_record(rl, &(rl->unprocessed_rcds));
+            bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+            if (bitmap == NULL) {
+                /*
+                 * Should not happen. This will only ever be NULL when the
+                 * current record is from a different epoch. But that cannot
+                 * be the case because we already checked the epoch above
+                 */
+                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+                 return 0;
+            }
+#ifndef OPENSSL_NO_SCTP
+            /* Only do replay check if no SCTP bio */
+            if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+            {
+                /*
+                 * Check whether this is a repeat, or aged record. We did this
+                 * check once already when we first received the record - but
+                 * we might have updated the window since then due to
+                 * records we subsequently processed.
+                 */
+                replayok = dtls1_record_replay_check(s, bitmap);
+            }
+
+            if (!replayok || !dtls1_process_record(s, bitmap)) {
+                if (ossl_statem_in_error(s)) {
+                    /* dtls1_process_record called SSLfatal() */
+                    return 0;
+                }
+                /* dump this record */
+                rr->length = 0;
+                s->rrlmethod->reset_packet_length(s->rrl);
+                continue;
+            }
+
+            if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
+                    SSL3_RECORD_get_seq_num(&rl->rrec[0])) < 0) {
+                /* SSLfatal() already called */
+                return 0;
+            }
+        }
+    }
+
+    /*
+     * sync epoch numbers once all the unprocessed records have been
+     * processed
+     */
+    rl->processed_rcds.epoch = s->rlayer.d->r_epoch;
+    rl->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
+
+    return 1;
+}
+
+int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq, size_t off)
+{
+    SSL3_RECORD *rr;
+    OSSL_RECORD_LAYER *rl = s->rrl;
+
+    rr = &rl->rrec[0];
+    memset(rr, 0, sizeof(SSL3_RECORD));
+
+    rr->length = len;
+    rr->type = SSL3_RT_HANDSHAKE;
+    memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
+    rr->off = off;
+
+    s->rrlmethod->set0_packet(s->rrl, s->rrlmethod->get0_rbuf(s->rrl)->buf,
+                              DTLS1_RT_HEADER_LENGTH + len);
+    rr->data = s->rrlmethod->get0_packet(s->rrl) + DTLS1_RT_HEADER_LENGTH;
+
+    if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
+                                  SSL3_RECORD_get_seq_num(rr)) <= 0) {
+        /* SSLfatal() already called */
+        return 0;
+    }
+
+    return 1;
+}
+
+/*-
+ * Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3.rrec.type    - is the type of record
+ * ssl->s3.rrec.data    - data
+ * ssl->s3.rrec.length  - number of bytes
+ */
+/* used only by dtls1_read_bytes */
+static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
+{
+    int ssl_major, ssl_minor;
+    int rret;
+    size_t more, n;
+    SSL3_RECORD *rr;
+    unsigned char *p = NULL;
+    unsigned short version;
+    DTLS1_BITMAP *bitmap;
+    unsigned int is_next_epoch;
+    /* TODO(RECLAYER): Remove me */
+    SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+    rl->num_recs = 0;
+    rl->curr_rec = 0;
+    rl->num_released = 0;
+
+    rr = rl->rrec;
+
+ again:
+    /*
+     * The epoch may have changed.  If so, process all the pending records.
+     * This is a non-blocking operation.
+     */
+    if (!dtls_process_rlayer_buffered_records(s)) {
+        /* SSLfatal() already called */
+        return OSSL_RECORD_RETURN_FATAL;
+    }
+
+    /* if we're renegotiating, then there may be buffered records */
+    if (dtls_retrieve_rlayer_buffered_record(rl, &rl->processed_rcds)) {
+        rl->num_recs = 1;
+        return OSSL_RECORD_RETURN_SUCCESS;
+    }
+
+    /* get something from the wire */
+
+    /* check if we have the header */
+    if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+        (s->rrlmethod->get_packet_length(s->rrl) < DTLS1_RT_HEADER_LENGTH)) {
+        rret = s->rrlmethod->read_n(s->rrl, DTLS1_RT_HEADER_LENGTH,
+                                    SSL3_BUFFER_get_len(s->rrlmethod->get0_rbuf(s->rrl)),
+                                    0, 1, &n);
+        /* read timeout is handled by dtls1_read_bytes */
+        if (rret < OSSL_RECORD_RETURN_SUCCESS) {
+            /* SSLfatal() already called if appropriate */
+            return rret;         /* error or non-blocking */
+        }
+
+        /* this packet contained a partial record, dump it */
+        if (s->rrlmethod->get_packet_length(s->rrl) != DTLS1_RT_HEADER_LENGTH) {
+            s->rrlmethod->reset_packet_length(s->rrl);
+            goto again;
+        }
+
+        RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+        p = s->rrlmethod->get0_packet(s->rrl);
+
+        if (s->msg_callback)
+            s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
+                            ssl, s->msg_callback_arg);
+
+        /* Pull apart the header into the DTLS1_RECORD */
+        rr->type = *(p++);
+        ssl_major = *(p++);
+        ssl_minor = *(p++);
+        version = (ssl_major << 8) | ssl_minor;
+
+        /* sequence number is 64 bits, with top 2 bytes = epoch */
+        n2s(p, rr->epoch);
+
+        memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
+        p += 6;
+
+        n2s(p, rr->length);
+        rr->read = 0;
+
+        /*
+         * Lets check the version. We tolerate alerts that don't have the exact
+         * version number (e.g. because of protocol version errors)
+         */
+        if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
+            if (version != s->version) {
+                /* unexpected version, silently discard */
+                rr->length = 0;
+                rr->read = 1;
+                s->rrlmethod->reset_packet_length(s->rrl);
+                goto again;
+            }
+        }
+
+        if ((version & 0xff00) != (s->version & 0xff00)) {
+            /* wrong version, silently discard record */
+            rr->length = 0;
+            rr->read = 1;
+            s->rrlmethod->reset_packet_length(s->rrl);
+            goto again;
+        }
+
+        if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+            /* record too long, silently discard it */
+            rr->length = 0;
+            rr->read = 1;
+            s->rrlmethod->reset_packet_length(s->rrl);
+            goto again;
+        }
+
+        /* If received packet overflows own-client Max Fragment Length setting */
+        if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
+                && rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
+            /* record too long, silently discard it */
+            rr->length = 0;
+            rr->read = 1;
+            s->rrlmethod->reset_packet_length(s->rrl);
+            goto again;
+        }
+
+        /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+    }
+
+    /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
+
+    if (rr->length >
+        s->rrlmethod->get_packet_length(s->rrl) - DTLS1_RT_HEADER_LENGTH) {
+        /* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
+        more = rr->length;
+        rret = s->rrlmethod->read_n(s->rrl, more, more, 1, 1, &n);
+        /* this packet contained a partial record, dump it */
+        if (rret < OSSL_RECORD_RETURN_SUCCESS || n != more) {
+            if (ossl_statem_in_error(s)) {
+                /* read_n() called SSLfatal() */
+                return OSSL_RECORD_RETURN_FATAL;
+            }
+            rr->length = 0;
+            rr->read = 1;
+            s->rrlmethod->reset_packet_length(s->rrl);
+            goto again;
+        }
+
+        /*
+         * now n == rr->length, and s->rlayer.packet_length ==
+         * DTLS1_RT_HEADER_LENGTH + rr->length
+         */
+    }
+    /* set state for later operations */
+    RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+    /* match epochs.  NULL means the packet is dropped on the floor */
+    bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+    if (bitmap == NULL) {
+        rr->length = 0;
+        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+        goto again;             /* get another record */
+    }
+#ifndef OPENSSL_NO_SCTP
+    /* Only do replay check if no SCTP bio */
+    if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+#endif
+        /* Check whether this is a repeat, or aged record. */
+        if (!dtls1_record_replay_check(s, bitmap)) {
+            rr->length = 0;
+            rr->read = 1;
+            s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+            goto again;         /* get another record */
+        }
+#ifndef OPENSSL_NO_SCTP
+    }
+#endif
+
+    /* just read a 0 length packet */
+    if (rr->length == 0) {
+        rr->read = 1;
+        goto again;
+    }
+
+    /*
+     * If this record is from the next epoch (either HM or ALERT), and a
+     * handshake is currently in progress, buffer it since it cannot be
+     * processed at this time.
+     */
+    if (is_next_epoch) {
+        if ((SSL_in_init(ssl) || ossl_statem_get_in_handshake(s))) {
+            if (dtls_rlayer_buffer_record (s,
+                    &(rl->unprocessed_rcds),
+                    rr->seq_num) < 0) {
+                /* SSLfatal() already called */
+                return OSSL_RECORD_RETURN_FATAL;
+            }
+        }
+        rr->length = 0;
+        rr->read = 1;
+        s->rrlmethod->reset_packet_length(s->rrl);
+        goto again;
+    }
+
+    if (!dtls1_process_record(s, bitmap)) {
+        if (ossl_statem_in_error(s)) {
+            /* dtls1_process_record() called SSLfatal */
+            return OSSL_RECORD_RETURN_FATAL;
+        }
+        rr->length = 0;
+        rr->read = 1;
+        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+        goto again;             /* get another record */
+    }
+
+    rl->num_recs = 1;
+    return OSSL_RECORD_RETURN_SUCCESS;
+
+}
+
+static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
+{
+    rl->version = version;
+    return 1;
+}
+
+static struct record_functions_st dtls_funcs = {
+    NULL,
+    NULL,
+    dtls_get_more_records,
+    NULL,
+    NULL,
+    dtls_set_protocol_version,
+    NULL
+};
+
+static int dtls_free(OSSL_RECORD_LAYER *rl)
+{
+    pitem *item;
+    DTLS_RLAYER_RECORD_DATA *rdata;
+
+    if (rl->unprocessed_rcds.q == NULL) {
+        while ((item = pqueue_pop(rl->unprocessed_rcds.q)) != NULL) {
+            rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+            OPENSSL_free(rdata->rbuf.buf);
+            OPENSSL_free(item->data);
+            pitem_free(item);
+        }
+        pqueue_free(rl->unprocessed_rcds.q);
+    }
+
+    if (rl->processed_rcds.q == NULL) {
+        while ((item = pqueue_pop(rl->processed_rcds.q)) != NULL) {
+            rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+            OPENSSL_free(rdata->rbuf.buf);
+            OPENSSL_free(item->data);
+            pitem_free(item);
+        }
+        pqueue_free(rl->processed_rcds.q);
+    }
+
+    return tls_free(rl);
+}
+
+static int
+dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+                      int role, int direction, int level, unsigned char *key,
+                      size_t keylen, unsigned char *iv, size_t ivlen,
+                      unsigned char *mackey, size_t mackeylen,
+                      const EVP_CIPHER *ciph, size_t taglen,
+                      /* TODO(RECLAYER): This probably should not be an int */
+                      int mactype,
+                      const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+                      BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
+                      const OSSL_PARAM *settings, const OSSL_PARAM *options,
+                      const OSSL_DISPATCH *fns, void *cbarg,
+                      OSSL_RECORD_LAYER **retrl)
+{
+    int ret;
+
+
+    ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
+                                   key, keylen, iv, ivlen, mackey, mackeylen,
+                                   ciph, taglen, mactype, md, comp, prev,
+                                   transport, next, local, peer, settings,
+                                   options, fns, cbarg, retrl);
+
+    if (ret != OSSL_RECORD_RETURN_SUCCESS)
+        return ret;
+
+    (*retrl)->unprocessed_rcds.q = pqueue_new();
+    (*retrl)->processed_rcds.q = pqueue_new();
+    if ((*retrl)->unprocessed_rcds.q == NULL || (*retrl)->processed_rcds.q == NULL) {
+        dtls_free(*retrl);
+        *retrl = NULL;
+        RLAYERfatal(*retrl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        return OSSL_RECORD_RETURN_FATAL;
+    }
+
+    (*retrl)->isdtls = 1;
+    (*retrl)->funcs = &dtls_funcs;
+
+    return OSSL_RECORD_RETURN_SUCCESS;
+}
+
+const OSSL_RECORD_METHOD ossl_dtls_record_method = {
+    dtls_new_record_layer,
+    dtls_free,
+    tls_reset,
+    tls_unprocessed_read_pending,
+    tls_processed_read_pending,
+    tls_app_data_pending,
+    tls_write_pending,
+    tls_get_max_record_len,
+    tls_get_max_records,
+    tls_write_records,
+    tls_retry_write_records,
+    tls_read_record,
+    tls_release_record,
+    tls_get_alert_code,
+    tls_set1_bio,
+    tls_set_protocol_version,
+    NULL,
+    tls_set_first_handshake,
+    tls_set_max_pipelines,
+
+    /*
+     * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
+     * during the record layer refactoring. They need to be removed before the
+     * refactor is complete.
+     */
+    tls_default_read_n,
+    tls_get0_rbuf,
+    tls_get0_packet,
+    tls_set0_packet,
+    tls_get_packet_length,
+    tls_reset_packet_length
+};
index 465795e57817f2efbfb902c449869f3e4a34b8bb..460501c9d38dcb03e7ffa61b5f27000119edfb32 100644 (file)
@@ -473,6 +473,7 @@ static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
 static struct record_functions_st ossl_ktls_funcs = {
     ktls_set_crypto_state,
     ktls_read_n,
+    tls_get_more_records,
     ktls_cipher,
     NULL,
     tls_default_set_protocol_version,
index 1aa7f9b3eb582c073688433d4b012277e8622567..01590626a7508bff0263c376e941be68032e0a09 100644 (file)
@@ -34,6 +34,9 @@ struct record_functions_st
 
     int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
                   int clearold, size_t *readbytes);
+
+    int (*get_more_records)(OSSL_RECORD_LAYER *rl);
+
     /*
      * Returns:
      *    0: if the record is publicly invalid, or an internal error, or AEAD
@@ -169,6 +172,10 @@ struct ossl_record_layer_st
 
     size_t taglen;
 
+    /* DTLS eceived handshake records (processed and unprocessed) */
+    record_pqueue unprocessed_rcds;
+    record_pqueue processed_rcds;
+
     /* Callbacks */
     void *cbarg;
     OSSL_FUNC_rlayer_skip_early_data_fn *skip_early_data;
@@ -181,6 +188,14 @@ struct ossl_record_layer_st
     struct record_functions_st *funcs;
 };
 
+typedef struct dtls_rlayer_record_data_st {
+    unsigned char *packet;
+    size_t packet_length;
+    SSL3_BUFFER rbuf;
+    SSL3_RECORD rrec;
+} DTLS_RLAYER_RECORD_DATA;
+
+
 extern struct record_functions_st ssl_3_0_funcs;
 extern struct record_functions_st tls_1_funcs;
 extern struct record_functions_st tls_1_3_funcs;
@@ -216,6 +231,7 @@ __owur int ssl3_cbc_digest_record(const EVP_MD *md,
 
 int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
                        int clearold, size_t *readbytes);
+int tls_get_more_records(OSSL_RECORD_LAYER *rl);
 
 int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
 int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *re);
index 6d8fa14c16f886e3776ac913343bf38f46ffd3ee..c8062679a2bbfe84638ac117fa51546bc0cdf53a 100644 (file)
@@ -299,6 +299,7 @@ static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
 struct record_functions_st ssl_3_0_funcs = {
     ssl3_set_crypto_state,
     tls_default_read_n,
+    tls_get_more_records,
     ssl3_cipher,
     ssl3_mac,
     tls_default_set_protocol_version,
index 799df982378290bf680637a09a7500e939d0599f..0ef499ce410d095115833894517f906a30ba4274 100644 (file)
@@ -241,6 +241,7 @@ static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
 struct record_functions_st tls_1_3_funcs = {
     tls13_set_crypto_state,
     tls_default_read_n,
+    tls_get_more_records,
     tls13_cipher,
     NULL,
     tls_default_set_protocol_version,
index bb15e4b1ddab2b6f64a3cfaba0b60c3282e4ca66..8268d004fc149dd6e627a4d0ee4c392e78969ea0 100644 (file)
@@ -545,6 +545,7 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
 struct record_functions_st tls_1_funcs = {
     tls1_set_crypto_state,
     tls_default_read_n,
+    tls_get_more_records,
     tls1_cipher,
     tls1_mac,
     tls_default_set_protocol_version,
index 0f5aa4951cc42bea11b2ecebea3b3cb73787390d..c3198b23b0446b1bb1e55fcd87521cb10b61c160 100644 (file)
@@ -425,7 +425,7 @@ static int rlayer_early_data_count_ok(OSSL_RECORD_LAYER *rl, size_t length,
  * SSL3_RT_APPLICATION_DATA. The number of records returned will always be <=
  * |max_pipelines|
  */
-static int tls_get_more_records(OSSL_RECORD_LAYER *rl)
+int tls_get_more_records(OSSL_RECORD_LAYER *rl)
 {
     int enc_err, rret;
     int i;
@@ -975,7 +975,7 @@ int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,  int *rversion,
             return OSSL_RECORD_RETURN_FATAL;
         }
 
-        ret = tls_get_more_records(rl);
+        ret = rl->funcs->get_more_records(rl);
 
         if (ret != OSSL_RECORD_RETURN_SUCCESS)
             return ret;
@@ -990,8 +990,12 @@ int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,  int *rversion,
     *rechandle = rec;
     *rversion = rec->rec_version;
     *type = rec->type;
-    *data = rec->data;
+    *data = rec->data + rec->off;
     *datalen = rec->length;
+    if (rl->isdtls) {
+        *epoch = (uint16_t)rec->epoch;
+        memcpy(seq_num, rec->seq_num, sizeof(rec->seq_num));
+    }
 
     return OSSL_RECORD_RETURN_SUCCESS;
 }
@@ -1209,53 +1213,6 @@ tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
     return ret;
 }
 
-/* TODO(RECLAYER): Temporary funcs */
-static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
-{
-    rl->version = version;
-    return 1;
-}
-static struct record_functions_st dtls_funcs = {
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    dtls_set_protocol_version,
-    NULL
-};
-
-static int
-dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
-                      int role, int direction, int level, unsigned char *key,
-                      size_t keylen, unsigned char *iv, size_t ivlen,
-                      unsigned char *mackey, size_t mackeylen,
-                      const EVP_CIPHER *ciph, size_t taglen,
-                      /* TODO(RECLAYER): This probably should not be an int */
-                      int mactype,
-                      const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
-                      BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
-                      const OSSL_PARAM *settings, const OSSL_PARAM *options,
-                      const OSSL_DISPATCH *fns, void *cbarg,
-                      OSSL_RECORD_LAYER **retrl)
-{
-    int ret;
-
-
-    ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
-                                   key, keylen, iv, ivlen, mackey, mackeylen,
-                                   ciph, taglen, mactype, md, comp, prev,
-                                   transport, next, local, peer, settings,
-                                   options, fns, cbarg, retrl);
-
-    if (ret != OSSL_RECORD_RETURN_SUCCESS)
-        return ret;
-
-    (*retrl)->isdtls = 1;
-    (*retrl)->funcs = &dtls_funcs;
-
-    return OSSL_RECORD_RETURN_SUCCESS;
-}
-
 static void tls_int_free(OSSL_RECORD_LAYER *rl)
 {
     /* TODO(RECLAYER): Cleanse sensitive fields */
@@ -1445,37 +1402,3 @@ const OSSL_RECORD_METHOD ossl_tls_record_method = {
     tls_get_packet_length,
     tls_reset_packet_length
 };
-
-const OSSL_RECORD_METHOD ossl_dtls_record_method = {
-    dtls_new_record_layer,
-    tls_free,
-    tls_reset,
-    tls_unprocessed_read_pending,
-    tls_processed_read_pending,
-    tls_app_data_pending,
-    tls_write_pending,
-    tls_get_max_record_len,
-    tls_get_max_records,
-    tls_write_records,
-    tls_retry_write_records,
-    tls_read_record,
-    tls_release_record,
-    tls_get_alert_code,
-    tls_set1_bio,
-    tls_set_protocol_version,
-    NULL,
-    tls_set_first_handshake,
-    tls_set_max_pipelines,
-
-    /*
-     * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
-     * during the record layer refactoring. They need to be removed before the
-     * refactor is complete.
-     */
-    tls_default_read_n,
-    tls_get0_rbuf,
-    tls_get0_packet,
-    tls_set0_packet,
-    tls_get_packet_length,
-    tls_reset_packet_length
-};
index c0df9759e85389147b24f91163a2fcbca691c3a6..1953b7fed056760d867c90cea101ac25a404a7e5 100644 (file)
@@ -144,6 +144,7 @@ static int tls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
 struct record_functions_st tls_any_funcs = {
     tls_any_set_crypto_state,
     tls_default_read_n,
+    tls_get_more_records,
     tls_any_cipher,
     NULL,
     tls_any_set_protocol_version,
index dd78921948fcb2e97eb369ca727ed536030347e5..9e41d382974abd393f55d80ef8722e347809defc 100644 (file)
@@ -27,15 +27,9 @@ int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
 
     rl->d = d;
 
-    d->unprocessed_rcds.q = pqueue_new();
-    d->processed_rcds.q = pqueue_new();
     d->buffered_app_data.q = pqueue_new();
 
-    if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL
-        || d->buffered_app_data.q == NULL) {
-        pqueue_free(d->unprocessed_rcds.q);
-        pqueue_free(d->processed_rcds.q);
-        pqueue_free(d->buffered_app_data.q);
+    if (d->buffered_app_data.q == NULL) {
         OPENSSL_free(d);
         rl->d = NULL;
         return 0;
@@ -50,8 +44,6 @@ void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
         return;
 
     DTLS_RECORD_LAYER_clear(rl);
-    pqueue_free(rl->d->unprocessed_rcds.q);
-    pqueue_free(rl->d->processed_rcds.q);
     pqueue_free(rl->d->buffered_app_data.q);
     OPENSSL_free(rl->d);
     rl->d = NULL;
@@ -61,44 +53,22 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
 {
     DTLS_RECORD_LAYER *d;
     pitem *item = NULL;
-    DTLS1_RECORD_DATA *rdata;
-    pqueue *unprocessed_rcds;
-    pqueue *processed_rcds;
+    TLS_RECORD *rec;
     pqueue *buffered_app_data;
 
     d = rl->d;
 
-    while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
-        OPENSSL_free(rdata->rbuf.buf);
-        OPENSSL_free(item->data);
-        pitem_free(item);
-    }
-
-    while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
-        if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
-            OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
-        OPENSSL_free(rdata->rbuf.buf);
-        OPENSSL_free(item->data);
-        pitem_free(item);
-    }
-
     while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
+        rec = (TLS_RECORD *)item->data;
         if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
-            OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
-        OPENSSL_free(rdata->rbuf.buf);
+            OPENSSL_cleanse(rec->data, rec->length);
+        OPENSSL_free(rec->data);
         OPENSSL_free(item->data);
         pitem_free(item);
     }
 
-    unprocessed_rcds = d->unprocessed_rcds.q;
-    processed_rcds = d->processed_rcds.q;
     buffered_app_data = d->buffered_app_data.q;
     memset(d, 0, sizeof(*d));
-    d->unprocessed_rcds.q = unprocessed_rcds;
-    d->processed_rcds.q = processed_rcds;
     d->buffered_app_data.q = buffered_app_data;
 }
 
@@ -123,40 +93,22 @@ void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq)
     memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
 }
 
-/* copy buffered record into SSL structure */
-static int dtls1_copy_record(SSL_CONNECTION *s, pitem *item)
+int dtls_buffer_record(SSL_CONNECTION *s, TLS_RECORD *rec)
 {
-    DTLS1_RECORD_DATA *rdata;
-
-    rdata = (DTLS1_RECORD_DATA *)item->data;
-
-    SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
-
-    s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
-    memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
-    memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
-
-    /* Set proper sequence number for mac calculation */
-    memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
-
-    return 1;
-}
-
-int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
-                        unsigned char *priority)
-{
-    DTLS1_RECORD_DATA *rdata;
+    TLS_RECORD *rdata;
     pitem *item;
-#ifndef OPENSSL_NO_SCTP
-    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-#endif
+    record_pqueue *queue = &(s->rlayer.d->buffered_app_data);
 
     /* Limit the size of the queue to prevent DOS attacks */
     if (pqueue_size(queue->q) >= 100)
         return 0;
 
+    /* We don't buffer partially read records */
+    if (!ossl_assert(rec->off == 0))
+        return -1;
+
     rdata = OPENSSL_malloc(sizeof(*rdata));
-    item = pitem_new(priority, rdata);
+    item = pitem_new(rec->seq_num, rdata);
     if (rdata == NULL || item == NULL) {
         OPENSSL_free(rdata);
         pitem_free(item);
@@ -164,10 +116,24 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
         return -1;
     }
 
-    rdata->packet = s->rrlmethod->get0_packet(s->rrl);
-    rdata->packet_length = s->rrlmethod->get_packet_length(s->rrl);
-    memcpy(&(rdata->rbuf), s->rrlmethod->get0_rbuf(s->rrl), sizeof(SSL3_BUFFER));
-    memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
+    *rdata = *rec;
+    /*
+     * We will release the record from the record layer soon, so we take a copy
+     * now. Copying data isn't good - but this should be infrequent so we
+     * accept it here.
+     */
+    rdata->data = OPENSSL_memdup(rec->data, rec->length);
+    if (rdata->data == NULL) {
+        OPENSSL_free(rdata);
+        pitem_free(item);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+    /*
+     * We use a NULL rechandle to indicate that the data field has been
+     * allocated by us.
+     */
+    rdata->rechandle = NULL;
 
     item->data = rdata;
 
@@ -181,21 +147,9 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
     }
 #endif
 
-    s->rrlmethod->set0_packet(s->rrl, NULL, 0);
-    memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
-    memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));
-
-    if (!ssl3_setup_buffers(s)) {
-        /* SSLfatal() already called */
-        OPENSSL_free(rdata->rbuf.buf);
-        OPENSSL_free(rdata);
-        pitem_free(item);
-        return -1;
-    }
-
     if (pqueue_insert(queue->q, item) == NULL) {
         /* Must be a duplicate so ignore it */
-        OPENSSL_free(rdata->rbuf.buf);
+        OPENSSL_free(rdata->data);
         OPENSSL_free(rdata);
         pitem_free(item);
     }
@@ -203,114 +157,39 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
     return 1;
 }
 
-int dtls1_retrieve_buffered_record(SSL_CONNECTION *s, record_pqueue *queue)
+/* Unbuffer a previously buffered TLS_RECORD structure if any */
+static void dtls_unbuffer_record(SSL_CONNECTION *s)
 {
+    TLS_RECORD *rdata;
     pitem *item;
 
-    item = pqueue_pop(queue->q);
-    if (item) {
-        dtls1_copy_record(s, item);
-
-        OPENSSL_free(item->data);
-        pitem_free(item);
-
-        return 1;
-    }
-
-    return 0;
-}
-
-/*
- * retrieve a buffered record that belongs to the new epoch, i.e., not
- * processed yet
- */
-#define dtls1_get_unprocessed_record(s) \
-                   dtls1_retrieve_buffered_record((s), \
-                   &((s)->rlayer.d->unprocessed_rcds))
-
-int dtls1_process_buffered_records(SSL_CONNECTION *s)
-{
-    pitem *item;
-    SSL3_BUFFER *rb;
-    SSL3_RECORD *rr;
-    DTLS1_BITMAP *bitmap;
-    unsigned int is_next_epoch;
-    int replayok = 1;
-
-    item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
-    if (item) {
-        /* Check if epoch is current. */
-        if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
-            return 1;         /* Nothing to do. */
+    /* If we already have records to handle then do nothing */
+    if (s->rlayer.curr_rec < s->rlayer.num_recs)
+        return;
 
-        rr = RECORD_LAYER_get_rrec(&s->rlayer);
+    item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
+    if (item != NULL) {
+        rdata = (TLS_RECORD *)item->data;
 
-        rb = s->rrlmethod->get0_rbuf(s->rrl);
+        s->rlayer.tlsrecs[0] = *rdata;
+        s->rlayer.num_recs = 1;
+        s->rlayer.curr_rec = 0;
 
-        if (SSL3_BUFFER_get_left(rb) > 0) {
-            /*
-             * We've still got data from the current packet to read. There could
-             * be a record from the new epoch in it - so don't overwrite it
-             * with the unprocessed records yet (we'll do it when we've
-             * finished reading the current packet).
-             */
-            return 1;
-        }
-
-        /* Process all the records. */
-        while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
-            dtls1_get_unprocessed_record(s);
-            bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
-            if (bitmap == NULL) {
-                /*
-                 * Should not happen. This will only ever be NULL when the
-                 * current record is from a different epoch. But that cannot
-                 * be the case because we already checked the epoch above
-                 */
-                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-                 return 0;
-            }
 #ifndef OPENSSL_NO_SCTP
-            /* Only do replay check if no SCTP bio */
-            if (!BIO_dgram_is_sctp(SSL_get_rbio(SSL_CONNECTION_GET_SSL(s))))
+        /* Restore bio_dgram_sctp_rcvinfo struct */
+        if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+            DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
+            BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
+                        sizeof(rdata->recordinfo), &rdata->recordinfo);
+        }
 #endif
-            {
-                /*
-                 * Check whether this is a repeat, or aged record. We did this
-                 * check once already when we first received the record - but
-                 * we might have updated the window since then due to
-                 * records we subsequently processed.
-                 */
-                replayok = dtls1_record_replay_check(s, bitmap);
-            }
 
-            if (!replayok || !dtls1_process_record(s, bitmap)) {
-                if (ossl_statem_in_error(s)) {
-                    /* dtls1_process_record called SSLfatal() */
-                    return 0;
-                }
-                /* dump this record */
-                rr->length = 0;
-                s->rrlmethod->reset_packet_length(s->rrl);
-                continue;
-            }
+        /* Set proper sequence number for mac calculation */
+        memcpy(&(s->rlayer.read_sequence[2]), &(rdata->seq_num[2]), 6);
 
-            if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
-                    SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) {
-                /* SSLfatal() already called */
-                return 0;
-            }
-        }
+        OPENSSL_free(item->data);
+        pitem_free(item);
     }
-
-    /*
-     * sync epoch numbers once all the unprocessed records have been
-     * processed
-     */
-    s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
-    s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
-
-    return 1;
 }
 
 /*-
@@ -345,9 +224,9 @@ int dtls1_process_buffered_records(SSL_CONNECTION *s)
 int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                      size_t len, int peek, size_t *readbytes)
 {
-    int i, j, iret;
+    int i, j, ret;
     size_t n;
-    SSL3_RECORD *rr;
+    TLS_RECORD *rr;
     void (*cb) (const SSL *ssl, int type2, int val) = NULL;
     SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
 
@@ -382,37 +261,12 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
  start:
     sc->rwstate = SSL_NOTHING;
 
-    /*-
-     * s->s3.rrec.type     - is the type of record
-     * s->s3.rrec.data,    - data
-     * s->s3.rrec.off,     - offset into 'data' for next read
-     * s->s3.rrec.length,  - number of bytes.
-     */
-    rr = sc->rlayer.rrec;
-
     /*
      * We are not handshaking and have no data yet, so process data buffered
      * during the last handshake in advance, if any.
      */
-    if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
-        pitem *item;
-        item = pqueue_pop(sc->rlayer.d->buffered_app_data.q);
-        if (item) {
-#ifndef OPENSSL_NO_SCTP
-            /* Restore bio_dgram_sctp_rcvinfo struct */
-            if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
-                DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
-                BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
-                         sizeof(rdata->recordinfo), &rdata->recordinfo);
-            }
-#endif
-
-            dtls1_copy_record(sc, item);
-
-            OPENSSL_free(item->data);
-            pitem_free(item);
-        }
-    }
+    if (SSL_is_init_finished(s))
+        dtls_unbuffer_record(sc);
 
     /* Check for timeout */
     if (dtls1_handle_timeout(sc) > 0) {
@@ -423,49 +277,57 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
     }
 
     /* get new packet if necessary */
-    if ((SSL3_RECORD_get_length(rr) == 0)
-        || (sc->rlayer.rstate == SSL_ST_READ_BODY)) {
-        RECORD_LAYER_set_numrpipes(&sc->rlayer, 0);
-        iret = dtls1_get_record(sc);
-        if (iret <= 0) {
-            iret = dtls1_read_failed(sc, iret);
-            /*
-             * Anything other than a timeout is an error. SSLfatal() already
-             * called if appropriate.
-             */
-            if (iret <= 0)
-                return iret;
-            else
-                goto start;
-        }
-        RECORD_LAYER_set_numrpipes(&sc->rlayer, 1);
+    if (sc->rlayer.curr_rec >= sc->rlayer.num_recs) {
+        sc->rlayer.curr_rec = sc->rlayer.num_recs = 0;
+        do {
+            rr = &sc->rlayer.tlsrecs[sc->rlayer.num_recs];
+
+            /* TODO(RECLAYER): Check HANDLE_RLAYER_RETURN for DTLS */
+            ret = HANDLE_RLAYER_RETURN(sc,
+                    sc->rrlmethod->read_record(sc->rrl, &rr->rechandle,
+                                              &rr->version, &rr->type,
+                                              &rr->data, &rr->length,
+                                              &rr->epoch, rr->seq_num));
+            if (ret <= 0) {
+                ret = dtls1_read_failed(sc, ret);
+                /*
+                * Anything other than a timeout is an error. SSLfatal() already
+                * called if appropriate.
+                */
+                if (ret <= 0)
+                    return ret;
+                else
+                    goto start;
+            }
+            rr->off = 0;
+            sc->rlayer.num_recs++;
+        } while (sc->rrlmethod->processed_read_pending(sc->rrl)
+                 && sc->rlayer.num_recs < SSL_MAX_PIPELINES);
     }
+    rr = &sc->rlayer.tlsrecs[sc->rlayer.curr_rec];
 
     /*
      * Reset the count of consecutive warning alerts if we've got a non-empty
      * record that isn't an alert.
      */
-    if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
-            && SSL3_RECORD_get_length(rr) != 0)
+    if (rr->type != SSL3_RT_ALERT && rr->length != 0)
         sc->rlayer.alert_count = 0;
 
     /* we now have a packet which can be read and processed */
 
     if (sc->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
                                   * reset by ssl3_get_finished */
-        && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
+        && (rr->type != SSL3_RT_HANDSHAKE)) {
         /*
          * We now have application data between CCS and Finished. Most likely
          * the packets were reordered on their way, so buffer the application
          * data for later processing rather than dropping the connection.
          */
-        if (dtls1_buffer_record(sc, &(sc->rlayer.d->buffered_app_data),
-                                SSL3_RECORD_get_seq_num(rr)) < 0) {
+        if (dtls_buffer_record(sc, rr) < 0) {
             /* SSLfatal() already called */
             return -1;
         }
-        SSL3_RECORD_set_length(rr, 0);
-        SSL3_RECORD_set_read(rr);
+        ssl_release_record(sc, rr);
         goto start;
     }
 
@@ -474,14 +336,13 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
      * 'peek' mode)
      */
     if (sc->shutdown & SSL_RECEIVED_SHUTDOWN) {
-        SSL3_RECORD_set_length(rr, 0);
-        SSL3_RECORD_set_read(rr);
+        ssl_release_record(sc, rr);
         sc->rwstate = SSL_NOTHING;
         return 0;
     }
 
-    if (type == SSL3_RECORD_get_type(rr)
-        || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+    if (type == rr->type
+        || (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC
             && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
         /*
          * SSL3_RT_APPLICATION_DATA or
@@ -500,37 +361,37 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
         }
 
         if (recvd_type != NULL)
-            *recvd_type = SSL3_RECORD_get_type(rr);
+            *recvd_type = rr->type;
 
         if (len == 0) {
             /*
-             * Mark a zero length record as read. This ensures multiple calls to
+             * Release a zero length record. This ensures multiple calls to
              * SSL_read() with a zero length buffer will eventually cause
              * SSL_pending() to report data as being available.
              */
-            if (SSL3_RECORD_get_length(rr) == 0)
-                SSL3_RECORD_set_read(rr);
+            if (rr->length == 0)
+                ssl_release_record(sc, rr);
             return 0;
         }
 
-        if (len > SSL3_RECORD_get_length(rr))
-            n = SSL3_RECORD_get_length(rr);
+        if (len > rr->length)
+            n = rr->length;
         else
             n = len;
 
-        memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
+        memcpy(buf, &(rr->data[rr->off]), n);
         if (peek) {
-            if (SSL3_RECORD_get_length(rr) == 0)
-                SSL3_RECORD_set_read(rr);
+            if (rr->length == 0)
+                ssl_release_record(sc, rr);
         } else {
             if (sc->options & SSL_OP_CLEANSE_PLAINTEXT)
-                OPENSSL_cleanse(&(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
-            SSL3_RECORD_sub_length(rr, n);
-            SSL3_RECORD_add_off(rr, n);
-            if (SSL3_RECORD_get_length(rr) == 0) {
+                OPENSSL_cleanse(&(rr->data[rr->off]), n);
+            rr->length -= n;
+            rr->off += n;
+            if (rr->length == 0) {
+                /* TODO(RECLAYER): Do something with this? */
                 sc->rlayer.rstate = SSL_ST_READ_HEADER;
-                SSL3_RECORD_set_off(rr, 0);
-                SSL3_RECORD_set_read(rr);
+                ssl_release_record(sc, rr);
             }
         }
 #ifndef OPENSSL_NO_SCTP
@@ -555,13 +416,12 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
      * then it was unexpected (Hello Request or Client Hello).
      */
 
-    if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+    if (rr->type == SSL3_RT_ALERT) {
         unsigned int alert_level, alert_descr;
-        unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
-                                     + SSL3_RECORD_get_off(rr);
+        unsigned char *alert_bytes = rr->data + rr->off;
         PACKET alert;
 
-        if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
+        if (!PACKET_buf_init(&alert, alert_bytes, rr->length)
                 || !PACKET_get_1(&alert, &alert_level)
                 || !PACKET_get_1(&alert, &alert_descr)
                 || PACKET_remaining(&alert) != 0) {
@@ -585,7 +445,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
 
         if (alert_level == SSL3_AL_WARNING) {
             sc->s3.warn_alert = alert_descr;
-            SSL3_RECORD_set_read(rr);
+            ssl_release_record(sc, rr);
 
             sc->rlayer.alert_count++;
             if (sc->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
@@ -620,7 +480,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                           SSL_AD_REASON_OFFSET + alert_descr,
                           "SSL alert number %d", alert_descr);
             sc->shutdown |= SSL_RECEIVED_SHUTDOWN;
-            SSL3_RECORD_set_read(rr);
+            ssl_release_record(sc, rr);
             SSL_CTX_remove_session(sc->session_ctx, sc->session);
             return 0;
         } else {
@@ -634,36 +494,32 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
     if (sc->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
                                             * shutdown */
         sc->rwstate = SSL_NOTHING;
-        SSL3_RECORD_set_length(rr, 0);
-        SSL3_RECORD_set_read(rr);
+        ssl_release_record(sc, rr);
         return 0;
     }
 
-    if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
+    if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
         /*
          * We can't process a CCS now, because previous handshake messages
          * are still missing, so just drop it.
          */
-        SSL3_RECORD_set_length(rr, 0);
-        SSL3_RECORD_set_read(rr);
+        ssl_release_record(sc, rr);
         goto start;
     }
 
     /*
      * Unexpected handshake message (Client Hello, or protocol violation)
      */
-    if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
-            !ossl_statem_get_in_handshake(sc)) {
+    if (rr->type == SSL3_RT_HANDSHAKE && !ossl_statem_get_in_handshake(sc)) {
         struct hm_header_st msg_hdr;
 
         /*
          * This may just be a stale retransmit. Also sanity check that we have
          * at least enough record bytes for a message header
          */
-        if (SSL3_RECORD_get_epoch(rr) != sc->rlayer.d->r_epoch
-                || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) {
-            SSL3_RECORD_set_length(rr, 0);
-            SSL3_RECORD_set_read(rr);
+        if (rr->epoch != sc->rlayer.d->r_epoch
+                || rr->length < DTLS1_HM_HEADER_LENGTH) {
+            ssl_release_record(sc, rr);
             goto start;
         }
 
@@ -684,8 +540,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                 if (ossl_statem_in_error(sc))
                     return -1;
             }
-            SSL3_RECORD_set_length(rr, 0);
-            SSL3_RECORD_set_read(rr);
+            ssl_release_record(sc, rr);
             if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
                 if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
                     /* no read-ahead left? */
@@ -742,7 +597,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
         goto start;
     }
 
-    switch (SSL3_RECORD_get_type(rr)) {
+    switch (rr->type) {
     default:
         SSLfatal(sc, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
         return -1;
@@ -1007,31 +862,6 @@ int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
     return ssl3_write_pending(sc, type, buf, len, written);
 }
 
-DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
-                               unsigned int *is_next_epoch)
-{
-
-    *is_next_epoch = 0;
-
-    /* In current epoch, accept HM, CCS, DATA, & ALERT */
-    if (rr->epoch == s->rlayer.d->r_epoch)
-        return &s->rlayer.d->bitmap;
-
-    /*
-     * Only HM and ALERT messages can be from the next epoch and only if we
-     * have already processed all of the unprocessed records from the last
-     * epoch
-     */
-    else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
-             s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
-             (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
-        *is_next_epoch = 1;
-        return &s->rlayer.d->next_bitmap;
-    }
-
-    return NULL;
-}
-
 void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw)
 {
     unsigned char *seq;
index 70e198be8b169fe9d95e96175f873f59c02f1df8..b51615c396b4059169f54d2e2fbbfb2582b8670b 100644 (file)
@@ -78,34 +78,12 @@ void RECORD_LAYER_release(RECORD_LAYER *rl)
 /* Checks if we have unprocessed read ahead data pending */
 int RECORD_LAYER_read_pending(const RECORD_LAYER *rl)
 {
-    /*
-     * TODO(RECLAYER): Temporarily do it the old way until DTLS is converted to
-     * the new record layer code
-     */
-    if (SSL_CONNECTION_IS_DTLS(rl->s))
-        return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
-
     return rl->s->rrlmethod->unprocessed_read_pending(rl->s->rrl);
 }
 
 /* Checks if we have decrypted unread record data pending */
 int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
 {
-    /*
-     * TODO(RECLAYER): Temporarily do it the old way until DTLS is converted to
-     * the new record layer code
-     */
-    if (SSL_CONNECTION_IS_DTLS(rl->s)) {
-        const SSL3_RECORD *rr = rl->rrec;
-
-        size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl);
-
-        while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]))
-            curr_rec++;
-
-        return curr_rec < num_recs;
-    }
-
     return (rl->curr_rec < rl->num_recs)
            || rl->s->rrlmethod->processed_read_pending(rl->s->rrl);
 }
@@ -137,32 +115,21 @@ size_t ssl3_pending(const SSL *s)
     if (sc->rlayer.rstate == SSL_ST_READ_BODY)
         return 0;
 
-    /*
-     * TODO(RECLAYER): We need to do it the old way temporary for DTLS until
-     * that is converted to use the new record layer code
-     */
     if (SSL_CONNECTION_IS_DTLS(sc)) {
-        DTLS1_RECORD_DATA *rdata;
+        TLS_RECORD *rdata;
         pitem *item, *iter;
 
         iter = pqueue_iterator(sc->rlayer.d->buffered_app_data.q);
         while ((item = pqueue_next(&iter)) != NULL) {
             rdata = item->data;
-            num += rdata->rrec.length;
+            num += rdata->length;
         }
+    }
 
-        for (i = 0; i < RECORD_LAYER_get_numrpipes(&sc->rlayer); i++) {
-            if (SSL3_RECORD_get_type(&sc->rlayer.rrec[i])
-                != SSL3_RT_APPLICATION_DATA)
-                return 0;
-            num += SSL3_RECORD_get_length(&sc->rlayer.rrec[i]);
-        }
-    } else {
-        for (i = 0; i <sc->rlayer.num_recs; i++) {
-            if (sc->rlayer.tlsrecs[i].type != SSL3_RT_APPLICATION_DATA)
-                return 0;
-            num += sc->rlayer.tlsrecs[i].length;
-        }
+    for (i = 0; i < sc->rlayer.num_recs; i++) {
+        if (sc->rlayer.tlsrecs[i].type != SSL3_RT_APPLICATION_DATA)
+            return num;
+        num += sc->rlayer.tlsrecs[i].length;
     }
 
     return num;
@@ -1170,6 +1137,18 @@ int ossl_tls_handle_rlayer_return(SSL_CONNECTION *s, int ret, char *file,
     return ret;
 }
 
+void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr)
+{
+    if (rr->rechandle != NULL) {
+        /* The record layer allocated the buffers for this record */
+        s->rrlmethod->release_record(s->rrl, rr->rechandle);
+    } else {
+        /* We allocated the buffers for this record (only happens with DTLS) */
+        OPENSSL_free(rr->data);
+    }
+    s->rlayer.curr_rec++;
+}
+
 /*-
  * Return up to 'len' payload bytes received in 'type' records.
  * 'type' is one of the following:
@@ -1360,10 +1339,9 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
              * SSL_read() with a zero length buffer will eventually cause
              * SSL_pending() to report data as being available.
              */
-            if (rr->length == 0) {
-                s->rrlmethod->release_record(s->rrl, rr->rechandle);
-                s->rlayer.curr_rec++;
-            }
+            if (rr->length == 0)
+                ssl_release_record(s, rr);
+
             return 0;
         }
 
@@ -1379,10 +1357,8 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
             buf += n;
             if (peek) {
                 /* Mark any zero length record as consumed CVE-2016-6305 */
-                if (rr->length == 0) {
-                    s->rrlmethod->release_record(s->rrl, rr->rechandle);
-                    s->rlayer.curr_rec++;
-                }
+                if (rr->length == 0)
+                    ssl_release_record(s, rr);
             } else {
                 if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
                     OPENSSL_cleanse(&(rr->data[rr->off]), n);
@@ -1393,8 +1369,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
                     #if 0
                     s->rlayer.rstate = SSL_ST_READ_HEADER;
                     #endif
-                    s->rrlmethod->release_record(s->rrl, rr->rechandle);
-                    s->rlayer.curr_rec++;
+                    ssl_release_record(s, rr);
                 }
             }
             if (rr->length == 0
@@ -1490,8 +1465,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
         if ((!is_tls13 && alert_level == SSL3_AL_WARNING)
                 || (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) {
             s->s3.warn_alert = alert_descr;
-            s->rrlmethod->release_record(s->rrl, rr->rechandle);
-            s->rlayer.curr_rec++;
+            ssl_release_record(s, rr);
 
             s->rlayer.alert_count++;
             if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
@@ -1518,8 +1492,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
                           SSL_AD_REASON_OFFSET + alert_descr,
                           "SSL alert number %d", alert_descr);
             s->shutdown |= SSL_RECEIVED_SHUTDOWN;
-            s->rrlmethod->release_record(s->rrl, rr->rechandle);
-            s->rlayer.curr_rec++;
+            ssl_release_record(s, rr);
             SSL_CTX_remove_session(s->session_ctx, s->session);
             return 0;
         } else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
@@ -1554,8 +1527,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
              * sent close_notify.
              */
             if (!SSL_CONNECTION_IS_TLS13(s)) {
-                s->rrlmethod->release_record(s->rrl, rr->rechandle);
-                s->rlayer.curr_rec++;
+                ssl_release_record(s, rr);
 
                 if ((s->mode & SSL_MODE_AUTO_RETRY) != 0)
                     goto start;
@@ -1574,8 +1546,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
              * above.
              * No alert sent because we already sent close_notify
              */
-            s->rrlmethod->release_record(s->rrl, rr->rechandle);
-            s->rlayer.curr_rec++;
+            ssl_release_record(s, rr);
             SSLfatal(s, SSL_AD_NO_ALERT,
                      SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
             return -1;
@@ -1602,10 +1573,8 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
         rr->off += n;
         rr->length -= n;
         *dest_len += n;
-        if (rr->length == 0) {
-            s->rrlmethod->release_record(s->rrl, rr->rechandle);
-            s->rlayer.curr_rec++;
-        }
+        if (rr->length == 0)
+            ssl_release_record(s, rr);
 
         if (*dest_len < dest_maxlen)
             goto start;     /* fragment was too small */
@@ -1709,8 +1678,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
                 /* SSLfatal() already called */
                 return -1;
             }
-            s->rrlmethod->release_record(s->rrl, rr->rechandle);
-            s->rlayer.curr_rec++;
+            ssl_release_record(s, rr);
             goto start;
         } else {
             SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
index 51d96f26069fa269c2abbc2f880982e765c63cf4..0b15e55fbc41c05f5ddecbf4324d03bf34fd30c6 100644 (file)
@@ -86,6 +86,13 @@ typedef struct tls_record_st {
     size_t length;
     /* Offset into the data buffer where to start reading */
     size_t off;
+    /* epoch number. DTLS only */
+    uint16_t epoch;
+    /* sequence number. DTLS only */
+    unsigned char seq_num[SEQ_NUM_SIZE];
+#ifndef OPENSSL_NO_SCTP
+    struct bio_dgram_sctp_rcvinfo recordinfo;
+#endif
 } TLS_RECORD;
 
 typedef struct dtls1_bitmap_st {
@@ -122,9 +129,6 @@ typedef struct dtls_record_layer_st {
     DTLS1_BITMAP bitmap;
     /* renegotiation starts a new set of sequence numbers */
     DTLS1_BITMAP next_bitmap;
-    /* Received handshake records (processed and unprocessed) */
-    record_pqueue unprocessed_rcds;
-    record_pqueue processed_rcds;
     /*
      * Buffered application records. Only for records between CCS and
      * Finished to prevent either protocol violation or unnecessary message
@@ -220,10 +224,6 @@ typedef struct ssl_mac_buf_st SSL_MAC_BUF;
 #define RECORD_LAYER_get_packet_length(rl)      ((rl)->packet_length)
 #define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
 #define DTLS_RECORD_LAYER_get_w_epoch(rl)       ((rl)->d->w_epoch)
-#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
-                                                ((rl)->d->processed_rcds)
-#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
-                                                ((rl)->d->unprocessed_rcds)
 #define RECORD_LAYER_get_rbuf(rl)               (&(rl)->rbuf)
 #define RECORD_LAYER_get_wbuf(rl)               ((rl)->wbuf)
 
@@ -276,7 +276,7 @@ int do_dtls1_write(SSL_CONNECTION *s, int type, const unsigned char *buf,
 void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw);
 int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
                               size_t off);
-
+void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr);
 
 # define HANDLE_RLAYER_RETURN(s, ret) \
     ossl_tls_handle_rlayer_return(s, ret, OPENSSL_FILE, OPENSSL_LINE)
index c2b0109d8dc426f9a5cd64fea9f3c318abd8a780..8b898dfd0b13114596e86ef58d749f0cbadfae81 100644 (file)
 #define RECORD_LAYER_clear_first_record(rl)     ((rl)->is_first_record = 0)
 #define DTLS_RECORD_LAYER_get_r_epoch(rl)       ((rl)->d->r_epoch)
 
-DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
-                               unsigned int *is_next_epoch);
-int dtls1_process_buffered_records(SSL_CONNECTION *s);
-int dtls1_retrieve_buffered_record(SSL_CONNECTION *s, record_pqueue *queue);
-int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *q,
-                        unsigned char *priority);
+int dtls_buffer_record(SSL_CONNECTION *s, TLS_RECORD *rec);
 void ssl3_record_sequence_update(unsigned char *seq);
 
-/* Functions provided by the DTLS1_BITMAP component */
-
-int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-
 /* Macros/functions provided by the SSL3_BUFFER component */
 
 #define SSL3_BUFFER_get_buf(b)              ((b)->buf)
@@ -120,8 +110,6 @@ __owur int tls1_cbc_remove_padding_and_mac(size_t *reclen,
                                            size_t block_size, size_t mac_size,
                                            int aead,
                                            OSSL_LIB_CTX *libctx);
-int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-__owur int dtls1_get_record(SSL_CONNECTION *s);
 uint32_t ossl_get_max_early_data(SSL_CONNECTION *s);
 int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length, size_t overhead,
                              int send);
index 42811e39c71e09a458852960fd600469495dbd53..fac317a4ac64d14ea31c750ff3d7c8e58979c7e4 100644 (file)
@@ -833,430 +833,3 @@ int tls1_mac_old(SSL_CONNECTION *sc, SSL3_RECORD *rec, unsigned char *md,
     EVP_MD_CTX_free(hmac);
     return ret;
 }
-
-int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
-{
-    int i;
-    int enc_err;
-    SSL_SESSION *sess;
-    SSL3_RECORD *rr;
-    int imac_size;
-    size_t mac_size = 0;
-    unsigned char md[EVP_MAX_MD_SIZE];
-    size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
-    SSL_MAC_BUF macbuf = { NULL, 0 };
-    int ret = 0;
-    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-
-    rr = RECORD_LAYER_get_rrec(&s->rlayer);
-    sess = s->session;
-
-    /*
-     * At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
-     * and we have that many bytes in s->rlayer.packet
-     */
-    rr->input = &(s->rrlmethod->get0_packet(s->rrl)[DTLS1_RT_HEADER_LENGTH]);
-
-    /*
-     * ok, we can now read from 's->rlayer.packet' data into 'rr'. rr->input
-     * points at rr->length bytes, which need to be copied into rr->data by
-     * either the decryption or by the decompression. When the data is 'copied'
-     * into the rr->data buffer, rr->input will be pointed at the new buffer
-     */
-
-    /*
-     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
-     * bytes of encrypted compressed stuff.
-     */
-
-    /* check is not needed I believe */
-    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
-        SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
-        return 0;
-    }
-
-    /* decrypt in place in 'rr->input' */
-    rr->data = rr->input;
-    rr->orig_len = rr->length;
-
-    if (s->read_hash != NULL) {
-        const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
-
-        if (tmpmd != NULL) {
-            imac_size = EVP_MD_get_size(tmpmd);
-            if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
-                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
-                    return 0;
-            }
-            mac_size = (size_t)imac_size;
-        }
-    }
-
-    if (SSL_READ_ETM(s) && s->read_hash) {
-        unsigned char *mac;
-
-        if (rr->orig_len < mac_size) {
-            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
-            return 0;
-        }
-        rr->length -= mac_size;
-        mac = rr->data + rr->length;
-        i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
-        if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
-            SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
-                     SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-            return 0;
-        }
-        /*
-         * We've handled the mac now - there is no MAC inside the encrypted
-         * record
-         */
-        mac_size = 0;
-    }
-
-    /*
-     * Set a mark around the packet decryption attempt.  This is DTLS, so
-     * bad packets are just ignored, and we don't want to leave stray
-     * errors in the queue from processing bogus junk that we ignored.
-     */
-    ERR_set_mark();
-    enc_err = ssl->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
-
-    /*-
-     * enc_err is:
-     *    0: if the record is publicly invalid, or an internal error, or AEAD
-     *       decryption failed, or ETM decryption failed.
-     *    1: Success or MTE decryption failed (MAC will be randomised)
-     */
-    if (enc_err == 0) {
-        ERR_pop_to_mark();
-        if (ossl_statem_in_error(s)) {
-            /* SSLfatal() got called */
-            goto end;
-        }
-        /* For DTLS we simply ignore bad packets. */
-        rr->length = 0;
-        s->rrlmethod->reset_packet_length(s->rrl);
-        goto end;
-    }
-    ERR_clear_last_mark();
-    OSSL_TRACE_BEGIN(TLS) {
-        BIO_printf(trc_out, "dec %zd\n", rr->length);
-        BIO_dump_indent(trc_out, rr->data, rr->length, 4);
-    } OSSL_TRACE_END(TLS);
-
-    /* r->length is now the compressed data plus mac */
-    if ((sess != NULL)
-            && !SSL_READ_ETM(s)
-            && (s->enc_read_ctx != NULL)
-            && (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
-        /* s->read_hash != NULL => mac_size != -1 */
-
-        i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
-        if (i == 0 || macbuf.mac == NULL
-            || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
-            enc_err = 0;
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
-            enc_err = 0;
-    }
-
-    if (enc_err == 0) {
-        /* decryption failed, silently discard message */
-        rr->length = 0;
-        s->rrlmethod->reset_packet_length(s->rrl);
-        goto end;
-    }
-
-    /* r->length is now just compressed */
-    if (s->expand != NULL) {
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
-            SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
-                     SSL_R_COMPRESSED_LENGTH_TOO_LONG);
-            goto end;
-        }
-        if (!ssl3_do_uncompress(s, rr)) {
-            SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
-            goto end;
-        }
-    }
-
-    /* use current Max Fragment Length setting if applicable */
-    if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
-        max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
-
-    /* send overflow if the plaintext is too long now it has passed MAC */
-    if (rr->length > max_plain_length) {
-        SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
-        goto end;
-    }
-
-    rr->off = 0;
-    /*-
-     * So at this point the following is true
-     * ssl->s3.rrec.type   is the type of record
-     * ssl->s3.rrec.length == number of bytes in record
-     * ssl->s3.rrec.off    == offset to first valid byte
-     * ssl->s3.rrec.data   == where to take bytes from, increment
-     *                        after use :-).
-     */
-
-    /* we have pulled in a full packet so zero things */
-    s->rrlmethod->reset_packet_length(s->rrl);
-
-    /* Mark receipt of record. */
-    dtls1_record_bitmap_update(s, bitmap);
-
-    ret = 1;
- end:
-    if (macbuf.alloced)
-        OPENSSL_free(macbuf.mac);
-    return ret;
-}
-
-/*
- * Retrieve a buffered record that belongs to the current epoch, i.e. processed
- */
-#define dtls1_get_processed_record(s) \
-                   dtls1_retrieve_buffered_record((s), \
-                   &(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
-
-/*-
- * Call this to get a new input record.
- * It will return <= 0 if more data is needed, normally due to an error
- * or non-blocking IO.
- * When it finishes, one packet has been decoded and can be found in
- * ssl->s3.rrec.type    - is the type of record
- * ssl->s3.rrec.data    - data
- * ssl->s3.rrec.length  - number of bytes
- */
-/* used only by dtls1_read_bytes */
-int dtls1_get_record(SSL_CONNECTION *s)
-{
-    int ssl_major, ssl_minor;
-    int rret;
-    size_t more, n;
-    SSL3_RECORD *rr;
-    unsigned char *p = NULL;
-    unsigned short version;
-    DTLS1_BITMAP *bitmap;
-    unsigned int is_next_epoch;
-    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-
-    rr = RECORD_LAYER_get_rrec(&s->rlayer);
-
- again:
-    /*
-     * The epoch may have changed.  If so, process all the pending records.
-     * This is a non-blocking operation.
-     */
-    if (!dtls1_process_buffered_records(s)) {
-        /* SSLfatal() already called */
-        return -1;
-    }
-
-    /* if we're renegotiating, then there may be buffered records */
-    if (dtls1_get_processed_record(s))
-        return 1;
-
-    /* get something from the wire */
-
-    /* check if we have the header */
-    if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
-        (s->rrlmethod->get_packet_length(s->rrl) < DTLS1_RT_HEADER_LENGTH)) {
-        rret = HANDLE_RLAYER_RETURN(s,
-            s->rrlmethod->read_n(s->rrl, DTLS1_RT_HEADER_LENGTH,
-                                 SSL3_BUFFER_get_len(s->rrlmethod->get0_rbuf(s->rrl)), 0, 1, &n));
-        /* read timeout is handled by dtls1_read_bytes */
-        if (rret <= 0) {
-            /* SSLfatal() already called if appropriate */
-            return rret;         /* error or non-blocking */
-        }
-
-        /* this packet contained a partial record, dump it */
-        if (s->rrlmethod->get_packet_length(s->rrl) != DTLS1_RT_HEADER_LENGTH) {
-            s->rrlmethod->reset_packet_length(s->rrl);
-            goto again;
-        }
-
-        RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
-
-        p = s->rrlmethod->get0_packet(s->rrl);
-
-        if (s->msg_callback)
-            s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
-                            ssl, s->msg_callback_arg);
-
-        /* Pull apart the header into the DTLS1_RECORD */
-        rr->type = *(p++);
-        ssl_major = *(p++);
-        ssl_minor = *(p++);
-        version = (ssl_major << 8) | ssl_minor;
-
-        /* sequence number is 64 bits, with top 2 bytes = epoch */
-        n2s(p, rr->epoch);
-
-        memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
-        p += 6;
-
-        n2s(p, rr->length);
-        rr->read = 0;
-
-        /*
-         * Lets check the version. We tolerate alerts that don't have the exact
-         * version number (e.g. because of protocol version errors)
-         */
-        if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
-            if (version != s->version) {
-                /* unexpected version, silently discard */
-                rr->length = 0;
-                rr->read = 1;
-                s->rrlmethod->reset_packet_length(s->rrl);
-                goto again;
-            }
-        }
-
-        if ((version & 0xff00) != (s->version & 0xff00)) {
-            /* wrong version, silently discard record */
-            rr->length = 0;
-            rr->read = 1;
-            s->rrlmethod->reset_packet_length(s->rrl);
-            goto again;
-        }
-
-        if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
-            /* record too long, silently discard it */
-            rr->length = 0;
-            rr->read = 1;
-            s->rrlmethod->reset_packet_length(s->rrl);
-            goto again;
-        }
-
-        /* If received packet overflows own-client Max Fragment Length setting */
-        if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
-                && rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
-            /* record too long, silently discard it */
-            rr->length = 0;
-            rr->read = 1;
-            s->rrlmethod->reset_packet_length(s->rrl);
-            goto again;
-        }
-
-        /* now s->rlayer.rstate == SSL_ST_READ_BODY */
-    }
-
-    /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
-
-    if (rr->length >
-        s->rrlmethod->get_packet_length(s->rrl) - DTLS1_RT_HEADER_LENGTH) {
-        /* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
-        more = rr->length;
-        rret = HANDLE_RLAYER_RETURN(s,
-            s->rrlmethod->read_n(s->rrl, more, more, 1, 1, &n));
-        /* this packet contained a partial record, dump it */
-        if (rret <= 0 || n != more) {
-            if (ossl_statem_in_error(s)) {
-                /* read_n() called SSLfatal() */
-                return -1;
-            }
-            rr->length = 0;
-            rr->read = 1;
-            s->rrlmethod->reset_packet_length(s->rrl);
-            goto again;
-        }
-
-        /*
-         * now n == rr->length, and s->rlayer.packet_length ==
-         * DTLS1_RT_HEADER_LENGTH + rr->length
-         */
-    }
-    /* set state for later operations */
-    RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
-
-    /* match epochs.  NULL means the packet is dropped on the floor */
-    bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
-    if (bitmap == NULL) {
-        rr->length = 0;
-        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
-        goto again;             /* get another record */
-    }
-#ifndef OPENSSL_NO_SCTP
-    /* Only do replay check if no SCTP bio */
-    if (!BIO_dgram_is_sctp(SSL_get_rbio(ssl))) {
-#endif
-        /* Check whether this is a repeat, or aged record. */
-        if (!dtls1_record_replay_check(s, bitmap)) {
-            rr->length = 0;
-            rr->read = 1;
-            s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
-            goto again;         /* get another record */
-        }
-#ifndef OPENSSL_NO_SCTP
-    }
-#endif
-
-    /* just read a 0 length packet */
-    if (rr->length == 0) {
-        rr->read = 1;
-        goto again;
-    }
-
-    /*
-     * If this record is from the next epoch (either HM or ALERT), and a
-     * handshake is currently in progress, buffer it since it cannot be
-     * processed at this time.
-     */
-    if (is_next_epoch) {
-        if ((SSL_in_init(ssl) || ossl_statem_get_in_handshake(s))) {
-            if (dtls1_buffer_record (s,
-                    &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
-                    rr->seq_num) < 0) {
-                /* SSLfatal() already called */
-                return -1;
-            }
-        }
-        rr->length = 0;
-        rr->read = 1;
-        s->rrlmethod->reset_packet_length(s->rrl);
-        goto again;
-    }
-
-    if (!dtls1_process_record(s, bitmap)) {
-        if (ossl_statem_in_error(s)) {
-            /* dtls1_process_record() called SSLfatal */
-            return -1;
-        }
-        rr->length = 0;
-        rr->read = 1;
-        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
-        goto again;             /* get another record */
-    }
-
-    return 1;
-
-}
-
-int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
-                              size_t off)
-{
-    SSL3_RECORD *rr;
-
-    rr = RECORD_LAYER_get_rrec(&s->rlayer);
-    memset(rr, 0, sizeof(SSL3_RECORD));
-
-    rr->length = len;
-    rr->type = SSL3_RT_HANDSHAKE;
-    memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
-    rr->off = off;
-
-    s->rrlmethod->set0_packet(s->rrl, s->rrlmethod->get0_rbuf(s->rrl)->buf,
-                              DTLS1_RT_HEADER_LENGTH + len);
-    rr->data = s->rrlmethod->get0_packet(s->rrl) + DTLS1_RT_HEADER_LENGTH;
-
-    if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
-                            SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) {
-        /* SSLfatal() already called */
-        return 0;
-    }
-
-    return 1;
-}
index f20b10606f1521b71c88e9b2a42fb349c11fbd1d..9e4d689c23c32cc14b4a4471ccf3c12a7b25c1ea 100644 (file)
@@ -1791,13 +1791,13 @@ int SSL_has_pending(const SSL *s)
 
     /* Check buffered app data if any first */
     if (SSL_CONNECTION_IS_DTLS(sc)) {
-        DTLS1_RECORD_DATA *rdata;
+        TLS_RECORD *rdata;
         pitem *item, *iter;
 
         iter = pqueue_iterator(sc->rlayer.d->buffered_app_data.q);
         while ((item = pqueue_next(&iter)) != NULL) {
             rdata = item->data;
-            if (rdata->rrec.length > 0)
+            if (rdata->length > 0)
                 return 1;
         }
     }
index 6068c833c657495a12269ab48c56ce8c07578f99..e1b6b5790e0744e4e1075715a57055eb7ece7a0e 100644 (file)
@@ -825,7 +825,7 @@ static int dtls_get_reassembled_message(SSL_CONNECTION *s, int *errtype,
      * We must have at least frag_len bytes left in the record to be read.
      * Fragments must not span records.
      */
-    if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
+    if (frag_len > s->rlayer.tlsrecs[s->rlayer.curr_rec].length) {
         SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH);
         goto f_err;
     }
index f470d91a7be8eaed8a6f60f385773c08e80e7446..774728bbc1aafa401ecc75ba06447dbe9701f351 100644 (file)
@@ -1544,6 +1544,7 @@ static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
     int testresult = 0;
     void *zbuf;
     SSL_CONNECTION *serversc;
+    TLS_RECORD *rr;
 
     static unsigned char cbuf[16000];
     static unsigned char sbuf[16000];
@@ -1606,24 +1607,11 @@ static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
      */
     if (!TEST_ptr(serversc = SSL_CONNECTION_FROM_SSL_ONLY(serverssl)))
         goto end;
+    rr = serversc->rlayer.tlsrecs;
 
-    /*
-     * TODO(RECLAYER): This is temporary until DTLS is converted to use the new
-     * record layer code.
-     */
-    if (!SSL_is_dtls(serverssl)) {
-        TLS_RECORD *rr = serversc->rlayer.tlsrecs;
-
-        zbuf = &rr->data[rr->off];
-        if (!TEST_int_eq(rr->length, sizeof(cbuf)))
-            goto end;
-    } else {
-        SSL3_RECORD *rr = serversc->rlayer.rrec;
-
-        zbuf = &rr->data[rr->off];
-        if (!TEST_int_eq(rr->length, sizeof(cbuf)))
-            goto end;
-    }
+    zbuf = &rr->data[rr->off];
+    if (!TEST_int_eq(rr->length, sizeof(cbuf)))
+        goto end;
 
     /*
      * After SSL_peek() the plaintext must still be stored in the