Transfer the functionality from ssl3_read_n to the new record layer
authorMatt Caswell <matt@openssl.org>
Thu, 7 Apr 2022 16:35:36 +0000 (17:35 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 18 Aug 2022 15:38:12 +0000 (16:38 +0100)
This transfers the low level function ssl3_read_n to the new record layer.
We temporarily make the read_n function a top level record layer function.
Eventually, in later commits in this refactor, we will remove it as a top
level function and it will just be called from read_record.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18132)

17 files changed:
crypto/err/openssl.txt
include/openssl/core_names.h
include/openssl/sslerr.h
ssl/d1_lib.c
ssl/ktls.c
ssl/record/rec_layer_d1.c
ssl/record/rec_layer_s3.c
ssl/record/record_local.h
ssl/record/recordmethod.h
ssl/record/ssl3_buffer.c
ssl/record/ssl3_record.c
ssl/record/tlsrecord.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_local.h
ssl/sslerr.h
ssl/t1_enc.c

index 7c9a516c137a185d468d784d86dba3724b59c9b8..9ab7c0fdd4808ed6a83d30e2119ee5e4c0f1a322 100644 (file)
@@ -1351,6 +1351,7 @@ SSL_R_EXCESSIVE_MESSAGE_SIZE:152:excessive message size
 SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received
 SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
 SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
+SSL_R_FAILED_TO_GET_PARAMETER:316:failed to get parameter
 SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
 SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
 SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
@@ -1457,6 +1458,7 @@ SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb
 SSL_R_PSK_NO_SERVER_CB:225:psk no server cb
 SSL_R_READ_BIO_NOT_SET:211:read bio not set
 SSL_R_READ_TIMEOUT_EXPIRED:312:read timeout expired
+SSL_R_RECORD_LAYER_FAILURE:313:record layer failure
 SSL_R_RECORD_LENGTH_MISMATCH:213:record length mismatch
 SSL_R_RECORD_TOO_SMALL:298:record too small
 SSL_R_RENEGOTIATE_EXT_TOO_LONG:335:renegotiate ext too long
index a8f875a59abd84bbfb7a279320d1028bfba789c6..1d866368f7e2d2a0f838dc5da35088b09106eb45 100644 (file)
@@ -555,6 +555,13 @@ extern "C" {
 /* OSSL_DECODER input type if a decoder is used by the store */
 #define OSSL_STORE_PARAM_INPUT_TYPE "input-type"   /* UTF8_STRING */
 
+
+/* Libssl record layer */
+
+#define OSSL_LIBSSL_RECORD_LAYER_PARAM_OPTIONS    "options"
+#define OSSL_LIBSSL_RECORD_LAYER_PARAM_MODE       "mode"
+#define OSSL_LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD "read_ahead"
+
 # ifdef __cplusplus
 }
 # endif
index a4746d70b5b66e2fdc438720b882cd9cdd31ffa7..e984fe375e3052c92c1b3250d10c82b3bdcb7615 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
 # define SSL_R_EXTENSION_NOT_RECEIVED                     279
 # define SSL_R_EXTRA_DATA_IN_MESSAGE                      153
 # define SSL_R_EXT_LENGTH_MISMATCH                        163
+# define SSL_R_FAILED_TO_GET_PARAMETER                    316
 # define SSL_R_FAILED_TO_INIT_ASYNC                       405
 # define SSL_R_FRAGMENTED_CLIENT_HELLO                    401
 # define SSL_R_GOT_A_FIN_BEFORE_A_CCS                     154
 # define SSL_R_PSK_NO_SERVER_CB                           225
 # define SSL_R_READ_BIO_NOT_SET                           211
 # define SSL_R_READ_TIMEOUT_EXPIRED                       312
+# define SSL_R_RECORD_LAYER_FAILURE                       313
 # define SSL_R_RECORD_LENGTH_MISMATCH                     213
 # define SSL_R_RECORD_TOO_SMALL                           298
 # define SSL_R_RENEGOTIATE_EXT_TOO_LONG                   335
index 3b76065be9e83b80475e793cdd94ab666e1086ee..e38c6d677f0a45d76a7d3bb6433ac6cc403da212 100644 (file)
@@ -490,13 +490,13 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
         /* ERR_raise() already called */
         return -1;
     }
-    buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
+    buf = s->rrlmethod->get0_rbuf(s->rrl)->buf;
     wbuf = RECORD_LAYER_get_wbuf(&s->rlayer)[0].buf;
 #if defined(SSL3_ALIGN_PAYLOAD)
 # if SSL3_ALIGN_PAYLOAD != 0
     /*
      * Using SSL3_RT_HEADER_LENGTH here instead of DTLS1_RT_HEADER_LENGTH for
-     * consistency with ssl3_read_n. In practice it should make no difference
+     * consistency with read_n. In practice it should make no difference
      * for sensible values of SSL3_ALIGN_PAYLOAD because the difference between
      * SSL3_RT_HEADER_LENGTH and DTLS1_RT_HEADER_LENGTH is exactly 8
      */
index 67499c350741abddde4b08f6192d642724d5d646..78e6ecd554b8bd073bc5899580e3c038da73375b 100644 (file)
@@ -20,7 +20,7 @@
   */
 static int count_unprocessed_records(SSL_CONNECTION *s)
 {
-    SSL3_BUFFER *rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+    SSL3_BUFFER *rbuf = s->rrlmethod->get0_rbuf(s->rrl);
     PACKET pkt, subpkt;
     int count = 0;
 
index 9f90bee9d9187cdfa89809ad552986f316c92d7d..dd78921948fcb2e97eb369ca727ed536030347e5 100644 (file)
@@ -130,11 +130,10 @@ static int dtls1_copy_record(SSL_CONNECTION *s, pitem *item)
 
     rdata = (DTLS1_RECORD_DATA *)item->data;
 
-    SSL3_BUFFER_release(&s->rlayer.rbuf);
+    SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
 
-    s->rlayer.packet = rdata->packet;
-    s->rlayer.packet_length = rdata->packet_length;
-    memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
+    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 */
@@ -165,9 +164,9 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
         return -1;
     }
 
