Split out non record layer functions out of s3_pkt.c and d1_pkt.c into
[openssl.git] / ssl / s3_pkt.c
index 07adf0f25a084c79dfb90ee6ca39b8db28d0ee4a..16a6db42ccd016335c8111f688194d74fe88e249 100644 (file)
 # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
 #endif
 
-static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
-                         unsigned int len, int create_empty_fragment);
-static int ssl3_get_record(SSL *s);
-
 int ssl3_read_n(SSL *s, int n, int max, int extend)
 {
     /*
      * 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->s3->rbuf.buf specified by s->packet and s->packet_length. (If
-     * s->read_ahead is set, 'max' bytes may be stored in rbuf [plus
+     * s->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus
      * s->packet_length bytes if extend == 1].)
      */
     int i, len, left;
@@ -153,7 +149,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     if (n <= 0)
         return n;
 
-    rb = &(s->s3->rbuf);
+    rb = RECORD_LAYER_get_rbuf(&s->rlayer);
     if (rb->buf == NULL)
         if (!ssl3_setup_read_buffer(s))
             return -1;
@@ -232,7 +228,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     }
 
     /* We always act like read_ahead is set for DTLS */
-    if (!s->read_ahead && !SSL_IS_DTLS(s))
+    if (!RECORD_LAYER_get_read_ahead(&s->rlayer) && !SSL_IS_DTLS(s))
         /* ignore max parameter */
         max = n;
     else {
@@ -285,357 +281,6 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     return (n);
 }
 
