Remove unneccesary KTLS code from non-KTLS specific files
authorMatt Caswell <matt@openssl.org>
Thu, 12 May 2022 16:21:25 +0000 (17:21 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 18 Aug 2022 15:38:12 +0000 (16:38 +0100)
This also moves other protocol specific code to the protocol specific
files.

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

12 files changed:
ssl/record/methods/ktls_meth.c
ssl/record/methods/recmethod_local.h
ssl/record/methods/ssl3_meth.c
ssl/record/methods/tls13_meth.c
ssl/record/methods/tls1_meth.c
ssl/record/methods/tls_common.c
ssl/record/methods/tlsany_meth.c
ssl/record/rec_layer_s3.c
ssl/record/recordmethod.h
ssl/statem/statem.h
ssl/statem/statem_lib.c
ssl/statem/statem_srvr.c

index b6c8aeeb5710a75f50ec61b13a495e7ef5628d65..3a9c836077c40bc90dfce43fa45b378fa2e86347 100644 (file)
@@ -408,6 +408,35 @@ static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
     return OSSL_RECORD_RETURN_SUCCESS;
 }
 
+static int ktls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+                       int clearold, size_t *readbytes)
+{
+    int ret;
+
+    ret = tls_default_read_n(rl, n, max, extend, clearold, readbytes);
+
+    if (ret < OSSL_RECORD_RETURN_RETRY) {
+        switch (errno) {
+        case EBADMSG:
+            RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC,
+                        SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+            break;
+        case EMSGSIZE:
+            RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
+                        SSL_R_PACKET_LENGTH_TOO_LONG);
+            break;
+        case EINVAL:
+            RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+                        SSL_R_WRONG_VERSION_NUMBER);
+            break;
+        default:
+            break;
+        }
+    }
+
+    return ret;
+}
+
 static int ktls_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs,
                        int sending, SSL_MAC_BUF *mac, size_t macsize,
                        /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
@@ -415,8 +444,108 @@ static int ktls_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs
     return 1;
 }
 
-struct record_functions_st ossl_ktls_funcs = {
+static int ktls_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
+{
+    if (rec->rec_version != TLS1_2_VERSION) {
+        RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_WRONG_VERSION_NUMBER);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec,
+                                    SSL_CONNECTION *s)
+{
+    if (rl->version == TLS1_3_VERSION)
+        return tls13_common_post_process_record(rl, rec, s);
+
+    return 1;
+}
+
+static struct record_functions_st ossl_ktls_funcs = {
     ktls_set_crypto_state,
+    ktls_read_n,
     ktls_cipher,
-    NULL
+    NULL,
+    tls_default_set_protocol_version,
+    ktls_validate_record_header,
+    ktls_post_process_record
+};
+
+static int
+ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+                      int role, int direction, int level, unsigned char *key,
+                      size_t keylen, unsigned char *iv, size_t ivlen,
+                      unsigned char *mackey, size_t mackeylen,
+                      const EVP_CIPHER *ciph, size_t taglen,
+                      /* TODO(RECLAYER): This probably should not be an int */
+                      int mactype,
+                      const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+                      BIO_ADDR *local, BIO_ADDR *peer,
+                      const OSSL_PARAM *settings, const OSSL_PARAM *options,
+                      OSSL_RECORD_LAYER **retrl,
+                      /* TODO(RECLAYER): Remove me */
+                      SSL_CONNECTION *s)
+{
+    int ret;
+
+    ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
+                                   key, keylen, iv, ivlen, mackey, mackeylen,
+                                   ciph, taglen, mactype, md, comp, transport,
+                                   local, peer, settings, options, retrl, s);
+
+    if (ret != OSSL_RECORD_RETURN_SUCCESS)
+        return ret;
+
+    (*retrl)->funcs = &ossl_ktls_funcs;
+
+    ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
+                                            ivlen, mackey, mackeylen, ciph,
+                                            taglen, mactype, md, comp, s);
+
+    if (ret != OSSL_RECORD_RETURN_SUCCESS) {
+        OPENSSL_free(*retrl);
+        *retrl = NULL;
+    } else {
+        /*
+         * With KTLS we always try and read as much as possible and fill the
+         * buffer
+         */
+        (*retrl)->read_ahead = 1;
+    }
+    return ret;
+}
+
+const OSSL_RECORD_METHOD ossl_ktls_record_method = {
+    ktls_new_record_layer,
+    tls_free,
+    tls_reset,
+    tls_unprocessed_read_pending,
+    tls_processed_read_pending,
+    tls_app_data_pending,
+    tls_write_pending,
+    tls_get_max_record_len,
+    tls_get_max_records,
+    tls_write_records,
+    tls_retry_write_records,
+    tls_read_record,
+    tls_release_record,
+    tls_get_alert_code,
+    tls_set1_bio,
+    tls_set_protocol_version,
+    tls_set_plain_alerts,
+    tls_set_first_handshake,
+
+    /*
+     * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
+     * during the record layer refactoring. They need to be removed before the
+     * refactor is complete.
+     */
+    tls_default_read_n,
+    tls_get0_rbuf,
+    tls_get0_packet,
+    tls_set0_packet,
+    tls_get_packet_length,
+    tls_reset_packet_length
 };
index 2e21a25b87272a9ff1b40d3f7e846dea3ebb0650..ef124c8237c366c4f36b7d8e559d66330263c209 100644 (file)
@@ -33,6 +33,9 @@ struct record_functions_st
                             const SSL_COMP *comp,
                             /* TODO(RECLAYER): Remove me */
                             SSL_CONNECTION *s);
+
+    int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+                  int clearold, size_t *readbytes);
     /*
      * Returns:
      *    0: if the record is publicly invalid, or an internal error, or AEAD
@@ -45,6 +48,16 @@ struct record_functions_st
     /* Returns 1 for success or 0 for error */
     int (*mac)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
                int sending, /* TODO(RECLAYER): Remove me */SSL_CONNECTION *ssl);