-    rdata->packet = s->rlayer.packet;
-    rdata->packet_length = s->rlayer.packet_length;
-    memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
+    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));
 
     item->data = rdata;
@@ -182,9 +181,8 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
     }
 #endif
 
-    s->rlayer.packet = NULL;
-    s->rlayer.packet_length = 0;
-    memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf));
+    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)) {
@@ -247,7 +245,7 @@ int dtls1_process_buffered_records(SSL_CONNECTION *s)
 
         rr = RECORD_LAYER_get_rrec(&s->rlayer);
 
-        rb = RECORD_LAYER_get_rbuf(&s->rlayer);
+        rb = s->rrlmethod->get0_rbuf(s->rrl);
 
         if (SSL3_BUFFER_get_left(rb) > 0) {
             /*
@@ -293,7 +291,7 @@ int dtls1_process_buffered_records(SSL_CONNECTION *s)
                 }
                 /* dump this record */
                 rr->length = 0;
-                RECORD_LAYER_reset_packet_length(&s->rlayer);
+                s->rrlmethod->reset_packet_length(s->rrl);
                 continue;
             }
 
@@ -356,7 +354,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
     if (sc == NULL)
         return -1;
 
-    if (!SSL3_BUFFER_is_initialised(&sc->rlayer.rbuf)) {
+    if (!SSL3_BUFFER_is_initialised(sc->rrlmethod->get0_rbuf(sc->rrl))) {
         /* Not initialized yet */
         if (!ssl3_setup_buffers(sc)) {
             /* SSLfatal() already called */
@@ -689,7 +687,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
             SSL3_RECORD_set_length(rr, 0);
             SSL3_RECORD_set_read(rr);
             if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
-                if (SSL3_BUFFER_get_left(&sc->rlayer.rbuf) == 0) {
+                if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
                     /* no read-ahead left? */
                     BIO *bio;
 
@@ -725,7 +723,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
             return -1;
 
         if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
-            if (SSL3_BUFFER_get_left(&sc->rlayer.rbuf) == 0) {
+            if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
                 /* no read-ahead left? */
                 BIO *bio;
                 /*
index 05b49a21e3ac3043a15b05a109ba05937b0e018a..d7791cf93536c3fb27fdb0f888f6966b2716d68f 100644 (file)
@@ -152,8 +152,7 @@ void SSL_set_default_read_buffer_len(SSL *s, size_t len)
 
     if (sc == NULL)
         return;
-
-    SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&sc->rlayer), len);
+    SSL3_BUFFER_set_default_len(sc->rrlmethod->get0_rbuf(sc->rrl), len);
 }
 
 const char *SSL_rstate_string_long(const SSL *s)
@@ -194,186 +193,6 @@ const char *SSL_rstate_string(const SSL *s)
     }
 }
 
-/*
- * Return values are as per SSL_read()
- */
-int ssl3_read_n(SSL_CONNECTION *s, size_t n, size_t max, int extend,
-                int clearold, size_t *readbytes)
-{
-    /*
-     * If extend == 0, obtain new n-byte packet; if extend == 1, increase
-     * packet by another n bytes. The packet will be in the sub-array of
-     * s->rlayer.rbuf.buf specified by s->rlayer.packet and
-     * s->rlayer.packet_length. (If s->rlayer.read_ahead is set, 'max' bytes may
-     * be stored in rbuf [plus s->rlayer.packet_length bytes if extend == 1].)
-     * if clearold == 1, move the packet to the start of the buffer; if
-     * clearold == 0 then leave any old packets where they were
-     */
-    size_t len, left, align = 0;
-    unsigned char *pkt;
-    SSL3_BUFFER *rb;
-
-    if (n == 0)
-        return 0;
-
-    rb = &s->rlayer.rbuf;
-    if (rb->buf == NULL)
-        if (!ssl3_setup_read_buffer(s)) {
-            /* SSLfatal() already called */
-            return -1;
-        }
-
-    left = rb->left;
-#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
-    align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
-    align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
-#endif
-
-    if (!extend) {
-        /* start with empty packet ... */
-        if (left == 0)
-            rb->offset = align;
-        else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) {
-            /*
-             * check if next packet length is large enough to justify payload
-             * alignment...
-             */
-            pkt = rb->buf + rb->offset;
-            if (pkt[0] == SSL3_RT_APPLICATION_DATA
-                && (pkt[3] << 8 | pkt[4]) >= 128) {
-                /*
-                 * Note that even if packet is corrupted and its length field
-                 * is insane, we can only be led to wrong decision about
-                 * whether memmove will occur or not. Header values has no
-                 * effect on memmove arguments and therefore no buffer
-                 * overrun can be triggered.
-                 */
-                memmove(rb->buf + align, pkt, left);
-                rb->offset = align;
-            }
-        }
-        s->rlayer.packet = rb->buf + rb->offset;
-        s->rlayer.packet_length = 0;
-        /* ... now we can act as if 'extend' was set */
-    }
-
-    len = s->rlayer.packet_length;
-    pkt = rb->buf + align;
-    /*
-     * Move any available bytes to front of buffer: 'len' bytes already
-     * pointed to by 'packet', 'left' extra ones at the end
-     */
-    if (s->rlayer.packet != pkt && clearold == 1) {
-        memmove(pkt, s->rlayer.packet, len + left);
-        s->rlayer.packet = pkt;
-        rb->offset = len + align;
-    }
-
-    /*
-     * For DTLS/UDP reads should not span multiple packets because the read
-     * operation returns the whole packet at once (as long as it fits into
-     * the buffer).
-     */
-    if (SSL_CONNECTION_IS_DTLS(s)) {
-        if (left == 0 && extend)
-            return 0;
-        if (left > 0 && n > left)
-            n = left;
-    }
-
-    /* if there is enough in the buffer from a previous read, take some */
-    if (left >= n) {
-        s->rlayer.packet_length += n;
-        rb->left = left - n;
-        rb->offset += n;
-        *readbytes = n;
-        return 1;
-    }
-
-    /* else we need to read more data */
-
-    if (n > rb->len - rb->offset) {
-        /* does not happen */
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return -1;
-    }
-
-    /*
-     * Ktls always reads full records.
-     * Also, we always act like read_ahead is set for DTLS.
-     */
-    if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
-        && !SSL_CONNECTION_IS_DTLS(s)) {
-        /* ignore max parameter */
-        max = n;
-    } else {
-        if (max < n)
-            max = n;
-        if (max > rb->len - rb->offset)
-            max = rb->len - rb->offset;
-    }
-
-    while (left < n) {
-        size_t bioread = 0;
-        int ret;
-
-        /*
-         * Now we have len+left bytes at the front of s->s3.rbuf.buf and
-         * need to read in more until we have len+n (up to len+max if
-         * possible)
-         */
-
-        clear_sys_error();
-        if (s->rbio != NULL) {
-            s->rwstate = SSL_READING;
-            ret = BIO_read(s->rbio, pkt + len + left, max - left);
-            if (ret >= 0)
-                bioread = ret;
-            if (ret <= 0
-                    && !BIO_should_retry(s->rbio)
-                    && BIO_eof(s->rbio)) {
-                if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
-                    SSL_set_shutdown(SSL_CONNECTION_GET_SSL(s),
-                                     SSL_RECEIVED_SHUTDOWN);
-                    s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
-                } else {
-                    SSLfatal(s, SSL_AD_DECODE_ERROR,
-                             SSL_R_UNEXPECTED_EOF_WHILE_READING);
-                }
-            }
-        } else {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
-            ret = -1;
-        }
-
-        if (ret <= 0) {
-            rb->left = left;
-            if ((s->mode & SSL_MODE_RELEASE_BUFFERS) != 0
-                && !SSL_CONNECTION_IS_DTLS(s))
-                if (len + left == 0)
-                    ssl3_release_read_buffer(s);
-            return ret;
-        }
-        left += bioread;
-        /*
-         * reads should *never* span multiple packets for DTLS because the
-         * underlying transport protocol is message oriented as opposed to
-         * byte oriented as in the TLS case.
-         */
-        if (SSL_CONNECTION_IS_DTLS(s)) {
-            if (n > left)
-                n = left;       /* makes the while condition false */
-        }
-    }
-
-    /* done reading, now the book-keeping */
-    rb->offset += n;
-    rb->left = left - n;
-    s->rlayer.packet_length += n;
-    s->rwstate = SSL_NOTHING;
-    *readbytes = n;
-    return 1;
-}
 
 /*
  * Call this to write data in records of type 'type' It will return <= 0 if
@@ -1321,7 +1140,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,
 
     is_tls13 = SSL_CONNECTION_IS_TLS13(s);
 
-    rbuf = &s->rlayer.rbuf;
+    rbuf = s->rrlmethod->get0_rbuf(s->rrl);
 
     if (!SSL3_BUFFER_is_initialised(rbuf)) {
         /* Not initialized yet */
index 31691787b17c65325c379f59245bf9d180e350a1..7d92c973ec4549f60f48c7fc1adaefdcbda8cfd1 100644 (file)
@@ -36,9 +36,6 @@
 #define RECORD_LAYER_clear_first_record(rl)     ((rl)->is_first_record = 0)
 #define DTLS_RECORD_LAYER_get_r_epoch(rl)       ((rl)->d->r_epoch)
 
-__owur int ssl3_read_n(SSL_CONNECTION *s, size_t n, size_t max, int extend,
-                       int clearold, size_t *readbytes);
-
 DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
                                unsigned int *is_next_epoch);
 int dtls1_process_buffered_records(SSL_CONNECTION *s);
index 22dfa7afe79765ade7b59655498188420f5d4729..da5739f8e7414e488e257fcdf0545473f779ccf8 100644 (file)
@@ -69,6 +69,12 @@ typedef struct ossl_record_layer_st OSSL_RECORD_LAYER;
 #define OSSL_RECORD_PROTECTION_LEVEL_APPLICATION 3
 
 
+#define OSSL_RECORD_RETURN_SUCCESS           1
+#define OSSL_RECORD_RETURN_RETRY             0
+#define OSSL_RECORD_RETURN_NON_FATAL_ERR    -1
+#define OSSL_RECORD_RETURN_FATAL            -2
+#define OSSL_RECORD_RETURN_EOF              -3
+
 /*
  * Template for creating a record. A record consists of the |type| of data it
  * will contain (e.g. alert, handshake, application data, etc) along with an
@@ -237,4 +243,35 @@ struct ossl_record_method_st {
      */
     void (*release_record)(OSSL_RECORD_LAYER *rl, void *rechandle);
 
+    /*
+     * In the event that a fatal error is returned from the functions above then
+     * get_alert_code() can be called to obtain a more details identifier for
+     * the error. In (D)TLS this is the alert description code.
+     */
+    int (*get_alert_code)(OSSL_RECORD_LAYER *rl);
+
+    /*
+     * Update the transport BIO from the one originally set in the
+     * new_record_layer call
+     */
+    int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio);
+
+    /*
+     * 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.
+     */
+    int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+                  int clearold, size_t *readbytes);
+    SSL3_BUFFER *(*get0_rbuf)(OSSL_RECORD_LAYER *rl);
+    unsigned char *(*get0_packet)(OSSL_RECORD_LAYER *rl);
+    void (*set0_packet)(OSSL_RECORD_LAYER *rl, unsigned char *packet,
+                        size_t packetlen);
+    size_t (*get_packet_length)(OSSL_RECORD_LAYER *rl);
+    void (*reset_packet_length)(OSSL_RECORD_LAYER *rl);
 };