-/*
- * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
- * will be processed per call to ssl3_get_record. Without this limit an
- * attacker could send empty records at a faster rate than we can process and
- * cause ssl3_get_record to loop forever.
- */
-#define MAX_EMPTY_RECORDS 32
-
-/*-
- * Call this to get a new input record.
- * It will return <= 0 if more data is needed, normally due to an error
- * or non-blocking IO.
- * When it finishes, one packet has been decoded and can be found in
- * ssl->s3->rrec.type    - is the type of record
- * ssl->s3->rrec.data,   - data
- * ssl->s3->rrec.length, - number of bytes
- */
-/* used only by ssl3_read_bytes */
-static int ssl3_get_record(SSL *s)
-{
-    int ssl_major, ssl_minor, al;
-    int enc_err, n, i, ret = -1;
-    SSL3_RECORD *rr;
-    SSL_SESSION *sess;
-    unsigned char *p;
-    unsigned char md[EVP_MAX_MD_SIZE];
-    short version;
-    unsigned mac_size;
-    size_t extra;
-    unsigned empty_record_count = 0;
-
-    rr = &(s->s3->rrec);
-    sess = s->session;
-
-    if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
-        extra = SSL3_RT_MAX_EXTRA;
-    else
-        extra = 0;
-    if (extra && !s->s3->init_extra) {
-        /*
-         * An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER set after
-         * ssl3_setup_buffers() was done
-         */
-        SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
-        return -1;
-    }
-
- again:
-    /* check if we have the header */
-    if ((s->rstate != SSL_ST_READ_BODY) ||
-        (s->packet_length < SSL3_RT_HEADER_LENGTH)) {
-        n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
-        if (n <= 0)
-            return (n);         /* error or non-blocking */
-        s->rstate = SSL_ST_READ_BODY;
-
-        p = s->packet;
-        if (s->msg_callback)
-            s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
-                            s->msg_callback_arg);
-
-        /* Pull apart the header into the SSL3_RECORD */
-        rr->type = *(p++);
-        ssl_major = *(p++);
-        ssl_minor = *(p++);
-        version = (ssl_major << 8) | ssl_minor;
-        n2s(p, rr->length);
-#if 0
-        fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length);
-#endif
-
-        /* Lets check version */
-        if (!s->first_packet) {
-            if (version != s->version) {
-                SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
-                if ((s->version & 0xFF00) == (version & 0xFF00)
-                    && !s->enc_write_ctx && !s->write_hash)
-                    /*
-                     * Send back error using their minor version number :-)
-                     */
-                    s->version = (unsigned short)version;
-                al = SSL_AD_PROTOCOL_VERSION;
-                goto f_err;
-            }
-        }
-
-        if ((version >> 8) != SSL3_VERSION_MAJOR) {
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
-            goto err;
-        }
-
-        if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) {
-            al = SSL_AD_RECORD_OVERFLOW;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG);
-            goto f_err;
-        }
-
-        /* now s->rstate == SSL_ST_READ_BODY */
-    }
-
-    /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
-
-    if (rr->length > s->packet_length - SSL3_RT_HEADER_LENGTH) {
-        /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
-        i = rr->length;
-        n = ssl3_read_n(s, i, i, 1);
-        if (n <= 0)
-            return (n);         /* error or non-blocking io */
-        /*
-         * now n == rr->length, and s->packet_length == SSL3_RT_HEADER_LENGTH
-         * + rr->length
-         */
-    }
-
-    s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */
-
-    /*
-     * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
-     * and we have that many bytes in s->packet
-     */
-    rr->input = &(s->packet[SSL3_RT_HEADER_LENGTH]);
-
-    /*
-     * ok, we can now read from 's->packet' data into 'rr' rr->input points
-     * at rr->length bytes, which need to be copied into rr->data by either
-     * the decryption or by the decompression When the data is 'copied' into
-     * the rr->data buffer, rr->input will be pointed at the new buffer
-     */
-
-    /*
-     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
-     * bytes of encrypted compressed stuff.
-     */
-
-    /* check is not needed I believe */
-    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    /* decrypt in place in 'rr->input' */
-    rr->data = rr->input;
-    rr->orig_len = rr->length;
-    /*
-     * If in encrypt-then-mac mode calculate mac from encrypted record. All
-     * the details below are public so no timing details can leak.
-     */
-    if (SSL_USE_ETM(s) && s->read_hash) {
-        unsigned char *mac;
-        mac_size = EVP_MD_CTX_size(s->read_hash);
-        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-        if (rr->length < mac_size) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-        rr->length -= mac_size;
-        mac = rr->data + rr->length;
-        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
-        if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
-            al = SSL_AD_BAD_RECORD_MAC;
-            SSLerr(SSL_F_SSL3_GET_RECORD,
-                   SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-            goto f_err;
-        }
-    }
-
-    enc_err = s->method->ssl3_enc->enc(s, 0);
-    /*-
-     * enc_err is:
-     *    0: (in non-constant time) if the record is publically invalid.
-     *    1: if the padding is valid
-     *    -1: if the padding is invalid
-     */
-    if (enc_err == 0) {
-        al = SSL_AD_DECRYPTION_FAILED;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
-        goto f_err;
-    }
-#ifdef TLS_DEBUG
-    printf("dec %d\n", rr->length);
-    {
-        unsigned int z;
-        for (z = 0; z < rr->length; z++)
-            printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
-    }
-    printf("\n");
-#endif
-
-    /* r->length is now the compressed data plus mac */
-    if ((sess != NULL) &&
-        (s->enc_read_ctx != NULL) &&
-        (EVP_MD_CTX_md(s->read_hash) != NULL) && !SSL_USE_ETM(s)) {
-        /* s->read_hash != NULL => mac_size != -1 */
-        unsigned char *mac = NULL;
-        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-        mac_size = EVP_MD_CTX_size(s->read_hash);
-        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-
-        /*
-         * orig_len is the length of the record before any padding was
-         * removed. This is public information, as is the MAC in use,
-         * therefore we can safely process the record in a different amount
-         * of time if it's too short to possibly contain a MAC.
-         */
-        if (rr->orig_len < mac_size ||
-            /* CBC records must have a padding length byte too. */
-            (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-             rr->orig_len < mac_size + 1)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
-            /*
-             * We update the length so that the TLS header bytes can be
-             * constructed correctly but we need to extract the MAC in
-             * constant time from within the record, without leaking the
-             * contents of the padding bytes.
-             */
-            mac = mac_tmp;
-            ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
-            rr->length -= mac_size;
-        } else {
-            /*
-             * In this case there's no padding, so |rec->orig_len| equals
-             * |rec->length| and we checked that there's enough bytes for
-             * |mac_size| above.
-             */
-            rr->length -= mac_size;
-            mac = &rr->data[rr->length];
-        }
-
-        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
-        if (i < 0 || mac == NULL
-            || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
-            enc_err = -1;
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra + mac_size)
-            enc_err = -1;
-    }
-
-    if (enc_err < 0) {
-        /*
-         * A separate 'decryption_failed' alert was introduced with TLS 1.0,
-         * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
-         * failure is directly visible from the ciphertext anyway, we should
-         * not reveal which kind of error occurred -- this might become
-         * visible to an attacker (e.g. via a logfile)
-         */
-        al = SSL_AD_BAD_RECORD_MAC;
-        SSLerr(SSL_F_SSL3_GET_RECORD,
-               SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-        goto f_err;
-    }
-
-    /* r->length is now just compressed */
-    if (s->expand != NULL) {
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) {
-            al = SSL_AD_RECORD_OVERFLOW;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
-            goto f_err;
-        }
-        if (!ssl3_do_uncompress(s)) {
-            al = SSL_AD_DECOMPRESSION_FAILURE;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION);
-            goto f_err;
-        }
-    }
-
-    if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    rr->off = 0;
-    /*-
-     * So at this point the following is true
-     * ssl->s3->rrec.type   is the type of record
-     * ssl->s3->rrec.length == number of bytes in record
-     * ssl->s3->rrec.off    == offset to first valid byte
-     * ssl->s3->rrec.data   == where to take bytes from, increment
-     *                         after use :-).
-     */
-
-    /* we have pulled in a full packet so zero things */
-    s->packet_length = 0;
-
-    /* just read a 0 length packet */
-    if (rr->length == 0) {
-        empty_record_count++;
-        if (empty_record_count > MAX_EMPTY_RECORDS) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL);
-            goto f_err;
-        }
-        goto again;
-    }
-#if 0
-    fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type,
-            rr->length);
-#endif
-
-    return (1);
-
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
-    return (ret);
-}
-
-int ssl3_do_uncompress(SSL *ssl)
-{
-#ifndef OPENSSL_NO_COMP
-    int i;
-    SSL3_RECORD *rr;
-
-    rr = &(ssl->s3->rrec);
-    i = COMP_expand_block(ssl->expand, rr->comp,
-                          SSL3_RT_MAX_PLAIN_LENGTH, rr->data,
-                          (int)rr->length);
-    if (i < 0)
-        return (0);
-    else
-        rr->length = i;
-    rr->data = rr->comp;
-#endif
-    return (1);
-}
-
-int ssl3_do_compress(SSL *ssl)
-{
-#ifndef OPENSSL_NO_COMP
-    int i;
-    SSL3_RECORD *wr;
-
-    wr = &(ssl->s3->wrec);
-    i = COMP_compress_block(ssl->compress, wr->data,
-                            SSL3_RT_MAX_COMPRESSED_LENGTH,
-                            wr->input, (int)wr->length);
-    if (i < 0)
-        return (0);
-    else
-        wr->length = i;
-
-    wr->input = wr->data;
-#endif
-    return (1);
-}
 
 /*
  * Call this to write data in records of type 'type' It will return <= 0 if
@@ -649,7 +294,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
 #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
     unsigned int max_send_fragment;
 #endif
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = RECORD_LAYER_get_wbuf(&s->rlayer);
     int i;
     unsigned int u_len = (unsigned int)len;
 
@@ -734,6 +379,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
                 packlen *= 4;
 
             wb->buf = OPENSSL_malloc(packlen);
+            if(!wb->buf) {
+                SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_MALLOC_FAILURE);
+                return -1;
+            }
             wb->len = packlen;
         } else if (tot == len) { /* done? */
             OPENSSL_free(wb->buf); /* free jumbo buffer */
