]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - ssl/record/rec_layer_s3.c
threads_pthread.c: change inline to ossl_inline
[thirdparty/openssl.git] / ssl / record / rec_layer_s3.c
index c8951d45dbfdb2662266a8b1da2ca0e68b99af59..e61861d9fd16ed6d288244dc338d51e87fe6c10a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 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
 #include <stdio.h>
 #include <limits.h>
 #include <errno.h>
+#include <assert.h>
 #include "../ssl_local.h"
+#include "../quic/quic_local.h"
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
 #include <openssl/core_names.h>
 #include "record_local.h"
 #include "internal/packet.h"
-
-#if     defined(OPENSSL_SMALL_FOOTPRINT) || \
-        !(      defined(AES_ASM) &&     ( \
-                defined(__x86_64)       || defined(__x86_64__)  || \
-                defined(_M_AMD64)       || defined(_M_X64)      ) \
-        )
-# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
-#endif
+#include "internal/comp.h"
 
 void RECORD_LAYER_init(RECORD_LAYER *rl, SSL_CONNECTION *s)
 {
     rl->s = s;
 }
 
-void RECORD_LAYER_clear(RECORD_LAYER *rl)
+int RECORD_LAYER_clear(RECORD_LAYER *rl)
 {
+    int ret = 1;
+
+    /* Clear any buffered records we no longer need */
+    while (rl->curr_rec < rl->num_recs)
+        ret &= ssl_release_record(rl->s,
+                                  &(rl->tlsrecs[rl->curr_rec++]),
+                                  0);
+
+
     rl->wnum = 0;
     memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment));
     rl->handshake_fragment_len = 0;
     rl->wpend_tot = 0;
     rl->wpend_type = 0;
-    rl->wpend_ret = 0;
     rl->wpend_buf = NULL;
+    rl->alert_count = 0;
+    rl->num_recs = 0;
+    rl->curr_rec = 0;
 
-    ssl3_release_write_buffer(rl->s);
-
-    RECORD_LAYER_reset_write_sequence(rl);
+    BIO_free(rl->rrlnext);
+    rl->rrlnext = NULL;
 
     if (rl->rrlmethod != NULL)
         rl->rrlmethod->free(rl->rrl); /* Ignore return value */
@@ -59,12 +63,35 @@ void RECORD_LAYER_clear(RECORD_LAYER *rl)
 
     if (rl->d)
         DTLS_RECORD_LAYER_clear(rl);
+
+    return ret;
 }
 
-void RECORD_LAYER_release(RECORD_LAYER *rl)
+int RECORD_LAYER_reset(RECORD_LAYER *rl)
 {
-    if (rl->numwpipes > 0)
-        ssl3_release_write_buffer(rl->s);
+    int ret;
+
+    ret = RECORD_LAYER_clear(rl);
+
+    /* We try and reset both record layers even if one fails */
+    ret &= ssl_set_new_record_layer(rl->s,
+                                    SSL_CONNECTION_IS_DTLS(rl->s)
+                                        ? DTLS_ANY_VERSION : TLS_ANY_VERSION,
+                                    OSSL_RECORD_DIRECTION_READ,
+                                    OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
+                                    NULL, 0, NULL, 0, NULL,  0, NULL, 0,
+                                    NID_undef, NULL, NULL, NULL);
+
+    ret &= ssl_set_new_record_layer(rl->s,
+                                    SSL_CONNECTION_IS_DTLS(rl->s)
+                                        ? DTLS_ANY_VERSION : TLS_ANY_VERSION,
+                                    OSSL_RECORD_DIRECTION_WRITE,
+                                    OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
+                                    NULL, 0, NULL, 0, NULL,  0, NULL, 0,
+                                    NID_undef, NULL, NULL, NULL);
+
+    /* SSLfatal already called in the event of failure */
+    return ret;
 }
 
 /* Checks if we have unprocessed read ahead data pending */
@@ -82,16 +109,63 @@ int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
 
 int RECORD_LAYER_write_pending(const RECORD_LAYER *rl)
 {
-    /* TODO(RECLAYER): Remove me when DTLS is moved to the write record layer */
-    if (SSL_CONNECTION_IS_DTLS(rl->s))
-        return (rl->numwpipes > 0)
-            && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0;
     return rl->wpend_tot > 0;
 }
 