+
+
+/* Standard built-in record methods */
+extern const OSSL_RECORD_METHOD ossl_tls_record_method;
+extern const OSSL_RECORD_METHOD ossl_dtls_record_method;
\ No newline at end of file
index 95149bfc05247010c7735e320d88f4b18a9c6eeb..514f522297e75724e3eb5588fb8ed06bd262f7fe 100644 (file)
@@ -40,7 +40,7 @@ int ssl3_setup_read_buffer(SSL_CONNECTION *s)
     size_t len, align = 0, headerlen;
     SSL3_BUFFER *b;
 
-    b = RECORD_LAYER_get_rbuf(&s->rlayer);
+    b = s->rrlmethod->get0_rbuf(s->rrl);
 
     if (SSL_CONNECTION_IS_DTLS(s))
         headerlen = DTLS1_RT_HEADER_LENGTH;
@@ -177,7 +177,7 @@ int ssl3_release_read_buffer(SSL_CONNECTION *s)
 {
     SSL3_BUFFER *b;
 
-    b = RECORD_LAYER_get_rbuf(&s->rlayer);
+    b = s->rrlmethod->get0_rbuf(s->rrl);
     if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
         OPENSSL_cleanse(b->buf, b->len);
     OPENSSL_free(b->buf);
index 02bf81b9fa80b27481979daa4bfd4ee883e76fef..0225a85b90e206cc2e0b40b51b10fa2e4e293ec1 100644 (file)
@@ -73,7 +73,7 @@ static int ssl3_record_app_data_waiting(SSL_CONNECTION *s)
     size_t left, len;
     unsigned char *p;
 
-    rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+    rbuf = s->rrlmethod->get0_rbuf(s->rrl);
 
     p = SSL3_BUFFER_get_buf(rbuf);
     if (p == NULL)
@@ -149,6 +149,54 @@ int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length,
     return 1;
 }
 