@@ -807,7 +456,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
 
             i = ssl3_write_pending(s, type, &buf[tot], nw);
             if (i <= 0) {
-                if (i < 0) {
+                if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) {
                     OPENSSL_free(wb->buf);
                     wb->buf = NULL;
                 }
@@ -866,8 +515,8 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
     }
 }
 
-static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
-                         unsigned int len, int create_empty_fragment)
+int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+                  unsigned int len, int create_empty_fragment)
 {
     unsigned char *p, *plen;
     int i, mac_size, clear = 0;
@@ -875,7 +524,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     int eivlen;
     long align = 0;
     SSL3_RECORD *wr;
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = RECORD_LAYER_get_wbuf(&s->rlayer);
     SSL_SESSION *sess;
 
     /*
@@ -900,17 +549,13 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     if (len == 0 && !create_empty_fragment)
         return 0;
 
-    wr = &(s->s3->wrec);
+    wr = RECORD_LAYER_get_wrec(&s->rlayer);
     sess = s->session;
 
     if ((sess == NULL) ||
         (s->enc_write_ctx == NULL) ||
         (EVP_MD_CTX_md(s->write_hash) == NULL)) {
-#if 1
         clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */
-#else
-        clear = 1;
-#endif
         mac_size = 0;
     } else {
         mac_size = EVP_MD_CTX_size(s->write_hash);
@@ -918,60 +563,6 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
             goto err;
     }
 