+
+    /* Return 1 for success or 0 for error */
+    int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version);
+
+    /* Return 1 for success or 0 for error */
+    int (*validate_record_header)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
+
+    /* Return 1 for success or 0 for error */
+    int (*post_process_record)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec,
+                               /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s);
 };
 
 struct ossl_record_layer_st
@@ -78,9 +91,6 @@ struct ossl_record_layer_st
     /* The number of records that have been released via tls_release_record */
     size_t num_released;
 
-    /* Set to true if this is the first record in a connection */
-    unsigned int is_first_record;
-
     /* where we are when reading */
     int rstate;
 
@@ -102,18 +112,28 @@ struct ossl_record_layer_st
 
     /* cryptographic state */
     EVP_CIPHER_CTX *enc_read_ctx;
-    /* TLSv1.3 static read IV */
-    unsigned char read_iv[EVP_MAX_IV_LENGTH];
+
     /* used for mac generation */
     EVP_MD_CTX *read_hash;
     /* uncompress */
     COMP_CTX *expand;
 
+    /* Set to 1 if this is the first handshake. 0 otherwise */
+    int is_first_handshake;
+
     /* Only used by SSLv3 */
     unsigned char mac_secret[EVP_MAX_MD_SIZE];
 
-    /* TLSv1.3 static IV */
+    /* TLSv1.3 fields */
+    /* static IV */
     unsigned char iv[EVP_MAX_IV_LENGTH];
+    /* static read IV */
+    unsigned char read_iv[EVP_MAX_IV_LENGTH];
+    int allow_plain_alerts;
+
+    /* TLS "any" fields */
+    /* Set to true if this is the first record in a connection */
+    unsigned int is_first_record;
 
     size_t taglen;
 
@@ -125,7 +145,6 @@ struct ossl_record_layer_st
 extern struct record_functions_st ssl_3_0_funcs;
 extern struct record_functions_st tls_1_funcs;
 extern struct record_functions_st tls_1_3_funcs;
-extern struct record_functions_st ossl_ktls_funcs;
 extern struct record_functions_st tls_any_funcs;
 
 void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
@@ -153,3 +172,56 @@ __owur int ssl3_cbc_digest_record(const EVP_MD *md,
                                   size_t data_plus_mac_plus_padding_size,
                                   const unsigned char *mac_secret,
                                   size_t mac_secret_length, char is_sslv3);
+
+int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+                       int clearold, size_t *readbytes);
+
+int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
+int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *re);
+int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, SSL_CONNECTION *s);
+int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec,
+                                     SSL_CONNECTION *s);
+
+int
+tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+                         int role, int direction, int level, unsigned char *key,
+                         size_t keylen, unsigned char *iv, size_t ivlen,
+                         unsigned char *mackey, size_t mackeylen,
+                         const EVP_CIPHER *ciph, size_t taglen,
+                         /* TODO(RECLAYER): This probably should not be an int */
+                         int mactype,
+                         const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+                         BIO_ADDR *local, BIO_ADDR *peer,
+                         const OSSL_PARAM *settings, const OSSL_PARAM *options,
+                         OSSL_RECORD_LAYER **retrl,
+                         /* TODO(RECLAYER): Remove me */
+                         SSL_CONNECTION *s);
+void tls_free(OSSL_RECORD_LAYER *rl);
+int tls_reset(OSSL_RECORD_LAYER *rl);
+int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl);
+int tls_processed_read_pending(OSSL_RECORD_LAYER *rl);
+size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl);
+int tls_write_pending(OSSL_RECORD_LAYER *rl);
+size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl);
+size_t tls_get_max_records(OSSL_RECORD_LAYER *rl);
+int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE **templates,
+                      size_t numtempl,  size_t allowance, size_t *sent);
+int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance,
+                            size_t *sent);
+int tls_get_alert_code(OSSL_RECORD_LAYER *rl);
+int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio);
+int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,  int *rversion,
+                    int *type, unsigned char **data, size_t *datalen,
+                    uint16_t *epoch, unsigned char *seq_num,
+                    /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s);
+int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle);
+int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
+int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
+void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow);
+void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first);
+SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl);
+unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl);
+void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet,
+                     size_t packetlen);
+size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl);
+void tls_reset_packet_length(OSSL_RECORD_LAYER *rl);
index 15f5d02c4174a5a9a03e7ba1d7b3972430f323d5..fa0e1c28a83932826d9f6bc3f32a68f39badbde4 100644 (file)
@@ -315,6 +315,10 @@ static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
 
 struct record_functions_st ssl_3_0_funcs = {
     ssl3_set_crypto_state,
+    tls_default_read_n,
     ssl3_cipher,
-    ssl3_mac
+    ssl3_mac,
+    tls_default_set_protocol_version,
+    tls_default_validate_record_header,
+    tls_default_post_process_record
 };
index bc8d5f0a03b87dd7944059df7b52e46cfd3b2f59..3ea0f5fec34ce4e4fafc7ca1ce880535114b4f79 100644 (file)
@@ -191,8 +191,71 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
     return 1;
 }
 
+static int tls13_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
+{
+    if (rec->type != SSL3_RT_APPLICATION_DATA
+            && (rec->type != SSL3_RT_CHANGE_CIPHER_SPEC
+                || !rl->is_first_handshake)
+            && (rec->type != SSL3_RT_ALERT || !rl->allow_plain_alerts)) {
+        RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+        return 0;
+    }
+
+    if (rec->rec_version != TLS1_2_VERSION) {
+        RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_WRONG_VERSION_NUMBER);
+        return 0;
+    }
+
+    if (rec->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) {
+        RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
+                    SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+        return 0;
+    }
+    return 1;
+}
+
+static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec,
+                                     SSL_CONNECTION *s)
+{
+    /* Skip this if we've received a plaintext alert */
+    if (rec->type != SSL3_RT_ALERT) {
+        size_t end;
+
+        if (rec->length == 0
+                || rec->type != SSL3_RT_APPLICATION_DATA) {
+            RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE,
+                        SSL_R_BAD_RECORD_TYPE);
+            return 0;
+        }
+
+        /* Strip trailing padding */
+        for (end = rec->length - 1; end > 0 && rec->data[end] == 0;
+                end--)
+            continue;
+
+        rec->length = end;
+        rec->type = rec->data[end];
+    }
+
+    if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+        RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+        return 0;
+    }
+
+    if (!tls13_common_post_process_record(rl, rec, s)) {
+        /* RLAYERfatal already called */
+        return 0;
+    }
+
+    return 1;
+}
+
 struct record_functions_st tls_1_3_funcs = {
     tls13_set_crypto_state,
+    tls_default_read_n,
     tls13_cipher,
-    NULL
+    NULL,
+    tls_default_set_protocol_version,
+    tls13_validate_record_header,
+    tls13_post_process_record
 };