+static int tls_handle_rlayer_return(SSL_CONNECTION *s, int ret, char *file,
+                                    int line)
+{
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+    if (ret == OSSL_RECORD_RETURN_RETRY) {
+        s->rwstate = SSL_READING;
+        ret = -1;
+    } else {
+        s->rwstate = SSL_NOTHING;
+        if (ret == OSSL_RECORD_RETURN_EOF) {
+            if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
+                SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
+                s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
+            } else {
+                ERR_new();
+                ERR_set_debug(file, line, 0);
+                ossl_statem_fatal(s, SSL_AD_DECODE_ERROR,
+                                  SSL_R_UNEXPECTED_EOF_WHILE_READING, NULL);
+            }
+        } else if (ret == OSSL_RECORD_RETURN_FATAL) {
+            ERR_new();
+            ERR_set_debug(file, line, 0);
+            ossl_statem_fatal(s, s->rrlmethod->get_alert_code(s->rrl),
+                              SSL_R_RECORD_LAYER_FAILURE, NULL);
+        }
+        /*
+         * The record layer distinguishes the cases of EOF, non-fatal
+         * err and retry. Upper layers do not.
+         * If we got a retry or success then *ret is already correct,
+         * otherwise we need to convert the return value.
+         */
+        /*
+         * TODO(RECLAYER): What does a non fatal err that isn't a retry even
+         * mean???
+         */
+        if (ret == OSSL_RECORD_RETURN_NON_FATAL_ERR || ret == OSSL_RECORD_RETURN_EOF)
+            ret = 0;
+        else if (ret < OSSL_RECORD_RETURN_NON_FATAL_ERR)
+            ret = -1;
+    }
+
+    return ret;
+}
+
+# define HANDLE_RLAYER_RETURN(s, ret) \
+    tls_handle_rlayer_return(s, ret, OPENSSL_FILE, OPENSSL_LINE)
+
 /*
  * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
  * will be processed per call to ssl3_get_record. Without this limit an
@@ -192,7 +240,8 @@ int ssl3_get_record(SSL_CONNECTION *s)
     SSL *ssl = SSL_CONNECTION_GET_SSL(s);
 
     rr = RECORD_LAYER_get_rrec(&s->rlayer);
-    rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+    rbuf = s->rrlmethod->get0_rbuf(s->rrl);
+
     max_recs = s->max_pipelines;
     if (max_recs == 0)
         max_recs = 1;
@@ -209,14 +258,15 @@ int ssl3_get_record(SSL_CONNECTION *s)
 
         /* check if we have the header */
         if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
-            (RECORD_LAYER_get_packet_length(&s->rlayer)
-             < SSL3_RT_HEADER_LENGTH)) {
+            (s->rrlmethod->get_packet_length(s->rrl) < SSL3_RT_HEADER_LENGTH)) {
             size_t sslv2len;
             unsigned int type;
 
-            rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
-                               SSL3_BUFFER_get_len(rbuf), 0,
-                               num_recs == 0 ? 1 : 0, &n);
+            rret = HANDLE_RLAYER_RETURN(s,
+                s->rrlmethod->read_n(s->rrl, SSL3_RT_HEADER_LENGTH,
+                                     SSL3_BUFFER_get_len(rbuf), 0,
+                                     num_recs == 0 ? 1 : 0, &n));
+
             if (rret <= 0) {
 #ifndef OPENSSL_NO_KTLS
                 if (!using_ktls || rret == 0)
@@ -242,9 +292,9 @@ int ssl3_get_record(SSL_CONNECTION *s)
             }
             RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
 
-            p = RECORD_LAYER_get_packet(&s->rlayer);
-            if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
-                                 RECORD_LAYER_get_packet_length(&s->rlayer))) {
+            p = s->rrlmethod->get0_packet(s->rrl);
+            if (!PACKET_buf_init(&pkt, p,
+                                 s->rrlmethod->get_packet_length(s->rrl))) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return -1;
             }