-void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl)
+static uint32_t ossl_get_max_early_data(SSL_CONNECTION *s)
 {
-    memset(rl->write_sequence, 0, sizeof(rl->write_sequence));
+    uint32_t max_early_data;
+    SSL_SESSION *sess = s->session;
+
+    /*
+     * If we are a client then we always use the max_early_data from the
+     * session/psksession. Otherwise we go with the lowest out of the max early
+     * data set in the session and the configured max_early_data.
+     */
+    if (!s->server && sess->ext.max_early_data == 0) {
+        if (!ossl_assert(s->psksession != NULL
+                         && s->psksession->ext.max_early_data > 0)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
+        sess = s->psksession;
+    }
+
+    if (!s->server)
+        max_early_data = sess->ext.max_early_data;
+    else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
+        max_early_data = s->recv_max_early_data;
+    else
+        max_early_data = s->recv_max_early_data < sess->ext.max_early_data
+                         ? s->recv_max_early_data : sess->ext.max_early_data;
+
+    return max_early_data;
+}
+
+static int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length,
+                                    size_t overhead, int send)
+{
+    uint32_t max_early_data;
+
+    max_early_data = ossl_get_max_early_data(s);
+
+    if (max_early_data == 0) {
+        SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+
+    /* If we are dealing with ciphertext we need to allow for the overhead */
+    max_early_data += overhead;
+
+    if (s->early_data_count + length > max_early_data) {
+        SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+    s->early_data_count += length;
+
+    return 1;
 }
 
 size_t ssl3_pending(const SSL *s)
@@ -106,7 +180,7 @@ size_t ssl3_pending(const SSL *s)
         TLS_RECORD *rdata;
         pitem *item, *iter;
 
-        iter = pqueue_iterator(sc->rlayer.d->buffered_app_data.q);
+        iter = pqueue_iterator(sc->rlayer.d->buffered_app_data);
         while ((item = pqueue_next(&iter)) != NULL) {
             rdata = item->data;
             num += rdata->length;
@@ -133,7 +207,7 @@ void SSL_set_default_read_buffer_len(SSL *s, size_t len)
 {
     SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
 
-    if (sc == NULL)
+    if (sc == NULL || IS_QUIC(s))
         return;
     sc->rlayer.default_read_buf_len = len;
 }
@@ -170,7 +244,7 @@ const char *SSL_rstate_string(const SSL *s)
     return shrt;
 }
 
-static int tls_write_check_pending(SSL_CONNECTION *s, int type,
+static int tls_write_check_pending(SSL_CONNECTION *s, uint8_t type,
                                    const unsigned char *buf, size_t len)
 {
     if (s->rlayer.wpend_tot == 0)
@@ -191,16 +265,12 @@ static int tls_write_check_pending(SSL_CONNECTION *s, int type,
  * Call this to write data in records of type 'type' It will return <= 0 if
  * not all data has been sent or non-blocking IO.
  */
-int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
+int ssl3_write_bytes(SSL *ssl, uint8_t type, const void *buf_, size_t len,
                      size_t *written)
 {
     const unsigned char *buf = buf_;
     size_t tot;
     size_t n, max_send_fragment, split_send_fragment, maxpipes;
-    /* TODO(RECLAYER): Re-enable multiblock code */
-#if 0 && !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-    size_t nw;
-#endif
     int i;
     SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl);
     OSSL_RECORD_TEMPLATE tmpls[SSL_MAX_PIPELINES];
@@ -266,9 +336,12 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
         return i;
     } else if (i > 0) {
         /* Retry needed */
-        i = s->rlayer.wrlmethod->retry_write_records(s->rlayer.wrl);
-        if (i <= 0)
+        i = HANDLE_RLAYER_WRITE_RETURN(s,
+                s->rlayer.wrlmethod->retry_write_records(s->rlayer.wrl));
+        if (i <= 0) {
+            s->rlayer.wnum = tot;
             return i;
+        }
         tot += s->rlayer.wpend_tot;
         s->rlayer.wpend_tot = 0;
     } /* else no retry required */
@@ -281,154 +354,19 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
         s->rlayer.wpend_tot = 0;
         s->rlayer.wpend_type = type;
         s->rlayer.wpend_buf = buf;
-        s->rlayer.wpend_ret = len;
     }
 
-/* TODO(RECLAYER): Re-enable multiblock code */
-#if 0 && !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-    /*
-     * Depending on platform multi-block can deliver several *times*
-     * better performance. Downside is that it has to allocate
-     * jumbo buffer to accommodate up to 8 records, but the
-     * compromise is considered worthy.
-     */
-    if (type == SSL3_RT_APPLICATION_DATA
-            && len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s))
-            && s->compress == NULL
-            && s->msg_callback == NULL
-            && !SSL_WRITE_ETM(s)
-            && SSL_USE_EXPLICIT_IV(s)
-            && !BIO_get_ktls_send(s->wbio)
-            && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
-                & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0) {
-        unsigned char aad[13];
-        EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
-        size_t packlen;
-        int packleni;
-
-        /* minimize address aliasing conflicts */
-        if ((max_send_fragment & 0xfff) == 0)
-            max_send_fragment -= 512;
-
-        if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */
-            ssl3_release_write_buffer(s);
-
-            packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
-                                          EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
-                                          (int)max_send_fragment, NULL);
-
-            if (len >= 8 * max_send_fragment)
-                packlen *= 8;
-            else
-                packlen *= 4;
-
-            if (!ssl3_setup_write_buffer(s, 1, packlen)) {
-                /* SSLfatal() already called */
-                return -1;
-            }
-        } else if (tot == len) { /* done? */
-            /* free jumbo buffer */
-            ssl3_release_write_buffer(s);
-            *written = tot;
-            return 1;
-        }
-
-        n = (len - tot);
-        for (;;) {
-            if (n < 4 * max_send_fragment) {
-                /* free jumbo buffer */
-                ssl3_release_write_buffer(s);
-                break;
-            }
-
-            if (s->s3.alert_dispatch) {
-                i = ssl->method->ssl_dispatch_alert(ssl);
-                if (i <= 0) {
-                    /* SSLfatal() already called if appropriate */
-                    s->rlayer.wnum = tot;
-                    return i;
-                }
-            }
-
-            if (n >= 8 * max_send_fragment)
-                nw = max_send_fragment * (mb_param.interleave = 8);
-            else
-                nw = max_send_fragment * (mb_param.interleave = 4);
-
-            memcpy(aad, s->rlayer.write_sequence, 8);
-            aad[8] = type;
-            aad[9] = (unsigned char)(s->version >> 8);
-            aad[10] = (unsigned char)(s->version);
-            aad[11] = 0;
-            aad[12] = 0;
-            mb_param.out = NULL;
-            mb_param.inp = aad;
-            mb_param.len = nw;
-
-            packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
-                                          EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
-                                          sizeof(mb_param), &mb_param);
-            packlen = (size_t)packleni;
-            if (packleni <= 0 || packlen > wb->len) { /* never happens */
-                /* free jumbo buffer */
-                ssl3_release_write_buffer(s);
-                break;
-            }
-
-            mb_param.out = wb->buf;
-            mb_param.inp = &buf[tot];
-            mb_param.len = nw;
-
-            if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
-                                    EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
-                                    sizeof(mb_param), &mb_param) <= 0)
-                return -1;
-
-            s->rlayer.write_sequence[7] += mb_param.interleave;
-            if (s->rlayer.write_sequence[7] < mb_param.interleave) {
-                int j = 6;
-                while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
-            }
-
-            wb->offset = 0;
-            wb->left = packlen;
-
-            s->rlayer.wpend_tot = nw;
-            s->rlayer.wpend_buf = &buf[tot];
-            s->rlayer.wpend_type = type;
-            s->rlayer.wpend_ret = nw;
-
-            i = ssl3_write_pending(s, type, &buf[tot], nw, &tmpwrit);
-            if (i <= 0) {
-                /* SSLfatal() already called if appropriate */
-                if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) {
-                    /* free jumbo buffer */
-                    ssl3_release_write_buffer(s);
-                }
-                s->rlayer.wnum = tot;
-                return i;
-            }
-            if (tmpwrit == n) {
-                /* free jumbo buffer */
-                ssl3_release_write_buffer(s);
-                *written = tot + tmpwrit;
-                return 1;
-            }
-            n -= tmpwrit;
-            tot += tmpwrit;
-        }
-    } else
-#endif  /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
     if (tot == len) {           /* done? */
         *written = tot;
         return 1;
     }
 
     /* If we have an alert to send, lets send it */