index 5c0a8f2cc3dcaa36137ef07192a29cd6c73152f0..2e60778b72ee14e2c20cf48f13168ac193c1d7fd 100644 (file)
@@ -591,6 +591,10 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
 /* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */
 struct record_functions_st tls_1_funcs = {
     tls1_set_crypto_state,
+    tls_default_read_n,
     tls1_cipher,
-    tls1_mac
+    tls1_mac,
+    tls_default_set_protocol_version,
+    tls_default_validate_record_header,
+    tls_default_post_process_record
 };
index 6189ab3a96cf741edb234b969d497de778252bf9..fa6551dffb5385c579cef58b159bdf5e484a78d0 100644 (file)
@@ -89,8 +89,6 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
     }
 }
 
-static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio);
-
 static int rlayer_allow_compression(OSSL_RECORD_LAYER *rl)
 {
     if (rl->options & SSL_OP_NO_COMPRESSION)
@@ -157,7 +155,7 @@ static int rlayer_release_read_buffer(OSSL_RECORD_LAYER *rl)
     return 1;
 }
 
-static void tls_reset_packet_length(OSSL_RECORD_LAYER *rl)
+void tls_reset_packet_length(OSSL_RECORD_LAYER *rl)
 {
     rl->packet_length = 0;
 }
@@ -165,8 +163,8 @@ static void tls_reset_packet_length(OSSL_RECORD_LAYER *rl)
 /*
  * 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)
+int tls_default_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
@@ -272,12 +270,8 @@ static int tls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
         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(rl->bio) && !rl->read_ahead
-            && !rl->isdtls) {
+    /* We always act like read_ahead is set for DTLS */
+    if (!rl->read_ahead && !rl->isdtls) {
         /* ignore max parameter */
         max = n;
     } else {
@@ -419,7 +413,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
     int imac_size;
     size_t num_recs = 0, max_recs, j;
     PACKET pkt, sslv2pkt;
-    int using_ktls;
     SSL_MAC_BUF *macbufs = NULL;
     int ret = OSSL_RECORD_RETURN_FATAL;
     SSL *ssl = SSL_CONNECTION_GET_SSL(s);
@@ -438,12 +431,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
         max_recs = 1;
     sess = s->session;
 
-    /*
-     * KTLS reads full records. If there is any data left,
-     * then it is from before enabling ktls.
-     */
-    using_ktls = BIO_get_ktls_recv(rl->bio) && SSL3_BUFFER_get_left(rbuf) == 0;
-
     do {
         thisrr = &rr[num_recs];
 
@@ -453,33 +440,13 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
             size_t sslv2len;
             unsigned int type;
 
-            rret = tls_read_n(rl, SSL3_RT_HEADER_LENGTH,
-                              SSL3_BUFFER_get_len(rbuf), 0,
-                              num_recs == 0 ? 1 : 0, &n);
-
-            if (rret < OSSL_RECORD_RETURN_SUCCESS) {
-#ifndef OPENSSL_NO_KTLS
-                if (!BIO_get_ktls_recv(rl->bio) || rret == 0)
-                    return rret;     /* error or non-blocking */
-                switch (errno) {
-                case EBADMSG:
-                    RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC,
-                                SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-                    break;
-                case EMSGSIZE:
-                    RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
-                                SSL_R_PACKET_LENGTH_TOO_LONG);
-                    break;
-                case EINVAL:
-                    RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
-                                SSL_R_WRONG_VERSION_NUMBER);
-                    break;
-                default:
-                    break;
-                }
-#endif
-                return rret;
-            }
+            rret = rl->funcs->read_n(rl, SSL3_RT_HEADER_LENGTH,
+                                     SSL3_BUFFER_get_len(rbuf), 0,
+                                     num_recs == 0 ? 1 : 0, &n);
+
+            if (rret < OSSL_RECORD_RETURN_SUCCESS)
+                return rret; /* error or non-blocking */
+
             rl->rstate = SSL_ST_READ_BODY;
 
             p = rl->packet;
@@ -520,11 +487,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
                                 SSL_R_PACKET_LENGTH_TOO_LONG);
                     return OSSL_RECORD_RETURN_FATAL;
                 }