@@ -344,7 +394,7 @@ int ssl3_get_record(SSL_CONNECTION *s)
                     if (RECORD_LAYER_is_first_record(&s->rlayer)) {
                         /* Go back to start of packet, look at the five bytes
                          * that we have. */
-                        p = RECORD_LAYER_get_packet(&s->rlayer);
+                        p = s->rrlmethod->get0_packet(s->rrl);
                         if (HAS_PREFIX((char *)p, "GET ") ||
                             HAS_PREFIX((char *)p, "POST ") ||
                             HAS_PREFIX((char *)p, "HEAD ") ||
@@ -449,7 +499,8 @@ int ssl3_get_record(SSL_CONNECTION *s)
         if (more > 0) {
             /* now s->rlayer.packet_length == SSL3_RT_HEADER_LENGTH */
 
-            rret = ssl3_read_n(s, more, more, 1, 0, &n);
+            rret = HANDLE_RLAYER_RETURN(s,
+                s->rrlmethod->read_n(s->rrl, more, more, 1, 0, &n));
             if (rret <= 0)
                 return rret;     /* error or non-blocking io */
         }
@@ -464,10 +515,10 @@ int ssl3_get_record(SSL_CONNECTION *s)
          */
         if (thisrr->rec_version == SSL2_VERSION) {
             thisrr->input =
-                &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]);
+                &(s->rrlmethod->get0_packet(s->rrl)[SSL2_RT_HEADER_LENGTH]);
         } else {
             thisrr->input =
-                &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]);
+                &(s->rrlmethod->get0_packet(s->rrl)[SSL3_RT_HEADER_LENGTH]);
         }
 
         /*
@@ -493,7 +544,7 @@ int ssl3_get_record(SSL_CONNECTION *s)
         num_recs++;
 
         /* we have pulled in a full packet so zero things */
-        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        s->rrlmethod->reset_packet_length(s->rrl);
         RECORD_LAYER_clear_first_record(&s->rlayer);
     } while (num_recs < max_recs
              && thisrr->type == SSL3_RT_APPLICATION_DATA
@@ -1543,7 +1594,7 @@ int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
      * 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 = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]);
+    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
@@ -1624,7 +1675,7 @@ int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
         }
         /* For DTLS we simply ignore bad packets. */
         rr->length = 0;
-        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        s->rrlmethod->reset_packet_length(s->rrl);
         goto end;
     }
     ERR_clear_last_mark();
@@ -1651,7 +1702,7 @@ int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
     if (enc_err == 0) {
         /* decryption failed, silently discard message */
         rr->length = 0;
-        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        s->rrlmethod->reset_packet_length(s->rrl);
         goto end;
     }
 
@@ -1689,7 +1740,7 @@ int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
      */
 
     /* we have pulled in a full packet so zero things */
-    RECORD_LAYER_reset_packet_length(&s->rlayer);
+    s->rrlmethod->reset_packet_length(s->rrl);
 
     /* Mark receipt of record. */
     dtls1_record_bitmap_update(s, bitmap);
@@ -1750,9 +1801,10 @@ int dtls1_get_record(SSL_CONNECTION *s)
 
     /* check if we have the header */
     if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
-        (RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) {
-        rret = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH,
-                           SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1, &n);
+        (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 */
@@ -1760,15 +1812,14 @@ int dtls1_get_record(SSL_CONNECTION *s)
         }
 
         /* this packet contained a partial record, dump it */
-        if (RECORD_LAYER_get_packet_length(&s->rlayer) !=
-            DTLS1_RT_HEADER_LENGTH) {
-            RECORD_LAYER_reset_packet_length(&s->rlayer);
+        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 = RECORD_LAYER_get_packet(&s->rlayer);
+        p = s->rrlmethod->get0_packet(s->rrl);
 
         if (s->msg_callback)
             s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
@@ -1798,7 +1849,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
                 /* unexpected version, silently discard */
                 rr->length = 0;
                 rr->read = 1;
-                RECORD_LAYER_reset_packet_length(&s->rlayer);
+                s->rrlmethod->reset_packet_length(s->rrl);
                 goto again;
             }
         }
@@ -1807,7 +1858,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
             /* wrong version, silently discard record */
             rr->length = 0;
             rr->read = 1;
-            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            s->rrlmethod->reset_packet_length(s->rrl);
             goto again;
         }
 
@@ -1815,7 +1866,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
             /* record too long, silently discard it */
             rr->length = 0;
             rr->read = 1;
-            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            s->rrlmethod->reset_packet_length(s->rrl);
             goto again;
         }
 
@@ -1825,7 +1876,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
             /* record too long, silently discard it */
             rr->length = 0;
             rr->read = 1;
-            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            s->rrlmethod->reset_packet_length(s->rrl);
             goto again;
         }
 
@@ -1835,19 +1886,20 @@ int dtls1_get_record(SSL_CONNECTION *s)
     /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
 
     if (rr->length >
-        RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_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 = ssl3_read_n(s, more, more, 1, 1, &n);
+        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)) {
-                /* ssl3_read_n() called SSLfatal() */
+                /* read_n() called SSLfatal() */
                 return -1;
             }
             rr->length = 0;
             rr->read = 1;
-            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            s->rrlmethod->reset_packet_length(s->rrl);
             goto again;
         }
 
@@ -1863,7 +1915,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
     bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
     if (bitmap == NULL) {
         rr->length = 0;
-        RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
         goto again;             /* get another record */
     }
 #ifndef OPENSSL_NO_SCTP
@@ -1874,7 +1926,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
         if (!dtls1_record_replay_check(s, bitmap)) {
             rr->length = 0;
             rr->read = 1;
-            RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+            s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
             goto again;         /* get another record */
         }
 #ifndef OPENSSL_NO_SCTP
@@ -1903,7 +1955,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
         }
         rr->length = 0;
         rr->read = 1;
-        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        s->rrlmethod->reset_packet_length(s->rrl);
         goto again;
     }
 
@@ -1914,7 +1966,7 @@ int dtls1_get_record(SSL_CONNECTION *s)
         }
         rr->length = 0;
         rr->read = 1;
-        RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+        s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
         goto again;             /* get another record */
     }
 
@@ -1935,9 +1987,9 @@ int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
     memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
     rr->off = off;
 