-#if 0 && !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-    if (type == SSL3_RT_APPLICATION_DATA && s->compress == NULL &&
-        !SSL_USE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
-        EVP_CIPHER_flags(s->enc_write_ctx->cipher) &
-        EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
-        do {
-            unsigned char aad[13];
-            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param =
-                { NULL, aad, sizeof(aad), 0 };
-            int packlen;
-
-            memcpy(aad, s->s3->write_sequence, 8);
-            aad[8] = type;
-            aad[9] = (unsigned char)(s->version >> 8);
-            aad[10] = (unsigned char)(s->version);
-            aad[11] = (unsigned char)(len >> 8);
-            aad[12] = (unsigned char)len;
-            packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
-                                          EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
-                                          sizeof(mb_param), &mb_param);
-
-            if (packlen == 0 || packlen > wb->len)
-                break;
-
-            mb_param.out = wb->buf;
-            mb_param.inp = buf;
-            mb_param.len = len;
-            EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
-                                EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
-                                sizeof(mb_param), &mb_param);
-
-            s->s3->write_sequence[7] += mb_param.interleave;
-            if (s->s3->write_sequence[7] < mb_param.interleave) {
-                int j = 6;
-                while (j >= 0 && (++s->s3->write_sequence[j--]) == 0) ;
-            }
-
-            wb->offset = 0;
-            wb->left = packlen;
-
-            /*
-             * memorize arguments so that ssl3_write_pending can detect bad
-             * write retries later
-             */
-            s->s3->wpend_tot = len;
-            s->s3->wpend_buf = buf;
-            s->s3->wpend_type = type;
-            s->s3->wpend_ret = len;
-
-            /* we now just need to write the buffer */
-            return ssl3_write_pending(s, type, buf, len);
-        } while (0);
-#endif
-
     /*
      * 'create_empty_fragment' is true only when this function calls itself
      */