-
-                if (thisrr->length < MIN_SSL2_RECORD_LEN) {
-                    RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
-                    return OSSL_RECORD_RETURN_FATAL;
-                }
             } else {
                 /* SSLv3+ style record */
 
@@ -545,89 +507,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
                     s->msg_callback(0, version, SSL3_RT_HEADER, p, 5, ssl,
                                     s->msg_callback_arg);
 
-                /*
-                 * Lets check version. In TLSv1.3 we only check this field
-                 * when encryption is occurring (see later check). For the
-                 * ServerHello after an HRR we haven't actually selected TLSv1.3
-                 * yet, but we still treat it as TLSv1.3, so we must check for
-                 * that explicitly
-                 */
-                if (!s->first_packet && !SSL_CONNECTION_IS_TLS13(s)
-                        && s->hello_retry_request != SSL_HRR_PENDING
-                        && version != (unsigned int)s->version) {
-                    if ((s->version & 0xFF00) == (version & 0xFF00)
-                        && !s->enc_write_ctx && !s->write_hash) {
-                        if (thisrr->type == SSL3_RT_ALERT) {
-                            /*
-                             * The record is using an incorrect version number,
-                             * but what we've got appears to be an alert. We
-                             * haven't read the body yet to check whether its a
-                             * fatal or not - but chances are it is. We probably
-                             * shouldn't send a fatal alert back. We'll just
-                             * end.
-                             */
-                            RLAYERfatal(rl, SSL_AD_NO_ALERT,
-                                        SSL_R_WRONG_VERSION_NUMBER);
-                            return OSSL_RECORD_RETURN_FATAL;
-                        }
-                        /*
-                         * Send back error using their minor version number :-)
-                         */
-                        s->version = (unsigned short)version;
-                    }
-                    RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
-                                SSL_R_WRONG_VERSION_NUMBER);
-                    return OSSL_RECORD_RETURN_FATAL;
-                }
-
-                if ((version >> 8) != SSL3_VERSION_MAJOR) {
-                    if (rl->is_first_record) {
-                        /* Go back to start of packet, look at the five bytes
-                         * that we have. */
-                        p = rl->packet;
-                        if (HAS_PREFIX((char *)p, "GET ") ||
-                            HAS_PREFIX((char *)p, "POST ") ||
-                            HAS_PREFIX((char *)p, "HEAD ") ||
-                            HAS_PREFIX((char *)p, "PUT ")) {
-                            RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
-                            return OSSL_RECORD_RETURN_FATAL;
-                        } else if (HAS_PREFIX((char *)p, "CONNE")) {
-                            RLAYERfatal(rl, SSL_AD_NO_ALERT,
-                                        SSL_R_HTTPS_PROXY_REQUEST);
-                            return OSSL_RECORD_RETURN_FATAL;
-                        }
-
-                        /* Doesn't look like TLS - don't send an alert */
-                        RLAYERfatal(rl, SSL_AD_NO_ALERT,
-                                    SSL_R_WRONG_VERSION_NUMBER);
-                        return OSSL_RECORD_RETURN_FATAL;
-                    } else {
-                        RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
-                                    SSL_R_WRONG_VERSION_NUMBER);
-                        return OSSL_RECORD_RETURN_FATAL;
-                    }
-                }
-
-                if (SSL_CONNECTION_IS_TLS13(s)
-                        && rl->enc_read_ctx != NULL
-                        && !using_ktls) {
-                    if (thisrr->type != SSL3_RT_APPLICATION_DATA
-                            && (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
-                                || !SSL_IS_FIRST_HANDSHAKE(s))
-                            && (thisrr->type != SSL3_RT_ALERT
-                                || s->statem.enc_read_state
-                                   != ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
-                        RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE,
-                                    SSL_R_BAD_RECORD_TYPE);
-                        return OSSL_RECORD_RETURN_FATAL;
-                    }
-                    if (thisrr->rec_version != TLS1_2_VERSION) {
-                        RLAYERfatal(rl, SSL_AD_DECODE_ERROR,
-                                    SSL_R_WRONG_VERSION_NUMBER);
-                        return OSSL_RECORD_RETURN_FATAL;
-                    }
-                }
-
                 if (thisrr->length >
                     SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
                     RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
@@ -636,42 +515,12 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
                 }
             }
 
-            /* now rl->rstate == SSL_ST_READ_BODY */
-        }
-
-        if (SSL_CONNECTION_IS_TLS13(s)) {
-            size_t len = SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH;
-
-            /* KTLS strips the inner record type. */
-            if (using_ktls)
-                len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
-
-            if (thisrr->length > len) {
-                RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
-                            SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+            if (!rl->funcs->validate_record_header(rl, thisrr)) {
+                /* RLAYERfatal already called */
                 return OSSL_RECORD_RETURN_FATAL;
             }
-        } else {
-            size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
 
-#ifndef OPENSSL_NO_COMP
-            /*
-             * If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH
-             * does not include the compression overhead anyway.
-             */
-            if (s->expand == NULL)
-                len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
-#endif
-
-            /* KTLS may use all of the buffer */
-            if (using_ktls)
-                len = SSL3_BUFFER_get_left(rbuf);
-
-            if (thisrr->length > len) {
-                RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
-                            SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
-                return OSSL_RECORD_RETURN_FATAL;
-            }
+            /* now rl->rstate == SSL_ST_READ_BODY */
         }
 
         /*
@@ -688,7 +537,7 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
         if (more > 0) {
             /* now rl->packet_length == SSL3_RT_HEADER_LENGTH */
 
-            rret = tls_read_n(rl, more, more, 1, 0, &n);
+            rret = rl->funcs->read_n(rl, more, more, 1, 0, &n);
             if (rret < OSSL_RECORD_RETURN_SUCCESS)
                 return rret;     /* error or non-blocking io */
         }
@@ -742,7 +591,7 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
     if (num_recs == 1
             && thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC
             && (SSL_CONNECTION_IS_TLS13(s) || s->hello_retry_request != SSL_HRR_NONE)
-            && SSL_IS_FIRST_HANDSHAKE(s)) {
+            && rl->is_first_handshake) {
         /*
          * CCS messages must be exactly 1 byte long, containing the value 0x01
          */
@@ -769,9 +618,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
         return OSSL_RECORD_RETURN_SUCCESS;
     }
 
-    if (using_ktls)
-        goto skip_decryption;
-
     if (rl->read_hash != NULL) {
         const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(rl->read_hash);
 
@@ -908,85 +754,11 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
         goto end;
     }
 