-    s->rlayer.packet = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
-    s->rlayer.packet_length = DTLS1_RT_HEADER_LENGTH + len;
-    rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH;
+    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) {
index 51fb5687a8d4f23ea0c43b1b162f08e070215fa3..c262eefd19977a8ae6dfb0e790f257785ed21f64 100644 (file)
 
 #include <openssl/bio.h>
 #include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include "internal/e_os.h"
+#include "record.h"
 #include "recordmethod.h"
 
 struct ossl_record_layer_st
 {
-    /* Placeholder until we have real data to store */
-    int dummy;
+    int isdtls;
+    int version;
+    int role;
+    int direction;
+    BIO *bio;
+    /* Types match the equivalent structures in the SSL object */
+    uint64_t options;
+    /*
+     * TODO(RECLAYER): Should we take the opportunity to make this uint64_t
+     * even though upper layer continue to use uint32_t?
+     */
+    uint32_t mode;
+
+    /* read IO goes into here */
+    SSL3_BUFFER rbuf;
+
+    /* used internally to point at a raw packet */
+    unsigned char *packet;
+    size_t packet_length;
+
+    int alert;
+
+    /*
+     * Read as many input bytes as possible (for
+     * non-blocking reads)
+     * TODO(RECLAYER): Why isn't this just an option?
+     */
+    int read_ahead;
 };
 
+static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio);
+
+# define SSL_AD_NO_ALERT    -1
+
+static void rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
+                         const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    ERR_vset_error(ERR_LIB_SSL, reason, fmt, args);
+    va_end(args);
+
+    rl->alert = al;
+}
+
+
+# define RLAYERfatal(rl, al, r) RLAYERfatal_data((rl), (al), (r), NULL)
+# define RLAYERfatal_data                                          \
+    (ERR_new(),                                                    \
+     ERR_set_debug(OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC),      \
+     rlayer_fatal)
+
+static int rlayer_allow_compression(OSSL_RECORD_LAYER *rl)
+{
+    if (rl->options & SSL_OP_NO_COMPRESSION)
+        return 0;
+#if 0
+    /* TODO(RECLAYER): Implement ssl_security inside the record layer */
+    return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL);
+#else
+    return 1;
+#endif
+}
+
+static int rlayer_setup_read_buffer(OSSL_RECORD_LAYER *rl)
+{
+    unsigned char *p;
+    size_t len, align = 0, headerlen;
+    SSL3_BUFFER *b;
+
+    b = &rl->rbuf;
+
+    if (rl->isdtls)
+        headerlen = DTLS1_RT_HEADER_LENGTH;
+    else
+        headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+    align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+    if (b->buf == NULL) {
+        len = SSL3_RT_MAX_PLAIN_LENGTH
+            + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
+#ifndef OPENSSL_NO_COMP
+        if (rlayer_allow_compression(rl))
+            len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+        if (b->default_len > len)
+            len = b->default_len;
+        if ((p = OPENSSL_malloc(len)) == NULL) {
+            /*
+             * We've got a malloc failure, and we're still initialising buffers.
+             * We assume we're so doomed that we won't even be able to send an
+             * alert.
+             */
+            RLAYERfatal(rl, SSL_AD_NO_ALERT, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        b->buf = p;
+        b->len = len;
+    }
+
+    return 1;
+}
+
+static int rlayer_release_read_buffer(OSSL_RECORD_LAYER *rl)
+{
+    SSL3_BUFFER *b;
+
+    b = &rl->rbuf;
+    if (rl->options & SSL_OP_CLEANSE_PLAINTEXT)
+        OPENSSL_cleanse(b->buf, b->len);
+    OPENSSL_free(b->buf);
+    b->buf = NULL;
+    return 1;
+}
+
+/*
+ * Return values are as per SSL_read()
+ */
+static int tls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+                      int clearold, size_t *readbytes)
+{
+    /*
+     * If extend == 0, obtain new n-byte packet; if extend == 1, increase
+     * packet by another n bytes. The packet will be in the sub-array of
+     * s->rlayer.rbuf.buf specified by s->rlayer.packet and
+     * s->rlayer.packet_length. (If s->rlayer.read_ahead is set, 'max' bytes may
+     * be stored in rbuf [plus s->rlayer.packet_length bytes if extend == 1].)
+     * if clearold == 1, move the packet to the start of the buffer; if
+     * clearold == 0 then leave any old packets where they were
+     */
+    size_t len, left, align = 0;
+    unsigned char *pkt;
+    SSL3_BUFFER *rb;
+
+    if (n == 0)
+        return OSSL_RECORD_RETURN_NON_FATAL_ERR;
+
+    rb = &rl->rbuf;
+    if (rb->buf == NULL) {
+        if (!rlayer_setup_read_buffer(rl)) {
+            /* RLAYERfatal() already called */
+            return OSSL_RECORD_RETURN_FATAL;
+        }
+    }
+
+    left = rb->left;
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
+    align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
+    align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
+#endif
+
+    if (!extend) {
+        /* start with empty packet ... */
+        if (left == 0) {
+            rb->offset = align;
+        } else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) {
+            /*
+             * check if next packet length is large enough to justify payload
+             * alignment...
+             */
+            pkt = rb->buf + rb->offset;
+            if (pkt[0] == SSL3_RT_APPLICATION_DATA
+                    && (pkt[3] << 8 | pkt[4]) >= 128) {
+                /*
+                 * Note that even if packet is corrupted and its length field
+                 * is insane, we can only be led to wrong decision about
+                 * whether memmove will occur or not. Header values has no
+                 * effect on memmove arguments and therefore no buffer
+                 * overrun can be triggered.
+                 */
+                memmove(rb->buf + align, pkt, left);
+                rb->offset = align;
+            }
+        }
+        rl->packet = rb->buf + rb->offset;
+        rl->packet_length = 0;
+        /* ... now we can act as if 'extend' was set */
+    }
+
+    len = rl->packet_length;
+    pkt = rb->buf + align;
+    /*
+     * Move any available bytes to front of buffer: 'len' bytes already
+     * pointed to by 'packet', 'left' extra ones at the end
+     */
+    if (rl->packet != pkt && clearold == 1) {
+        memmove(pkt, rl->packet, len + left);
+        rl->packet = pkt;
+        rb->offset = len + align;
+    }
+
+    /*
+     * For DTLS/UDP reads should not span multiple packets because the read
+     * operation returns the whole packet at once (as long as it fits into
+     * the buffer).
+     */
+    if (rl->isdtls) {
+        if (left == 0 && extend)
+            return 0;
+        if (left > 0 && n > left)
+            n = left;
+    }
+
+    /* if there is enough in the buffer from a previous read, take some */
+    if (left >= n) {
+        rl->packet_length += n;
+        rb->left = left - n;
+        rb->offset += n;
+        *readbytes = n;
+        return OSSL_RECORD_RETURN_SUCCESS;
+    }
+
+    /* else we need to read more data */
+
+    if (n > rb->len - rb->offset) {
+        /* does not happen */
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return OSSL_RECORD_RETURN_FATAL;
+    }
+
+    /*
+     * Ktls always reads full records.
+     * Also, we always act like read_ahead is set for DTLS.
+     */
+    if (!BIO_get_ktls_recv(s->rbio) && !rl->read_ahead
+            && !rl->isdtls) {
+        /* ignore max parameter */
+        max = n;
+    } else {
+        if (max < n)
+            max = n;
+        if (max > rb->len - rb->offset)
+            max = rb->len - rb->offset;
+    }
+
+    while (left < n) {
+        size_t bioread = 0;
+        int ret;
+
+        /*
+         * Now we have len+left bytes at the front of s->s3.rbuf.buf and
+         * need to read in more until we have len+n (up to len+max if
+         * possible)
+         */
+
+        clear_sys_error();
+        if (rl->bio != NULL) {
+            ret = BIO_read(rl->bio, pkt + len + left, max - left);
+            if (ret > 0) {
+                bioread = ret;
+                ret = OSSL_RECORD_RETURN_SUCCESS;
+            } else if (BIO_should_retry(rl->bio)) {
+                ret = OSSL_RECORD_RETURN_RETRY;
+            } else if (BIO_eof(rl->bio)) {
+                ret = OSSL_RECORD_RETURN_EOF;
+            } else {
+                ret = OSSL_RECORD_RETURN_FATAL;
+            }
+        } else {
+            RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
+            ret = OSSL_RECORD_RETURN_FATAL;
+        }
+
+        if (ret <= OSSL_RECORD_RETURN_RETRY) {
+            rb->left = left;
+            if (rl->mode & SSL_MODE_RELEASE_BUFFERS && !rl->isdtls)
+                if (len + left == 0)
+                    rlayer_release_read_buffer(rl);
+            return ret;
+        }
+        left += bioread;
+        /*
+         * reads should *never* span multiple packets for DTLS because the
+         * underlying transport protocol is message oriented as opposed to
+         * byte oriented as in the TLS case.
+         */
+        if (rl->isdtls) {
+            if (n > left)
+                n = left;       /* makes the while condition false */
+        }
+    }
+
+    /* done reading, now the book-keeping */
+    rb->offset += n;
+    rb->left = left - n;
+    rl->packet_length += n;
+    *readbytes = n;
+    return OSSL_RECORD_RETURN_SUCCESS;
+}
+
 static OSSL_RECORD_LAYER *tls_new_record_layer(int vers, int role, int direction,
                                                int level, unsigned char *secret,
                                                size_t secretlen, SSL_CIPHER *c,
                                                BIO *transport, BIO_ADDR *local,
                                                BIO_ADDR *peer,
-                                               OSSL_PARAM *settings,
-                                               OSSL_PARAM *options)
+                                               const OSSL_PARAM *settings,
+                                               const OSSL_PARAM *options)
 {
     OSSL_RECORD_LAYER *rl = OPENSSL_zalloc(sizeof(*rl));
+    const OSSL_PARAM *p;
+
+    if (rl == NULL) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    if (transport != NULL && !BIO_up_ref(transport)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    p = OSSL_PARAM_locate_const(options, OSSL_LIBSSL_RECORD_LAYER_PARAM_OPTIONS);
+    if (p != NULL && !OSSL_PARAM_get_uint64(p, &rl->options)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_FAILED_TO_GET_PARAMETER);
+        goto err;
+    }
+
+    p = OSSL_PARAM_locate_const(options, OSSL_LIBSSL_RECORD_LAYER_PARAM_MODE);
+    if (p != NULL && !OSSL_PARAM_get_uint32(p, &rl->mode)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_FAILED_TO_GET_PARAMETER);
+        goto err;
+    }
+
+
+    p = OSSL_PARAM_locate_const(options, OSSL_LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD);
+    if (p != NULL && !OSSL_PARAM_get_int(p, &rl->read_ahead)) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_FAILED_TO_GET_PARAMETER);
+        goto err;
+    }
+
+    rl->version = vers;
+    rl->role = role;
+    rl->direction = direction;
+    if (!tls_set1_bio(rl, transport))
+        goto err;
+
+    return rl;
+ err:
+    OPENSSL_free(rl);
+    return NULL;
+}
+
+static OSSL_RECORD_LAYER *dtls_new_record_layer(int vers, int role, int direction,
+                                                int level, unsigned char *secret,
+                                                size_t secretlen, SSL_CIPHER *c,
+                                                BIO *transport, BIO_ADDR *local,
+                                                BIO_ADDR *peer,
+                                                const OSSL_PARAM *settings,
+                                                const OSSL_PARAM *options)
+{
+    OSSL_RECORD_LAYER *rl = tls_new_record_layer(vers, role, direction, level,
+                                                 secret, secretlen, c, transport,
+                                                 local, peer, settings, options);
+
+    if (rl == NULL)
+        return NULL;
+
+    rl->isdtls = 1;
 
     return rl;
 }
 
 static void tls_free(OSSL_RECORD_LAYER *rl)
 {
+    BIO_free(rl->bio);
     OPENSSL_free(rl);
 }
 