-    if (s->s3.alert_dispatch) {
+    if (s->s3.alert_dispatch > 0) {
         i = ssl->method->ssl_dispatch_alert(ssl);
         if (i <= 0) {
             /* SSLfatal() already called if appropriate */
+            s->rlayer.wnum = tot;
             return i;
         }
         /* if it went, fall through and send more stuff */
@@ -438,37 +376,7 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
 
     max_send_fragment = ssl_get_max_send_fragment(s);
     split_send_fragment = ssl_get_split_send_fragment(s);
-    /*
-     * TODO(RECLAYER): This comment is now out-of-date and probably needs to
-     * move somewhere else
-     *
-     * If max_pipelines is 0 then this means "undefined" and we default to
-     * 1 pipeline. Similarly if the cipher does not support pipelined
-     * processing then we also only use 1 pipeline, or if we're not using
-     * explicit IVs
-     */
-    maxpipes = s->max_pipelines;
-    if (maxpipes > SSL_MAX_PIPELINES) {
-        /*
-         * We should have prevented this when we set max_pipelines so we
-         * shouldn't get here
-         */
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return -1;
-    }
-    /* If no explicit maxpipes configuration - default to 1 */
-    /* TODO(RECLAYER): Should we ask the record layer how many pipes it supports? */
-    if (maxpipes <= 0)
-        maxpipes = 1;
-#if 0
-    /* TODO(RECLAYER): FIX ME */
-    if (maxpipes == 0
-        || s->enc_write_ctx == NULL
-        || (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
-            & EVP_CIPH_FLAG_PIPELINE) == 0
-        || !SSL_USE_EXPLICIT_IV(s))
-        maxpipes = 1;
-#endif
+
     if (max_send_fragment == 0
             || split_send_fragment == 0
             || split_send_fragment > max_send_fragment) {
@@ -484,7 +392,6 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
      * Some servers hang if initial client hello is larger than 256 bytes
      * and record version number > TLS 1.0
      */
-    /* TODO(RECLAYER): Does this also need to be in the DTLS equivalent code? */
     recversion = (s->version == TLS1_3_VERSION) ? TLS1_2_VERSION : s->version;
     if (SSL_get_state(ssl) == TLS_ST_CW_CLNT_HELLO
             && !s->renegotiate
@@ -494,39 +401,56 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
 
     for (;;) {
         size_t tmppipelen, remain;
-        size_t numpipes, j, lensofar = 0;
+        size_t j, lensofar = 0;
 
-        if (n == 0)
-            numpipes = 1;
-        else
-            numpipes = ((n - 1) / split_send_fragment) + 1;
-        if (numpipes > maxpipes)
-            numpipes = maxpipes;
+        /*
+        * Ask the record layer how it would like to split the amount of data
+        * that we have, and how many of those records it would like in one go.
+        */
+        maxpipes = s->rlayer.wrlmethod->get_max_records(s->rlayer.wrl, type, n,
+                                                        max_send_fragment,
+                                                        &split_send_fragment);
+        /*
+        * If max_pipelines is 0 then this means "undefined" and we default to
+        * whatever the record layer wants to do. Otherwise we use the smallest
+        * value from the number requested by the record layer, and max number
+        * configured by the user.
+        */
+        if (s->max_pipelines > 0 && maxpipes > s->max_pipelines)
+            maxpipes = s->max_pipelines;
+
+        if (maxpipes > SSL_MAX_PIPELINES)
+            maxpipes = SSL_MAX_PIPELINES;
+
+        if (split_send_fragment > max_send_fragment) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return -1;
+        }
 
-        if (n / numpipes >= max_send_fragment) {
+        if (n / maxpipes >= split_send_fragment) {
             /*
              * We have enough data to completely fill all available
              * pipelines
              */
-            for (j = 0; j < numpipes; j++) {
+            for (j = 0; j < maxpipes; j++) {
                 tmpls[j].type = type;
                 tmpls[j].version = recversion;
-                tmpls[j].buf = &(buf[tot]) + (j * max_send_fragment);
-                tmpls[j].buflen = max_send_fragment;
+                tmpls[j].buf = &(buf[tot]) + (j * split_send_fragment);
+                tmpls[j].buflen = split_send_fragment;
             }
             /* Remember how much data we are going to be sending */
-            s->rlayer.wpend_tot = numpipes * max_send_fragment;
+            s->rlayer.wpend_tot = maxpipes * split_send_fragment;
         } else {
             /* We can partially fill all available pipelines */
-            tmppipelen = n / numpipes;
-            remain = n % numpipes;
+            tmppipelen = n / maxpipes;
+            remain = n % maxpipes;
             /*
              * If there is a remainder we add an extra byte to the first few
              * pipelines
              */
             if (remain > 0)
                 tmppipelen++;
-            for (j = 0; j < numpipes; j++) {
+            for (j = 0; j < maxpipes; j++) {
                 tmpls[j].type = type;
                 tmpls[j].version = recversion;
                 tmpls[j].buf = &(buf[tot]) + lensofar;
@@ -539,7 +463,8 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
             s->rlayer.wpend_tot = n;
         }
 
-        i = s->rlayer.wrlmethod->write_records(s->rlayer.wrl, tmpls, numpipes);
+        i = HANDLE_RLAYER_WRITE_RETURN(s,
+            s->rlayer.wrlmethod->write_records(s->rlayer.wrl, tmpls, maxpipes));
         if (i <= 0) {
             /* SSLfatal() already called if appropriate */
             s->rlayer.wnum = tot;
@@ -559,23 +484,37 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, size_t len,
     }
 }
 
-int ossl_tls_handle_rlayer_return(SSL_CONNECTION *s, int ret, char *file,
-                                  int line)
+int ossl_tls_handle_rlayer_return(SSL_CONNECTION *s, int writing, int ret,
+                                  char *file, int line)
 {
     SSL *ssl = SSL_CONNECTION_GET_SSL(s);
 
     if (ret == OSSL_RECORD_RETURN_RETRY) {
-        s->rwstate = SSL_READING;
+        s->rwstate = writing ? SSL_WRITING : SSL_READING;
         ret = -1;
     } else {
         s->rwstate = SSL_NOTHING;
         if (ret == OSSL_RECORD_RETURN_EOF) {
-            if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
+            if (writing) {
+                /*
+                 * This shouldn't happen with a writing operation. We treat it
+                 * as fatal.
+                 */
+                ERR_new();
+                ERR_set_debug(file, line, 0);
+                ossl_statem_fatal(s, SSL_AD_INTERNAL_ERROR,
+                                  ERR_R_INTERNAL_ERROR, NULL);
+                ret = OSSL_RECORD_RETURN_FATAL;
+            } else if ((s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) != 0) {
                 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
                 s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
             } else {
                 ERR_new();
                 ERR_set_debug(file, line, 0);
+                /*
+                 * This reason code is part of the API and may be used by
+                 * applications for control flow decisions.
+                 */
                 ossl_statem_fatal(s, SSL_AD_DECODE_ERROR,
                                   SSL_R_UNEXPECTED_EOF_WHILE_READING, NULL);
             }
@@ -609,23 +548,43 @@ 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)
+int ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr, size_t length)
 {
+    assert(rr->length >= length);
     if (rr->rechandle != NULL) {
+        if (length == 0)
+            length = rr->length;
         /* The record layer allocated the buffers for this record */
-        s->rlayer.rrlmethod->release_record(s->rlayer.rrl, rr->rechandle);
-    } else {
+        if (HANDLE_RLAYER_READ_RETURN(s,
+                s->rlayer.rrlmethod->release_record(s->rlayer.rrl,
+                                                    rr->rechandle,
+                                                    length)) <= 0) {
+            /* RLAYER_fatal already called */
+            return 0;
+        }
+
+        if (length == rr->length)
+            s->rlayer.curr_rec++;
+    } else if (length == 0 || length == rr->length) {
         /* We allocated the buffers for this record (only happens with DTLS) */
-        OPENSSL_free(rr->data);
+        OPENSSL_free(rr->allocdata);
+        rr->allocdata = NULL;
     }
-    s->rlayer.curr_rec++;
+    rr->length -= length;
+    if (rr->length > 0)
+        rr->off += length;
+    else
+        rr->off = 0;
+
+    return 1;
 }
 
 /*-
  * Return up to 'len' payload bytes received in 'type' records.
  * 'type' is one of the following:
  *
- *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
+ *   -  SSL3_RT_HANDSHAKE (when tls_get_message_header and tls_get_message_body
+ *                        call us)
  *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
  *   -  0 (during a shutdown, no data has to be returned)
  *
@@ -650,8 +609,9 @@ void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr)
  *     Application data protocol
  *             none of our business
  */
-int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
-                    size_t len, int peek, size_t *readbytes)
+int ssl3_read_bytes(SSL *ssl, uint8_t type, uint8_t *recvd_type,
+                    unsigned char *buf, size_t len,
+                    int peek, size_t *readbytes)
 {
     int i, j, ret;
     size_t n, curr_rec, totalbytes;
@@ -725,7 +685,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
         do {
             rr = &s->rlayer.tlsrecs[s->rlayer.num_recs];
 
-            ret = HANDLE_RLAYER_RETURN(s,
+            ret = HANDLE_RLAYER_READ_RETURN(s,
                     s->rlayer.rrlmethod->read_record(s->rlayer.rrl,
                                                      &rr->rechandle,
                                                      &rr->version, &rr->type,
@@ -791,7 +751,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
          * doing a handshake for the first time
          */
         if (SSL_in_init(ssl) && type == SSL3_RT_APPLICATION_DATA
-            && s->enc_read_ctx == NULL) {
+                && SSL_IS_FIRST_HANDSHAKE(s)) {
             SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_APP_DATA_IN_HANDSHAKE);
             return -1;
         }
@@ -812,8 +772,8 @@ 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)
-                ssl_release_record(s, rr);
+            if (rr->length == 0 && !ssl_release_record(s, rr, 0))
+                return -1;
 
             return 0;
         }
@@ -830,15 +790,11 @@ 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)
-                    ssl_release_record(s, rr);
+                if (rr->length == 0 && !ssl_release_record(s, rr, 0))
+                    return -1;
             } else {
-                if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
-                    OPENSSL_cleanse(&(rr->data[rr->off]), n);
-                rr->length -= n;
-                rr->off += n;
-                if (rr->length == 0)
-                    ssl_release_record(s, rr);
+                if (!ssl_release_record(s, rr, n))
+                    return -1;
             }
             if (rr->length == 0
                 || (peek && n == rr->length)) {
@@ -897,8 +853,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
 
     if (rr->type == SSL3_RT_ALERT) {
         unsigned int alert_level, alert_descr;
-        unsigned char *alert_bytes = rr->data
-                                     + rr->off;
+        const unsigned char *alert_bytes = rr->data + rr->off;
         PACKET alert;
 
         if (!PACKET_buf_init(&alert, alert_bytes, rr->length)
@@ -926,7 +881,8 @@ 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;
-            ssl_release_record(s, rr);
+            if (!ssl_release_record(s, rr, 0))
+                return -1;
 
             s->rlayer.alert_count++;
             if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
@@ -953,7 +909,8 @@ 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;
-            ssl_release_record(s, rr);
+            if (!ssl_release_record(s, rr, 0))
+                return -1;
             SSL_CTX_remove_session(s->session_ctx, s->session);
             return 0;
         } else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
@@ -988,7 +945,8 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
              * sent close_notify.
              */
             if (!SSL_CONNECTION_IS_TLS13(s)) {
-                ssl_release_record(s, rr);
+                if (!ssl_release_record(s, rr, 0))
+                    return -1;
 
                 if ((s->mode & SSL_MODE_AUTO_RETRY) != 0)
                     goto start;
@@ -1007,7 +965,8 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
              * above.
              * No alert sent because we already sent close_notify
              */
-            ssl_release_record(s, rr);
+            if (!ssl_release_record(s, rr, 0))
+                return -1;
             SSLfatal(s, SSL_AD_NO_ALERT,
                      SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
             return -1;
@@ -1030,12 +989,16 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
             n = rr->length; /* available bytes */
 
         /* now move 'n' bytes: */
-        memcpy(dest + *dest_len, rr->data + rr->off, n);
-        rr->off += n;
-        rr->length -= n;
-        *dest_len += n;
-        if (rr->length == 0)
-            ssl_release_record(s, rr);
+        if (n > 0) {
+            memcpy(dest + *dest_len, rr->data + rr->off, n);
+            *dest_len += n;
+        }
+        /*
+         * We release the number of bytes consumed, or the whole record if it
+         * is zero length
+         */
+        if ((n > 0 || rr->length == 0) && !ssl_release_record(s, rr, n))
+            return -1;
 
         if (*dest_len < dest_maxlen)
             goto start;     /* fragment was too small */
@@ -1139,7 +1102,8 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
                 /* SSLfatal() already called */
                 return -1;
             }
-            ssl_release_record(s, rr);
+            if (!ssl_release_record(s, rr, 0))
+                return -1;
             goto start;
         } else {
             SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
@@ -1148,17 +1112,6 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
     }
 }
 
-void ssl3_record_sequence_update(unsigned char *seq)
-{
-    int i;
-
-    for (i = 7; i >= 0; i--) {
-        ++seq[i];
-        if (seq[i] != 0)
-            break;
-    }
-}
-
 /*
  * Returns true if the current rrec was sent in SSLv2 backwards compatible
  * format and false otherwise.
@@ -1192,16 +1145,38 @@ static int rlayer_security_wrapper(void *cbarg, int op, int bits, int nid,
     return ssl_security(s, op, bits, nid, other);
 }
 
+static OSSL_FUNC_rlayer_padding_fn rlayer_padding_wrapper;
+static size_t rlayer_padding_wrapper(void *cbarg, int type, size_t len)
+{
+    SSL_CONNECTION *s = cbarg;
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+    return s->rlayer.record_padding_cb(ssl, type, len,
+                                       s->rlayer.record_padding_arg);
+}
+
 static const OSSL_DISPATCH rlayer_dispatch[] = {
     { OSSL_FUNC_RLAYER_SKIP_EARLY_DATA, (void (*)(void))ossl_statem_skip_early_data },
     { OSSL_FUNC_RLAYER_MSG_CALLBACK, (void (*)(void))rlayer_msg_callback_wrapper },
     { OSSL_FUNC_RLAYER_SECURITY, (void (*)(void))rlayer_security_wrapper },
-    { 0, NULL }
+    { OSSL_FUNC_RLAYER_PADDING, (void (*)(void))rlayer_padding_wrapper },
+    OSSL_DISPATCH_END
 };
 
+void ossl_ssl_set_custom_record_layer(SSL_CONNECTION *s,
+                                      const OSSL_RECORD_METHOD *meth,
+                                      void *rlarg)
+{
+    s->rlayer.custom_rlmethod = meth;
+    s->rlayer.rlarg = rlarg;
+}
+
 static const OSSL_RECORD_METHOD *ssl_select_next_record_layer(SSL_CONNECTION *s,
+                                                              int direction,
                                                               int level)
 {
+    if (s->rlayer.custom_rlmethod != NULL)
+        return s->rlayer.custom_rlmethod;
 
     if (level == OSSL_RECORD_PROTECTION_LEVEL_NONE) {
         if (SSL_CONNECTION_IS_DTLS(s))
@@ -1219,7 +1194,8 @@ static const OSSL_RECORD_METHOD *ssl_select_next_record_layer(SSL_CONNECTION *s,
 #endif
 
     /* Default to the current OSSL_RECORD_METHOD */
-    return s->rlayer.rrlmethod;
+    return direction == OSSL_RECORD_DIRECTION_READ ? s->rlayer.rrlmethod
+                                                   : s->rlayer.wrlmethod;
 }
 
 static int ssl_post_record_layer_select(SSL_CONNECTION *s, int direction)
@@ -1256,12 +1232,13 @@ static int ssl_post_record_layer_select(SSL_CONNECTION *s, int direction)
 
 int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
                              int direction, int level,
+                             unsigned char *secret, size_t secretlen,
                              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,
                              int mactype, const EVP_MD *md,
-                             const SSL_COMP *comp)
+                             const SSL_COMP *comp, const EVP_MD *kdfdigest)
 {
     OSSL_PARAM options[5], *opts = options;
     OSSL_PARAM settings[6], *set =  settings;
@@ -1271,11 +1248,14 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
     SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
     const OSSL_RECORD_METHOD *meth;
     int use_etm, stream_mac = 0, tlstree = 0;
-    unsigned int maxfrag = SSL3_RT_MAX_PLAIN_LENGTH;
+    unsigned int maxfrag = (direction == OSSL_RECORD_DIRECTION_WRITE)
+                           ? ssl_get_max_send_fragment(s)
+                           : SSL3_RT_MAX_PLAIN_LENGTH;
     int use_early_data = 0;
     uint32_t max_early_data;
+    COMP_METHOD *compm = (comp == NULL) ? NULL : comp->method;
 
-    meth = ssl_select_next_record_layer(s, level);
+    meth = ssl_select_next_record_layer(s, direction, level);
 
     if (direction == OSSL_RECORD_DIRECTION_READ) {
         thismethod = &s->rlayer.rrlmethod;
@@ -1305,6 +1285,9 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
                                               &s->rlayer.default_read_buf_len);
         *opts++ = OSSL_PARAM_construct_int(OSSL_LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD,
                                            &s->rlayer.read_ahead);
+    } else {
+        *opts++ = OSSL_PARAM_construct_size_t(OSSL_LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING,
+                                              &s->rlayer.block_padding);
     }
     *opts = OSSL_PARAM_construct_end();
 
@@ -1337,9 +1320,16 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
         *set++ = OSSL_PARAM_construct_int(OSSL_LIBSSL_RECORD_LAYER_PARAM_TLSTREE,
                                           &tlstree);
 
-    if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
+    /*
+     * We only need to do this for the read side. The write side should already
+     * have the correct value due to the ssl_get_max_send_fragment() call above
+     */
+    if (direction == OSSL_RECORD_DIRECTION_READ
+            && s->session != NULL
+            && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
         maxfrag = GET_MAX_FRAGMENT_LENGTH(s->session);
 
+
     if (maxfrag != SSL3_RT_MAX_PLAIN_LENGTH)
         *set++ = OSSL_PARAM_construct_uint(OSSL_LIBSSL_RECORD_LAYER_PARAM_MAX_FRAG_LEN,
                                            &maxfrag);
@@ -1349,7 +1339,6 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
      * using the early keys. A server also needs to worry about rejected early
      * data that might arrive when the handshake keys are in force.
      */
-    /* TODO(RECLAYER): Check this when doing the "write" record layer */
     if (s->server && direction == OSSL_RECORD_DIRECTION_READ) {
         use_early_data = (level == OSSL_RECORD_PROTECTION_LEVEL_EARLY
                           || level == OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE);
@@ -1360,8 +1349,8 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
         max_early_data = ossl_get_max_early_data(s);
 
         if (max_early_data != 0)
-            *set++ = OSSL_PARAM_construct_uint(OSSL_LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA,
-                                               &max_early_data);
+            *set++ = OSSL_PARAM_construct_uint32(OSSL_LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA,
+                                                 &max_early_data);
     }
 
     *set = OSSL_PARAM_construct_end();
@@ -1370,34 +1359,62 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
         int rlret;
         BIO *prev = NULL;
         BIO *next = NULL;
-        unsigned int epoch = 0;;
+        unsigned int epoch = 0;
+        OSSL_DISPATCH rlayer_dispatch_tmp[OSSL_NELEM(rlayer_dispatch)];
+        size_t i, j;
 
         if (direction == OSSL_RECORD_DIRECTION_READ) {
             prev = s->rlayer.rrlnext;
             if (SSL_CONNECTION_IS_DTLS(s)
                     && level != OSSL_RECORD_PROTECTION_LEVEL_NONE)
-                epoch =  DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer) + 1; /* new epoch */
+                epoch = dtls1_get_epoch(s, SSL3_CC_READ); /* new epoch */
 
+#ifndef OPENSSL_NO_DGRAM
             if (SSL_CONNECTION_IS_DTLS(s))
                 next = BIO_new(BIO_s_dgram_mem());
             else
+#endif
                 next = BIO_new(BIO_s_mem());
 
             if (next == NULL) {
-                BIO_free(prev);
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
             s->rlayer.rrlnext = next;
+        } else {
+            if (SSL_CONNECTION_IS_DTLS(s)
+                    && level != OSSL_RECORD_PROTECTION_LEVEL_NONE)
+                epoch = dtls1_get_epoch(s, SSL3_CC_WRITE); /* new epoch */
+        }
+
+        /*
+         * Create a copy of the dispatch array, missing out wrappers for
+         * callbacks that we don't need.
+         */
+        for (i = 0, j = 0; i < OSSL_NELEM(rlayer_dispatch); i++) {
+            switch (rlayer_dispatch[i].function_id) {
+            case OSSL_FUNC_RLAYER_MSG_CALLBACK:
+                if (s->msg_callback == NULL)
+                    continue;
+                break;
+            case OSSL_FUNC_RLAYER_PADDING:
+                if (s->rlayer.record_padding_cb == NULL)
+                    continue;
+                break;
+            default:
+                break;
+            }
+            rlayer_dispatch_tmp[j++] = rlayer_dispatch[i];
         }
 
         rlret = meth->new_record_layer(sctx->libctx, sctx->propq, version,
                                        s->server, direction, level, epoch,
-                                       key, keylen, iv, ivlen, mackey,
-                                       mackeylen, ciph, taglen, mactype, md,
-                                       comp, prev, thisbio, next, NULL, NULL,
-                                       settings, options, rlayer_dispatch, s,
-                                       &newrl);
+                                       secret, secretlen, key, keylen, iv,
+                                       ivlen, mackey, mackeylen, ciph, taglen,
+                                       mactype, md, compm, kdfdigest, prev,
+                                       thisbio, next, NULL, NULL, settings,
+                                       options, rlayer_dispatch_tmp, s,
+                                       s->rlayer.rlarg, &newrl);
         BIO_free(prev);
         switch (rlret) {
         case OSSL_RECORD_RETURN_FATAL:
@@ -1427,9 +1444,20 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
         break;
     }
 
-    if (*thismethod != NULL && !(*thismethod)->free(*thisrl)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return 0;
+    /*
+     * Free the old record layer if we have one except in the case of DTLS when
+     * writing and there are still buffered sent messages in our queue. In that
+     * case the record layer is still referenced by those buffered messages for
+     * potential retransmit. Only when those buffered messages get freed do we
+     * free the record layer object (see dtls1_hm_fragment_free)
+     */
+    if (!SSL_CONNECTION_IS_DTLS(s)
+            || direction == OSSL_RECORD_DIRECTION_READ
+            || pqueue_peek(s->d1->sent_messages) == NULL) {
+        if (*thismethod != NULL && !(*thismethod)->free(*thisrl)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
     }
 
     *thisrl = newrl;