- skip_decryption:
-
     for (j = 0; j < num_recs; j++) {
         thisrr = &rr[j];
 
-        /* thisrr->length is now just compressed */
-        if (s->expand != NULL) {
-            if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
-                RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
-                            SSL_R_COMPRESSED_LENGTH_TOO_LONG);
-                goto end;
-            }
-            if (!ssl3_do_uncompress(s, thisrr)) {
-                RLAYERfatal(rl, SSL_AD_DECOMPRESSION_FAILURE,
-                            SSL_R_BAD_DECOMPRESSION);
-                goto end;
-            }
-        }
-
-        if (SSL_CONNECTION_IS_TLS13(s)
-                && rl->enc_read_ctx != NULL
-                && thisrr->type != SSL3_RT_ALERT) {
-            /*
-             * The following logic are irrelevant in KTLS: the kernel provides
-             * unprotected record and thus record type represent the actual
-             * content type, and padding is already removed and thisrr->type and
-             * thisrr->length should have the correct values.
-             */
-            if (!using_ktls) {
-                size_t end;
-
-                if (thisrr->length == 0
-                        || thisrr->type != SSL3_RT_APPLICATION_DATA) {
-                    RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE,
-                                SSL_R_BAD_RECORD_TYPE);
-                    goto end;
-                }
-
-                /* Strip trailing padding */
-                for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0;
-                     end--)
-                    continue;
-
-                thisrr->length = end;
-                thisrr->type = thisrr->data[end];
-            }
-            if (thisrr->type != SSL3_RT_APPLICATION_DATA
-                    && thisrr->type != SSL3_RT_ALERT
-                    && thisrr->type != SSL3_RT_HANDSHAKE) {
-                RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
-                goto end;
-            }
-            if (s->msg_callback)
-                s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
-                                &thisrr->type, 1, ssl, s->msg_callback_arg);
-        }
-
-        /*
-         * TLSv1.3 alert and handshake records are required to be non-zero in
-         * length.
-         */
-        if (SSL_CONNECTION_IS_TLS13(s)
-                && (thisrr->type == SSL3_RT_HANDSHAKE
-                    || thisrr->type == SSL3_RT_ALERT)
-                && thisrr->length == 0) {
-            RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH);
-            goto end;
-        }
-
-        /*
-         * Usually thisrr->length is the length of a single record, but when
-         * KTLS handles the decryption, thisrr->length may be larger than
-         * SSL3_RT_MAX_PLAIN_LENGTH because the kernel may have coalesced
-         * multiple records.
-         * Therefore we have to rely on KTLS to check the plaintext length
-         * limit in the kernel.
-         */
-        if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH && !using_ktls) {
-            RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+        if (!rl->funcs->post_process_record(rl, thisrr, s)) {
+            /* RLAYERfatal already called */
             goto end;
         }
 
@@ -1045,11 +817,118 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
     return ret;
 }
 
-static int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,
-                           int *rversion, int *type, unsigned char **data,
-                           size_t *datalen, uint16_t *epoch,
-                           unsigned char *seq_num,
-                           /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
+/* Shared by ssl3_meth and tls1_meth */
+int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
+{
+    size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
+
+    if (rec->rec_version != rl->version) {
+        RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, SSL_R_WRONG_VERSION_NUMBER);
+        return 0;
+    }
+
+#ifndef OPENSSL_NO_COMP
+    /*
+        * If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH
+        * does not include the compression overhead anyway.
+        */
+    if (rl->expand == NULL)
+        len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+
+    if (rec->length > len) {
+        RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
+                    SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int tls_do_uncompress(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
+{
+#ifndef OPENSSL_NO_COMP
+    int i;
+
+    if (rec->comp == NULL) {
+        rec->comp = (unsigned char *)
+            OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
+    }
+    if (rec->comp == NULL)
+        return 0;
+
+    i = COMP_expand_block(rl->expand, rec->comp,
+                          SSL3_RT_MAX_PLAIN_LENGTH, rec->data, (int)rec->length);
+    if (i < 0)
+        return 0;
+    else
+        rec->length = i;
+    rec->data = rec->comp;
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+/* Shared by tlsany_meth, ssl3_meth and tls1_meth */
+int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, SSL_CONNECTION *s)
+{
+    if (rl->expand != NULL) {
+        if (rec->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+            RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
+                        SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+            return 0;
+        }
+        if (!tls_do_uncompress(rl, rec)) {
+            RLAYERfatal(rl, SSL_AD_DECOMPRESSION_FAILURE,
+                        SSL_R_BAD_DECOMPRESSION);
+            return 0;
+        }
+    }
+
+    if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+        RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+        return 0;
+    }
+
+    return 1;
+}
+
+/* Shared by tls13_meth and ktls_meth */
+int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec,
+                                     SSL_CONNECTION *s)
+{
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+    if (rec->type != SSL3_RT_APPLICATION_DATA
+            && rec->type != SSL3_RT_ALERT
+            && rec->type != SSL3_RT_HANDSHAKE) {
+        RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+        return 0;
+    }
+
+    if (s->msg_callback)
+        s->msg_callback(0, rl->version, SSL3_RT_INNER_CONTENT_TYPE,
+                        &rec->type, 1, ssl, s->msg_callback_arg);
+
+    /*
+     * TLSv1.3 alert and handshake records are required to be non-zero in
+     * length.
+     */
+    if ((rec->type == SSL3_RT_HANDSHAKE
+                || rec->type == SSL3_RT_ALERT)
+            && rec->length == 0) {
+        RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH);
+        return 0;
+    }
+
+    return 1;
+}
+
+int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,  int *rversion,
+                    int *type, unsigned char **data, size_t *datalen,
+                    uint16_t *epoch, unsigned char *seq_num,
+                    /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
 {
     SSL3_RECORD *rec;
 
@@ -1088,7 +967,7 @@ static int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,
     return OSSL_RECORD_RETURN_SUCCESS;
 }
 