@@ -97,6 +451,48 @@ static void tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
     return;
 }
 
+static int tls_get_alert_code(OSSL_RECORD_LAYER *rl)
+{
+    return rl->alert;
+}
+
+static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio)
+{
+    if (bio != NULL && !BIO_up_ref(bio))
+        return 0;
+    BIO_free(rl->bio);
+    rl->bio = bio;
+
+    return 1;
+}
+
+static SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl)
+{
+    return &rl->rbuf;
+}
+
+static unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl)
+{
+    return rl->packet;
+}
+
+static void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet,
+                            size_t packetlen)
+{
+    rl->packet = packet;
+    rl->packet_length = packetlen;
+}
+
+static size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl)
+{
+    return rl->packet_length;
+}
+
+static void tls_reset_packet_length(OSSL_RECORD_LAYER *rl)
+{
+    rl->packet_length = 0;
+}
+
 const OSSL_RECORD_METHOD ossl_tls_record_method = {
     tls_new_record_layer,
     tls_free,
@@ -110,5 +506,49 @@ const OSSL_RECORD_METHOD ossl_tls_record_method = {
     tls_write_records,
     tls_retry_write_records,
     tls_read_record,
-    tls_release_record
+    tls_release_record,
+    tls_get_alert_code,
+    tls_set1_bio,
+
+    /*
+     * 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_read_n,
+    tls_get0_rbuf,
+    tls_get0_packet,
+    tls_set0_packet,
+    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,
+
+    /*
+     * 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_read_n,
+    tls_get0_rbuf,
+    tls_get0_packet,
+    tls_set0_packet,
+    tls_get_packet_length,
+    tls_reset_packet_length
 };
index 75d720f990dc3b808065cbd8aa626985dd0e5fb0..a202cf92991573b6fdde2d07d9276e983be5d586 100644 (file)
@@ -170,6 +170,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "extra data in message"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXT_LENGTH_MISMATCH),
     "ext length mismatch"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_GET_PARAMETER),
+    "failed to get parameter"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_INIT_ASYNC),
     "failed to init async"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FRAGMENTED_CLIENT_HELLO),
@@ -342,6 +344,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_BIO_NOT_SET), "read bio not set"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_TIMEOUT_EXPIRED),
     "read timeout expired"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_LAYER_FAILURE),
+    "record layer failure"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_LENGTH_MISMATCH),
     "record length mismatch"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_TOO_SMALL), "record too small"},
index 1a7242aee22134e07d1732a7c6aa2f1aab1f95b6..c61ad65063d9978455089fae67862da7c06b9172 100644 (file)
@@ -885,6 +885,22 @@ SSL *ossl_ssl_connection_new(SSL_CTX *ctx)
         goto err;
 #endif
 
+    /*
+     * TODO(RECLAYER): This assignment should probably initialy come from the
+     * SSL_METHOD, and potentially be updated later. For now though we just
+     * assign it.
+     */
+    if (SSL_CONNECTION_IS_DTLS(s))
+        s->rrlmethod = &ossl_dtls_record_method;
+    else
+        s->rrlmethod = &ossl_tls_record_method;
+
+    /* BIO is NULL initially. It will get updated later */
+    s->rrl = s->rrlmethod->new_record_layer(s->version, s->server,
+                                            OSSL_RECORD_DIRECTION_READ,
+                                            0, 0, 0, NULL, NULL, NULL,
+                                            NULL, NULL, NULL);
+
     return ssl;
  err:
     SSL_free(ssl);
@@ -1422,6 +1438,7 @@ void SSL_set0_rbio(SSL *s, BIO *rbio)
 
     BIO_free_all(sc->rbio);
     sc->rbio = rbio;
+    sc->rrlmethod->set1_bio(sc->rrl, sc->rbio);
 }
 
 void SSL_set0_wbio(SSL *s, BIO *wbio)
index 76719f9e2c83f3a43b17410e27df38ac36055953..3af39c8cc7031536d5e3e5d40b2d2bab3e4b064f 100644 (file)
@@ -28,6 +28,7 @@
 # include <openssl/symhacks.h>
 # include <openssl/ct.h>
 # include "record/record.h"
+# include "record/recordmethod.h"
 # include "statem/statem.h"
 # include "internal/packet.h"
 # include "internal/dane.h"
@@ -1762,7 +1763,16 @@ struct ssl_connection_st {
      * basis, depending on the chosen cipher.
      */
     int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
+
+    /* Old RECORD_LAYER structure  - to be removed eventually */
     RECORD_LAYER rlayer;
+
+    /* New read direciton OSSL_RECORD_LAYER - to replace rlayer above */
+    const OSSL_RECORD_METHOD *rrlmethod;
+    /* The read direction record layer */
+    OSSL_RECORD_LAYER *rrl;
+
+
     /* Default password callback. */
     pem_password_cb *default_passwd_callback;
     /* Default password callback user data. */
index 5c5b760e38214c5e4cce9064e145cc1442a2eaed..6715ac6a3254903b586d9cbd737058c24c991b20 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-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
index f54aaf7188278267219de5765f321c023af717d9..b422dd76c169102abec1b31b73304535848b31a9 100644 (file)
@@ -172,6 +172,27 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
     BIO *bio;
 #endif
 
+#if 0
+    if ((which & SSL3_CC_READ) != 0) {
+        /*
+        * TODO(RECLAYER): This is probably not the right place to free this. The
+        * OSSL_RECORD_METHOD might have changed since we created the rl object.
+        * We should free it at the point that we update the OSSL_RECORD_METHOD.
+        * But for now this will do.
+        */
+        s->rrlmethod->free(s->rrl);
+        s->rrl = s->rrlmethod->new_record_layer(s->version, s->server,
+                                                OSSL_RECORD_DIRECTION_READ,
+                                                0, 0, 0, NULL, s->rbio, NULL,
+                                                NULL, NULL, NULL);
+    }
+#endif
+
+    if (s->rrl == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
     c = s->s3.tmp.new_sym_enc;
     m = s->s3.tmp.new_hash;
     mac_type = s->s3.tmp.new_mac_pkey_type;