@@ -1158,7 +749,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                        unsigned int len)
 {
     int i;
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = RECORD_LAYER_get_wbuf(&s->rlayer);
 
 /* XXXX */
     if ((s->s3->wpend_tot > (int)len)
@@ -1235,9 +826,11 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     SSL3_RECORD *rr;
     void (*cb) (const SSL *ssl, int type2, int val) = NULL;
 
-    if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+    if (!SSL3_BUFFER_is_initialised(RECORD_LAYER_get_rbuf(&s->rlayer))) {
+        /* Not initialized yet */
         if (!ssl3_setup_read_buffer(s))
             return (-1);
+    }
 
     if ((type && (type != SSL3_RT_APPLICATION_DATA)
          && (type != SSL3_RT_HANDSHAKE)) || (peek
@@ -1291,7 +884,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
      * s->s3->rrec.off,     - offset into 'data' for next read
      * s->s3->rrec.length,  - number of bytes.
      */
-    rr = &(s->s3->rrec);
+    rr = RECORD_LAYER_get_rrec(&s->rlayer);
 
     /* get new packet if necessary */
     if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) {
@@ -1349,7 +942,8 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                 s->rstate = SSL_ST_READ_HEADER;
                 rr->off = 0;
                 if (s->mode & SSL_MODE_RELEASE_BUFFERS
-                    && s->s3->rbuf.left == 0)
+                    && SSL3_BUFFER_get_left(
+                        RECORD_LAYER_get_rbuf(&s->rlayer)) == 0)
                     ssl3_release_read_buffer(s);
             }
         }
@@ -1381,7 +975,10 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         }
 #ifndef OPENSSL_NO_HEARTBEATS
         else if (rr->type == TLS1_RT_HEARTBEAT) {
-            tls1_process_heartbeat(s);
+            /* We can ignore 0 return values */
+            if(tls1_process_heartbeat(s) < 0) {
+                return -1;
+            }
 
             /* Exit and notify application to read again */
             rr->length = 0;
@@ -1449,7 +1046,9 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                 }
 
                 if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-                    if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+                    if (SSL3_BUFFER_get_left(
+                        RECORD_LAYER_get_rbuf(&s->rlayer)) == 0) {
+                        /* no read-ahead left? */
                         BIO *bio;
                         /*
                          * In the case where we try to read application data,
@@ -1512,7 +1111,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             cb(s, SSL_CB_READ_ALERT, j);
         }
 
-        if (alert_level == 1) { /* warning */
+        if (alert_level == SSL3_AL_WARNING) {
             s->s3->warn_alert = alert_descr;
             if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
                 s->shutdown |= SSL_RECEIVED_SHUTDOWN;
@@ -1535,7 +1134,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME)
                 return (0);
 #endif
-        } else if (alert_level == 2) { /* fatal */
+        } else if (alert_level == SSL3_AL_FATAL) {
             char tmp[16];
 
             s->rwstate = SSL_NOTHING;
@@ -1608,15 +1207,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake) {
         if (((s->state & SSL_ST_MASK) == SSL_ST_OK) &&
             !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
-#if 0                           /* worked only because C operator preferences
-                                 * are not as expected (and because this is
-                                 * not really needed for clients except for
-                                 * detecting protocol violations): */
-            s->state = SSL_ST_BEFORE | (s->server)
-                ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
-#else
             s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
-#endif
             s->renegotiate = 1;
             s->new_session = 1;
         }
@@ -1629,7 +1220,8 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         }
 
         if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-            if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+            if (SSL3_BUFFER_get_left(RECORD_LAYER_get_rbuf(&s->rlayer)) == 0) {
+                /* no read-ahead left? */
                 BIO *bio;
                 /*
                  * In the case where we try to read application data, but we
@@ -1649,7 +1241,6 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
 
     switch (rr->type) {
     default:
-#ifndef OPENSSL_NO_TLS
         /*
          * TLS up to v1.1 just ignores unknown message types: TLS v1.2 give
          * an unexpected message alert.
@@ -1658,7 +1249,6 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             rr->length = 0;
             goto start;
         }
-#endif
         al = SSL_AD_UNEXPECTED_MESSAGE;
         SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
         goto f_err;
@@ -1707,113 +1297,4 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     return (-1);
 }
 
-int ssl3_do_change_cipher_spec(SSL *s)
-{
-    int i;
-    const char *sender;
-    int slen;
-
-    if (s->state & SSL_ST_ACCEPT)
-        i = SSL3_CHANGE_CIPHER_SERVER_READ;
-    else
-        i = SSL3_CHANGE_CIPHER_CLIENT_READ;
-
-    if (s->s3->tmp.key_block == NULL) {
-        if (s->session == NULL || s->session->master_key_length == 0) {
-            /* might happen if dtls1_read_bytes() calls this */
-            SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,
-                   SSL_R_CCS_RECEIVED_EARLY);
-            return (0);
-        }
-
-        s->session->cipher = s->s3->tmp.new_cipher;
-        if (!s->method->ssl3_enc->setup_key_block(s))
-            return (0);
-    }
-
-    if (!s->method->ssl3_enc->change_cipher_state(s, i))
-        return (0);
-
-    /*
-     * we have to record the message digest at this point so we can get it
-     * before we read the finished message
-     */
-    if (s->state & SSL_ST_CONNECT) {
-        sender = s->method->ssl3_enc->server_finished_label;
-        slen = s->method->ssl3_enc->server_finished_label_len;
-    } else {
-        sender = s->method->ssl3_enc->client_finished_label;
-        slen = s->method->ssl3_enc->client_finished_label_len;
-    }
-
-    i = s->method->ssl3_enc->final_finish_mac(s,
-                                              sender, slen,
-                                              s->s3->tmp.peer_finish_md);
-    if (i == 0) {
-        SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
-    s->s3->tmp.peer_finish_md_len = i;
-
-    return (1);
-}
-
-int ssl3_send_alert(SSL *s, int level, int desc)
-{
-    /* Map tls/ssl alert value to correct one */
-    desc = s->method->ssl3_enc->alert_value(desc);
-    if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
-        desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
-                                          * protocol_version alerts */
-    if (desc < 0)
-        return -1;
-    /* If a fatal one, remove from cache */
-    if ((level == SSL3_AL_FATAL) && (s->session != NULL))
-        SSL_CTX_remove_session(s->ctx, s->session);
-
-    s->s3->alert_dispatch = 1;
-    s->s3->send_alert[0] = level;
-    s->s3->send_alert[1] = desc;
-    if (s->s3->wbuf.left == 0)  /* data still being written out? */
-        return s->method->ssl_dispatch_alert(s);
-    /*
-     * else data is still being written out, we will get written some time in
-     * the future
-     */
-    return -1;
-}
-
-int ssl3_dispatch_alert(SSL *s)
-{
-    int i, j;
-    void (*cb) (const SSL *ssl, int type, int val) = NULL;
 
-    s->s3->alert_dispatch = 0;
-    i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0);
-    if (i <= 0) {
-        s->s3->alert_dispatch = 1;
-    } else {
-        /*
-         * Alert sent to BIO.  If it is important, flush it now. If the
-         * message does not get sent due to non-blocking IO, we will not
-         * worry too much.
-         */
-        if (s->s3->send_alert[0] == SSL3_AL_FATAL)
-            (void)BIO_flush(s->wbio);
-
-        if (s->msg_callback)
-            s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
-                            2, s, s->msg_callback_arg);
-
-        if (s->info_callback != NULL)
-            cb = s->info_callback;
-        else if (s->ctx->info_callback != NULL)
-            cb = s->ctx->info_callback;
-
-        if (cb != NULL) {
-            j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
-            cb(s, SSL_CB_WRITE_ALERT, j);
-        }
-    }
-    return (i);
-}