-static int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
+int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
 {
     if (!ossl_assert(rl->num_released < rl->curr_rec)
             || !ossl_assert(rechandle == &rl->rrec[rl->num_released])) {
@@ -1102,7 +981,7 @@ static int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
     return OSSL_RECORD_RETURN_SUCCESS;
 }
 
-static int
+int
 tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
                          int role, int direction, int level, unsigned char *key,
                          size_t keylen, unsigned char *iv, size_t ivlen,
@@ -1173,7 +1052,7 @@ tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
     rl->role = role;
     rl->direction = direction;
 
-    if (level == 0)
+    if (level == OSSL_RECORD_PROTECTION_LEVEL_NONE)
         rl->is_first_record = 1;
 
     if (!tls_set1_bio(rl, transport))
@@ -1245,39 +1124,23 @@ tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
     return ret;
 }
 
-static int
-dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
-                      int role, int direction, int level, unsigned char *key,
-                      size_t keylen, unsigned char *iv, size_t ivlen,
-                      unsigned char *mackey, size_t mackeylen,
-                      const EVP_CIPHER *ciph, size_t taglen,
-                      /* TODO(RECLAYER): This probably should not be an int */
-                      int mactype,
-                      const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
-                      BIO_ADDR *local, BIO_ADDR *peer,
-                      const OSSL_PARAM *settings, const OSSL_PARAM *options,
-                      OSSL_RECORD_LAYER **retrl,
-                      /* TODO(RECLAYER): Remove me */
-                      SSL_CONNECTION *s)
+/* TODO(RECLAYER): Temporary funcs */
+static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
 {
-    int ret;
-
-    ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
-                                   key, keylen, iv, ivlen, mackey, mackeylen,
-                                   ciph, taglen, mactype, md, comp, transport,
-                                   local, peer, settings, options, retrl, s);
-
-    if (ret != OSSL_RECORD_RETURN_SUCCESS)
-        return ret;
-
-    (*retrl)->isdtls = 1;
-
-    return OSSL_RECORD_RETURN_SUCCESS;
+    rl->version = version;
+    return 1;
 }
+static struct record_functions_st dtls_funcs = {
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    dtls_set_protocol_version,
+    NULL
+};
 
-#ifndef OPENSSL_NO_KTLS
 static int
-ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
                       int role, int direction, int level, unsigned char *key,
                       size_t keylen, unsigned char *iv, size_t ivlen,
                       unsigned char *mackey, size_t mackeylen,
@@ -1293,6 +1156,7 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
 {
     int ret;
 
+
     ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
                                    key, keylen, iv, ivlen, mackey, mackeylen,
                                    ciph, taglen, mactype, md, comp, transport,
@@ -1301,83 +1165,74 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
     if (ret != OSSL_RECORD_RETURN_SUCCESS)
         return ret;
 
-    (*retrl)->funcs = &ossl_ktls_funcs;
-
-    ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
-                                            ivlen, mackey, mackeylen, ciph,
-                                            taglen, mactype, md, comp, s);
+    (*retrl)->isdtls = 1;
+    (*retrl)->funcs = &dtls_funcs;
 
-    if (ret != OSSL_RECORD_RETURN_SUCCESS) {
-        OPENSSL_free(*retrl);
-        *retrl = NULL;
-    }
-    return ret;
+    return OSSL_RECORD_RETURN_SUCCESS;
 }
-#endif
 
-static void tls_free(OSSL_RECORD_LAYER *rl)
+void tls_free(OSSL_RECORD_LAYER *rl)
 {
     /* TODO(RECLAYER): Cleanse sensitive fields */
     BIO_free(rl->bio);
     OPENSSL_free(rl);
 }
 
-static int tls_reset(OSSL_RECORD_LAYER *rl)
+int tls_reset(OSSL_RECORD_LAYER *rl)
 {
     memset(rl, 0, sizeof(*rl));
     return 1;
 }
 
-static int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl)
+int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl)
 {
     return SSL3_BUFFER_get_left(&rl->rbuf) != 0;;
 }
 
-static int tls_processed_read_pending(OSSL_RECORD_LAYER *rl)
+int tls_processed_read_pending(OSSL_RECORD_LAYER *rl)
 {
     return rl->curr_rec < rl->num_recs;
 }
 
-static size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl)
+size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl)
 {
     return 0;
 }
 
-static int tls_write_pending(OSSL_RECORD_LAYER *rl)
+int tls_write_pending(OSSL_RECORD_LAYER *rl)
 {
     return 0;
 }
 
-static size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl)
+size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl)
 {
     return 0;
 }
 
-static size_t tls_get_max_records(OSSL_RECORD_LAYER *rl)
+size_t tls_get_max_records(OSSL_RECORD_LAYER *rl)
 {
     return 0;
 }
 
-static int tls_write_records(OSSL_RECORD_LAYER *rl,
-                             OSSL_RECORD_TEMPLATE **templates, size_t numtempl,
-                             size_t allowance, size_t *sent)
+int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE **templates,
+                      size_t numtempl, size_t allowance, size_t *sent)
 {
     return 0;
 }
 
-static int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance,
-                                   size_t *sent)
+int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance,
+                            size_t *sent)
 {
     return 0;
 }
 
 
-static int tls_get_alert_code(OSSL_RECORD_LAYER *rl)
+int tls_get_alert_code(OSSL_RECORD_LAYER *rl)
 {
     return rl->alert;
 }
 
-static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio)
+int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio)
 {
     if (bio != NULL && !BIO_up_ref(bio))
         return 0;
@@ -1387,24 +1242,48 @@ static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio)
     return 1;
 }
 
-static SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl)
+/* Shared by most methods except tlsany_meth */
+int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
+{
+    if (rl->version != version)
+        return 0;
+
+    return 1;
+}
+
+int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
+{
+    return rl->funcs->set_protocol_version(rl, version);
+}
+
+void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow)
+{
+    rl->allow_plain_alerts = allow;
+}
+
+void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first)
+{
+    rl->is_first_handshake = first;
+}
+
+SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl)
 {
     return &rl->rbuf;
 }
 
-static unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl)
+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)
+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)
+size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl)
 {
     return rl->packet_length;
 }
@@ -1425,51 +1304,22 @@ const OSSL_RECORD_METHOD ossl_tls_record_method = {
     tls_release_record,
     tls_get_alert_code,
     tls_set1_bio,
+    tls_set_protocol_version,
+    tls_set_plain_alerts,
+    tls_set_first_handshake,
 
     /*
      * 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
-};
-
-#ifndef OPENSSL_NO_KTLS
-const OSSL_RECORD_METHOD ossl_ktls_record_method = {
-    ktls_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_default_read_n,
     tls_get0_rbuf,
     tls_get0_packet,
     tls_set0_packet,
     tls_get_packet_length,
     tls_reset_packet_length
 };
-#endif
 
 const OSSL_RECORD_METHOD ossl_dtls_record_method = {
     dtls_new_record_layer,
@@ -1487,13 +1337,16 @@ const OSSL_RECORD_METHOD ossl_dtls_record_method = {
     tls_release_record,
     tls_get_alert_code,
     tls_set1_bio,
+    tls_set_protocol_version,
+    NULL,
+    tls_set_first_handshake,
 
     /*
      * 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_default_read_n,
     tls_get0_rbuf,
     tls_get0_packet,
     tls_set0_packet,
index cde57a41cc05d761010199782d76b09feccf5659..12443261ea1ef7d1acd6720a6dbcc96b88fdd292 100644 (file)
@@ -43,8 +43,113 @@ static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs,
     return 1;
 }
 
+static int tls_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
+{
+    if (rec->rec_version == SSL2_VERSION) {
+        /* SSLv2 format ClientHello */
+        if (!ossl_assert(rl->version == TLS_ANY_VERSION)) {
+            RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
+        if (rec->length < MIN_SSL2_RECORD_LEN) {
+            RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
+            return 0;
+        }
+    } else {
+        if (rl->version == TLS_ANY_VERSION) {
+            if ((rec->rec_version >> 8) != SSL3_VERSION_MAJOR) {
+                if (rl->is_first_record) {
+                    unsigned char *p;
+
+                    /*
+                     * Go back to start of packet, look at the five bytes that
+                     * we have.
+                     */
+                    p = rl->packet;
+                    if (HAS_PREFIX((char *)p, "GET ") ||
+                        HAS_PREFIX((char *)p, "POST ") ||
+                        HAS_PREFIX((char *)p, "HEAD ") ||
+                        HAS_PREFIX((char *)p, "PUT ")) {
+                        RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
+                        return 0;
+                    } else if (HAS_PREFIX((char *)p, "CONNE")) {
+                        RLAYERfatal(rl, SSL_AD_NO_ALERT,
+                                    SSL_R_HTTPS_PROXY_REQUEST);
+                        return 0;
+                    }
+
+                    /* Doesn't look like TLS - don't send an alert */
+                    RLAYERfatal(rl, SSL_AD_NO_ALERT,
+                                SSL_R_WRONG_VERSION_NUMBER);
+                    return 0;
+                } else {
+                    RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+                                SSL_R_WRONG_VERSION_NUMBER);
+                    return 0;
+                }
+            }
+        } else if (rl->version == TLS1_3_VERSION) {
+            /*
+             * In this case we know we are going to negotiate TLSv1.3, but we've
+             * had an HRR, so we haven't actually done so yet. Nonetheless we
+             * still expect the record version to be TLSv1.2 as per a normal
+             * TLSv1.3 record
+             */
+            if (rec->rec_version != TLS1_2_VERSION) {
+                RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+                            SSL_R_WRONG_VERSION_NUMBER);
+                return 0;
+            }
+        } else if (rec->rec_version != rl->version) {
+            if ((rl->version & 0xFF00) == (rec->rec_version & 0xFF00)) {
+                if (rec->type == SSL3_RT_ALERT) {
+                    /*
+                     * The record is using an incorrect version number,
+                     * but what we've got appears to be an alert. We
+                     * haven't read the body yet to check whether its a
+                     * fatal or not - but chances are it is. We probably
+                     * shouldn't send a fatal alert back. We'll just
+                     * end.
+                     */
+                    RLAYERfatal(rl, SSL_AD_NO_ALERT,
+                                SSL_R_WRONG_VERSION_NUMBER);
+                    return 0;
+                }
+                /* Send back error using their minor version number */
+                rl->version = (unsigned short)rec->rec_version;
+            }
+            RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+                        SSL_R_WRONG_VERSION_NUMBER);
+            return 0;
+        }
+    }
+    if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+        /*
+         * We use SSL_R_DATA_LENGTH_TOO_LONG instead of
+         * SSL_R_ENCRYPTED_LENGTH_TOO_LONG here because we are the "any" method
+         * and we know that we are dealing with plaintext data
+         */
+        RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+        return 0;
+    }
+    return 1;
+}
+
+static int tls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
+{
+    if (rl->version != TLS_ANY_VERSION && rl->version != vers)
+        return 0;
+    rl->version = vers;
+
+    return 1;
+}
+
 struct record_functions_st tls_any_funcs = {
     tls_any_set_crypto_state,
+    tls_default_read_n,
     tls_any_cipher,
-    NULL
+    NULL,
+    tls_any_set_protocol_version,
+    tls_validate_record_header,
+    tls_default_post_process_record
 };
index deb108cfc77d947ae01b7244408c75fa76bb3921..c5f4591391005144116f501a2d0f0eb739e432d5 100644 (file)
@@ -1783,6 +1783,8 @@ static int ssl_post_record_layer_select(SSL_CONNECTION *s)
         SSL_set_options(ssl, SSL_OP_NO_RENEGOTIATION);
     }
 #endif
+    if (SSL_IS_FIRST_HANDSHAKE(s) && s->rrlmethod->set_first_handshake != NULL)
+        s->rrlmethod->set_first_handshake(s->rrl, 1);
     return 1;
 }
 
index 43562e36b4def569ea84c71bb3dc5833d0f97740..8f025cc7859d3a48ddfc4f6f79300eafc0b8da3d 100644 (file)
@@ -284,6 +284,22 @@ struct ossl_record_method_st {
      */
     int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio);
 
+    /* Called when protocol negotiation selects a protocol version to use */
+    int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version);
+
+    /*
+     * Whether we are allowed to receive unencrypted alerts, even if we might
+     * otherwise expect encrypted records. Ignored by protocol versions where
+     * this isn't relevant
+     */
+    void (*set_plain_alerts)(OSSL_RECORD_LAYER *rl, int allow);
+
+    /*
+     * Called immediately after creation of the recory layer if we are in a
+     * first handshake. Also called at the end of the first handshake
+     */
+    void (*set_first_handshake)(OSSL_RECORD_LAYER *rl, int first);
+
     /*
      * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
      * during the record layer refactoring. They need to be removed before the
index b904ee50c80e6f80dcaff9b8ede067310bb3e6f8..7dbe71ed7d48a5cf0a92a22d72f4b1d7c41ffca9 100644 (file)
@@ -80,13 +80,6 @@ typedef enum {
     ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
 } ENC_WRITE_STATES;
 
-typedef enum {
-    /* The enc_read_ctx can be used normally */
-    ENC_READ_STATE_VALID,
-    /* We may receive encrypted or plaintext alerts */
-    ENC_READ_STATE_ALLOW_PLAIN_ALERTS
-} ENC_READ_STATES;
-
 /*****************************************************************************
  *                                                                           *
  * This structure should be considered "opaque" to anything outside of the   *
@@ -117,7 +110,6 @@ struct ossl_statem_st {
     unsigned int no_cert_verify;
     int use_timer;
     ENC_WRITE_STATES enc_write_state;
-    ENC_READ_STATES enc_read_state;
 };
 typedef struct ossl_statem_st OSSL_STATEM;
 
index 70d194ff815f01f1aada6b2c50c08b812f7bebdb..d1614a56d886cf9feb2b10363ad2e362c2ad8b04 100644 (file)
@@ -794,16 +794,18 @@ MSG_PROCESS_RETURN tls_process_finished(SSL_CONNECTION *s, PACKET *pkt)
 {
     size_t md_len;
     SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+    int was_first = SSL_IS_FIRST_HANDSHAKE(s);
 
 
     /* This is a real handshake so make sure we clean it up at the end */
     if (s->server) {
         /*
         * To get this far we must have read encrypted data from the client. We
-        * no longer tolerate unencrypted alerts. This value is ignored if less
-        * than TLSv1.3
+        * no longer tolerate unencrypted alerts. This is ignored if less than
+        * TLSv1.3
         */
-        s->statem.enc_read_state = ENC_READ_STATE_VALID;
+        if (s->rrlmethod->set_plain_alerts != NULL)
+            s->rrlmethod->set_plain_alerts(s->rrl, 0);
         if (s->post_handshake_auth != SSL_PHA_REQUESTED)
             s->statem.cleanuphand = 1;
         if (SSL_CONNECTION_IS_TLS13(s)
@@ -893,6 +895,11 @@ MSG_PROCESS_RETURN tls_process_finished(SSL_CONNECTION *s, PACKET *pkt)
         }
     }
 
+    if (was_first
+            && !SSL_IS_FIRST_HANDSHAKE(s)
+            && s->rrlmethod->set_first_handshake != NULL)
+        s->rrlmethod->set_first_handshake(s->rrl, 0);
+
     return MSG_PROCESS_FINISHED_READING;
 }
 
@@ -1873,6 +1880,9 @@ int ssl_choose_server_version(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello,
             check_for_downgrade(s, best_vers, dgrd);
             s->version = best_vers;
             ssl->method = best_method;
+            if (!s->rrlmethod->set_protocol_version(s->rrl, best_vers))
+                return ERR_R_INTERNAL_ERROR;
+
             return 0;
         }
         return SSL_R_UNSUPPORTED_PROTOCOL;
@@ -1900,6 +1910,9 @@ int ssl_choose_server_version(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello,
             check_for_downgrade(s, vent->version, dgrd);
             s->version = vent->version;
             ssl->method = method;
+            if (!s->rrlmethod->set_protocol_version(s->rrl, s->version))
+                return ERR_R_INTERNAL_ERROR;
+
             return 0;
         }
         disabled = 1;
@@ -1959,6 +1972,10 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version,
          * versions they don't want.  If not, then easy to fix, just return
          * ssl_method_error(s, s->method)
          */
+        if (!s->rrlmethod->set_protocol_version(s->rrl, s->version)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
         return 1;
     case TLS_ANY_VERSION:
         table = tls_version_table;
@@ -2019,6 +2036,10 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version,
             continue;
 
         ssl->method = vent->cmeth();
+        if (!s->rrlmethod->set_protocol_version(s->rrl, s->version)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
         return 1;
     }
 
index db6d40682c0363e18e90073f4afe536e875b7d76..2ed19231abdc1e142cf9cc142fc323fef5d46fc2 100644 (file)
@@ -914,7 +914,8 @@ WORK_STATE ossl_statem_server_post_work(SSL_CONNECTION *s, WORK_STATE wst)
              * is an unencrypted alert, an encrypted alert, or an encrypted
              * handshake message. We temporarily tolerate unencrypted alerts.
              */
-            s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS;
+            if (s->rrlmethod->set_plain_alerts != NULL)
+                s->rrlmethod->set_plain_alerts(s->rrl, 1);
             break;
         }
 
@@ -3455,10 +3456,10 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
 
     /*
      * To get this far we must have read encrypted data from the client. We no
-     * longer tolerate unencrypted alerts. This value is ignored if less than
-     * TLSv1.3
+     * longer tolerate unencrypted alerts. This is ignored if less than TLSv1.3
      */
-    s->statem.enc_read_state = ENC_READ_STATE_VALID;
+    if (s->rrlmethod->set_plain_alerts != NULL)
+        s->rrlmethod->set_plain_alerts(s->rrl, 0);
 
     if ((sk = sk_X509_new_null()) == NULL) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);