/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include <stdio.h>
#include <limits.h>
#include <errno.h>
-#define USE_SOCKETS
#include "../ssl_locl.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include "record_locl.h"
-
-#ifndef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
-#endif
+#include "../packet_locl.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) || \
!( defined(AES_ASM) && ( \
void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s)
{
rl->s = s;
+ RECORD_LAYER_set_first_record(&s->rlayer);
SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
}
void RECORD_LAYER_clear(RECORD_LAYER *rl)
{
- unsigned int pipes;
-
rl->rstate = SSL_ST_READ_HEADER;
- /* Do I need to clear read_ahead? As far as I can tell read_ahead did not
+ /*
+ * Do I need to clear read_ahead? As far as I can tell read_ahead did not
* previously get reset by SSL_clear...so I'll keep it that way..but is
* that right?
*/
rl->packet = NULL;
rl->packet_length = 0;
rl->wnum = 0;
- memset(rl->alert_fragment, 0, sizeof(rl->alert_fragment));
- rl->alert_fragment_len = 0;
memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment));
rl->handshake_fragment_len = 0;
rl->wpend_tot = 0;
rl->wpend_buf = NULL;
SSL3_BUFFER_clear(&rl->rbuf);
- for(pipes = 0; pipes < rl->numwpipes; pipes++)
- SSL3_BUFFER_clear(&rl->wbuf[pipes]);
- rl->numwpipes = 0;
+ ssl3_release_write_buffer(rl->s);
rl->numrpipes = 0;
SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
RECORD_LAYER_reset_read_sequence(rl);
RECORD_LAYER_reset_write_sequence(rl);
-
+
if (rl->d)
DTLS_RECORD_LAYER_clear(rl);
}
SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES);
}
+/* Checks if we have unprocessed read ahead data pending */
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl)
{
return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
}
-int RECORD_LAYER_write_pending(const RECORD_LAYER *rl)
+/* Checks if we have decrypted unread record data pending */
+int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
{
- return (rl->numwpipes > 0)
- && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes-1]) != 0;
-}
+ size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl);
+ const SSL3_RECORD *rr = rl->rrec;
-int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len)
-{
- rl->packet_length = len;
- if (len != 0) {
- rl->rstate = SSL_ST_READ_HEADER;
- if (!SSL3_BUFFER_is_initialised(&rl->rbuf))
- if (!ssl3_setup_read_buffer(rl->s))
- return 0;
- }
+ while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]))
+ curr_rec++;
- rl->packet = SSL3_BUFFER_get_buf(&rl->rbuf);
- SSL3_BUFFER_set_data(&rl->rbuf, buf, len);
+ return curr_rec < num_recs;
+}
- return 1;
+int RECORD_LAYER_write_pending(const RECORD_LAYER *rl)
+{
+ return (rl->numwpipes > 0)
+ && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0;
}
void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl)
memset(rl->write_sequence, 0, sizeof(rl->write_sequence));
}
-int ssl3_pending(const SSL *s)
+size_t ssl3_pending(const SSL *s)
{
- unsigned int i;
- int num = 0;
+ size_t i, num = 0;
if (s->rlayer.rstate == SSL_ST_READ_BODY)
return 0;
for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) {
if (SSL3_RECORD_get_type(&s->rlayer.rrec[i])
- != SSL3_RT_APPLICATION_DATA)
+ != SSL3_RT_APPLICATION_DATA)
return 0;
num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]);
}
}
}
-int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold)
+/*
+ * Return values are as per SSL_read()
+ */
+int ssl3_read_n(SSL *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
* if clearold == 1, move the packet to the start of the buffer; if
* clearold == 0 then leave any old packets where they were
*/
- int i, len, left;
- size_t align = 0;
+ size_t len, left, align = 0;
unsigned char *pkt;
SSL3_BUFFER *rb;
- if (n <= 0)
- return n;
+ if (n == 0)
+ return 0;
rb = &s->rlayer.rbuf;
if (rb->buf == NULL)
/* ... 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
s->rlayer.packet_length += n;
rb->left = left - n;
rb->offset += n;
- return (n);
+ *readbytes = n;
+ return 1;
}
/* else we need to read more data */
- 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) { /* len > 0 */
- memmove(pkt, s->rlayer.packet, len + left);
- s->rlayer.packet = pkt;
- rb->offset = len + align;
- }
-
- if (n > (int)(rb->len - rb->offset)) { /* does not happen */
+ if (n > rb->len - rb->offset) { /* does not happen */
SSLerr(SSL_F_SSL3_READ_N, ERR_R_INTERNAL_ERROR);
return -1;
}
else {
if (max < n)
max = n;
- if (max > (int)(rb->len - rb->offset))
+ 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
clear_sys_error();
if (s->rbio != NULL) {
s->rwstate = SSL_READING;
- i = BIO_read(s->rbio, pkt + len + left, max - left);
+ /* TODO(size_t): Convert this function */
+ ret = BIO_read(s->rbio, pkt + len + left, max - left);
+ if (ret >= 0)
+ bioread = ret;
} else {
SSLerr(SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET);
- i = -1;
+ ret = -1;
}
- if (i <= 0) {
+ if (ret <= 0) {
rb->left = left;
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
if (len + left == 0)
ssl3_release_read_buffer(s);
- return (i);
+ return ret;
}
- left += i;
+ left += bioread;
/*
* reads should *never* span multiple packets for DTLS because the
* underlying transport protocol is message oriented as opposed to
rb->left = left - n;
s->rlayer.packet_length += n;
s->rwstate = SSL_NOTHING;
- return (n);
+ *readbytes = n;
+ return 1;
}
-
/*
* Call this to write data in records of type 'type' It will return <= 0 if
* not all data has been sent or non-blocking IO.
*/
-int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
+int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
+ size_t *written)
{
const unsigned char *buf = buf_;
- int tot;
- unsigned int n, split_send_fragment, maxpipes;
+ size_t tot;
+ size_t n, max_send_fragment, split_send_fragment, maxpipes;
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
- unsigned int max_send_fragment, nw;
- unsigned int u_len = (unsigned int)len;
+ size_t nw;
#endif
SSL3_BUFFER *wb = &s->rlayer.wbuf[0];
int i;
-
- if (len < 0) {
- SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_SSL_NEGATIVE_LENGTH);
- return -1;
- }
+ size_t tmpwrit;
s->rwstate = SSL_NOTHING;
tot = s->rlayer.wnum;
/*
* ensure that if we end up with a smaller value of data to write out
- * than the the original len from a write which didn't complete for
+ * than the original len from a write which didn't complete for
* non-blocking I/O and also somehow ended up avoiding the check for
* this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be
* possible to end up with (len-tot) as a large number that will then
* promptly send beyond the end of the users buffer ... so we trap and
* report the error in a way the user will notice
*/
- if ((unsigned int)len < s->rlayer.wnum) {
+ if ((len < s->rlayer.wnum)
+ || ((wb->left != 0) && (len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) {
SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_BAD_LENGTH);
return -1;
}
+ if (s->early_data_state == SSL_EARLY_DATA_WRITING
+ && !early_data_count_ok(s, len, 0, NULL))
+ return -1;
s->rlayer.wnum = 0;
- if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) {
+ /*
+ * When writing early data on the server side we could be "in_init" in
+ * between receiving the EoED and the CF - but we don't want to handle those
+ * messages yet.
+ */
+ if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)
+ && s->early_data_state != SSL_EARLY_DATA_UNAUTH_WRITING) {
i = s->handshake_func(s);
if (i < 0)
- return (i);
+ return i;
if (i == 0) {
SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
return -1;
* will happen with non blocking IO
*/
if (wb->left != 0) {
- i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot);
+ i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot,
+ &tmpwrit);
if (i <= 0) {
/* XXX should we ssl3_release_write_buffer if i<0? */
s->rlayer.wnum = tot;
return i;
}
- tot += i; /* this might be last fragment */
+ tot += tmpwrit; /* this might be last fragment */
}
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
/*
* compromise is considered worthy.
*/
if (type == SSL3_RT_APPLICATION_DATA &&
- u_len >= 4 * (max_send_fragment = s->max_send_fragment) &&
+ len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) &&
s->compress == NULL && s->msg_callback == NULL &&
- !SSL_USE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
+ !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
- int packlen;
+ size_t packlen;
+ int packleni;
/* minimize address aliasing conflicts */
if ((max_send_fragment & 0xfff) == 0)
packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
- max_send_fragment, NULL);
+ (int)max_send_fragment, NULL);
- if (u_len >= 8 * max_send_fragment)
+ if (len >= 8 * max_send_fragment)
packlen *= 8;
else
packlen *= 4;
- wb->buf = OPENSSL_malloc(packlen);
- if (wb->buf == NULL) {
+ if (!ssl3_setup_write_buffer(s, 1, packlen)) {
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 */
- wb->buf = NULL;
- return tot;
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ *written = tot;
+ return 1;
}
n = (len - tot);
for (;;) {
if (n < 4 * max_send_fragment) {
- OPENSSL_free(wb->buf); /* free jumbo buffer */
- wb->buf = NULL;
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
break;
}
mb_param.inp = aad;
mb_param.len = nw;
- packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
+ packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
-
- if (packlen <= 0 || packlen > (int)wb->len) { /* never happens */
- OPENSSL_free(wb->buf); /* free jumbo buffer */
- wb->buf = NULL;
+ packlen = (size_t)packleni;
+ if (packleni <= 0 || packlen > wb->len) { /* never happens */
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
break;
}
s->rlayer.wpend_type = type;
s->rlayer.wpend_ret = nw;
- i = ssl3_write_pending(s, type, &buf[tot], nw);
+ i = ssl3_write_pending(s, type, &buf[tot], nw, &tmpwrit);
if (i <= 0) {
if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) {
- OPENSSL_free(wb->buf);
- wb->buf = NULL;
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
}
s->rlayer.wnum = tot;
return i;
}
- if (i == (int)n) {
- OPENSSL_free(wb->buf); /* free jumbo buffer */
- wb->buf = NULL;
- return tot + i;
+ if (tmpwrit == n) {
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ *written = tot + tmpwrit;
+ return 1;
}
- n -= i;
- tot += i;
+ n -= tmpwrit;
+ tot += tmpwrit;
}
} else
-#endif
+#endif /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
if (tot == len) { /* done? */
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
ssl3_release_write_buffer(s);
- return tot;
+ *written = tot;
+ return 1;
}
n = (len - tot);
- split_send_fragment = s->split_send_fragment;
+ max_send_fragment = ssl_get_max_send_fragment(s);
+ split_send_fragment = ssl_get_split_send_fragment(s);
/*
* If max_pipelines is 0 then this means "undefined" and we default to
* 1 pipeline. Similarly if the cipher does not support pipelined
/*
* We should have prevented this when we set max_pipelines so we
* shouldn't get here
- */
+ */
SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
return -1;
}
if (maxpipes == 0
- || s->enc_write_ctx == NULL
- || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx))
- & EVP_CIPH_FLAG_PIPELINE)
- || !SSL_USE_EXPLICIT_IV(s))
+ || s->enc_write_ctx == NULL
+ || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx))
+ & EVP_CIPH_FLAG_PIPELINE)
+ || !SSL_USE_EXPLICIT_IV(s))
maxpipes = 1;
- if (s->max_send_fragment == 0 || split_send_fragment > s->max_send_fragment
- || split_send_fragment == 0) {
+ if (max_send_fragment == 0 || split_send_fragment == 0
+ || split_send_fragment > max_send_fragment) {
/*
- * We should have prevented this when we set the split and max send
+ * We should have prevented this when we set/get the split and max send
* fragments so we shouldn't get here
- */
+ */
SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
return -1;
}
for (;;) {
- unsigned int pipelens[SSL_MAX_PIPELINES], tmppipelen, remain;
- unsigned int numpipes, j;
+ size_t pipelens[SSL_MAX_PIPELINES], tmppipelen, remain;
+ size_t numpipes, j;
if (n == 0)
numpipes = 1;
if (numpipes > maxpipes)
numpipes = maxpipes;
- if (n / numpipes >= s->max_send_fragment) {
+ if (n / numpipes >= max_send_fragment) {
/*
* We have enough data to completely fill all available
* pipelines
*/
for (j = 0; j < numpipes; j++) {
- pipelens[j] = s->max_send_fragment;
+ pipelens[j] = max_send_fragment;
}
} else {
/* We can partially fill all available pipelines */
}
}
- i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0);
+ i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0,
+ &tmpwrit);
if (i <= 0) {
/* XXX should we ssl3_release_write_buffer if i<0? */
s->rlayer.wnum = tot;
return i;
}
- if ((i == (int)n) ||
+ if (tmpwrit == n ||
(type == SSL3_RT_APPLICATION_DATA &&
(s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
/*
!SSL_IS_DTLS(s))
ssl3_release_write_buffer(s);
- return tot + i;
+ *written = tot + tmpwrit;
+ return 1;
}
- n -= i;
- tot += i;
+ n -= tmpwrit;
+ tot += tmpwrit;
}
}
int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
- unsigned int *pipelens, unsigned int numpipes,
- int create_empty_fragment)
+ size_t *pipelens, size_t numpipes,
+ int create_empty_fragment, size_t *written)
{
- unsigned char *outbuf[SSL_MAX_PIPELINES], *plen[SSL_MAX_PIPELINES];
+ WPACKET pkt[SSL_MAX_PIPELINES];
SSL3_RECORD wr[SSL_MAX_PIPELINES];
+ WPACKET *thispkt;
+ SSL3_RECORD *thiswr;
+ unsigned char *recordstart;
int i, mac_size, clear = 0;
- int prefix_len = 0;
- int eivlen;
+ size_t prefix_len = 0;
+ int eivlen = 0;
size_t align = 0;
SSL3_BUFFER *wb;
SSL_SESSION *sess;
- unsigned int totlen = 0;
- unsigned int j;
+ size_t totlen = 0, len, wpinited = 0;
+ size_t j;
for (j = 0; j < numpipes; j++)
totlen += pipelens[j];
* will happen with non blocking IO
*/
if (RECORD_LAYER_write_pending(&s->rlayer))
- return (ssl3_write_pending(s, type, buf, totlen));
+ return ssl3_write_pending(s, type, buf, totlen, written);
/* If we have an alert to send, lets send it */
if (s->s3->alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0)
- return (i);
+ return i;
/* if it went, fall through and send more stuff */
}
if (s->rlayer.numwpipes < numpipes)
- if (!ssl3_setup_write_buffer(s, numpipes))
+ if (!ssl3_setup_write_buffer(s, numpipes, 0))
return -1;
if (totlen == 0 && !create_empty_fragment)
sess = s->session;
if ((sess == NULL) ||
- (s->enc_write_ctx == NULL) ||
- (EVP_MD_CTX_md(s->write_hash) == NULL)) {
+ (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) {
clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */
mac_size = 0;
} else {
+ /* TODO(siz_t): Convert me */
mac_size = EVP_MD_CTX_size(s->write_hash);
if (mac_size < 0)
goto err;
* 'prefix_len' bytes are sent out later together with the actual
* payload)
*/
- unsigned int tmppipelen = 0;
+ size_t tmppipelen = 0;
+ int ret;
- prefix_len = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1);
- if (prefix_len <= 0)
+ ret = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1, &prefix_len);
+ if (ret <= 0)
goto err;
if (prefix_len >
- (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD))
- {
+ (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
/* insufficient space */
SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
- outbuf[0] = SSL3_BUFFER_get_buf(wb) + align;
SSL3_BUFFER_set_offset(wb, align);
+ if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
+ SSL3_BUFFER_get_len(wb), 0)
+ || !WPACKET_allocate_bytes(&pkt[0], align, NULL)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ wpinited = 1;
} else if (prefix_len) {
wb = &s->rlayer.wbuf[0];
- outbuf[0] = SSL3_BUFFER_get_buf(wb) + SSL3_BUFFER_get_offset(wb)
- + prefix_len;
+ if (!WPACKET_init_static_len(&pkt[0],
+ SSL3_BUFFER_get_buf(wb),
+ SSL3_BUFFER_get_len(wb), 0)
+ || !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb)
+ + prefix_len, NULL)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ wpinited = 1;
} else {
- for (j=0; j < numpipes; j++) {
+ for (j = 0; j < numpipes; j++) {
+ thispkt = &pkt[j];
+
wb = &s->rlayer.wbuf[j];
-#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
- outbuf[j] = SSL3_BUFFER_get_buf(wb) + align;
SSL3_BUFFER_set_offset(wb, align);
+ if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb),
+ SSL3_BUFFER_get_len(wb), 0)
+ || !WPACKET_allocate_bytes(thispkt, align, NULL)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ wpinited++;
}
}
/* Explicit IV length, block ciphers appropriate version flag */
- if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) {
+ if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) {
int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
+ /* TODO(size_t): Convert me */
eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
if (eivlen <= 1)
eivlen = 0;
- }
- /* Need explicit part of IV for GCM mode */
- else if (mode == EVP_CIPH_GCM_MODE)
+ } else if (mode == EVP_CIPH_GCM_MODE) {
+ /* Need explicit part of IV for GCM mode */
eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
- else if (mode == EVP_CIPH_CCM_MODE)
+ } else if (mode == EVP_CIPH_CCM_MODE) {
eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
- else
- eivlen = 0;
- } else
- eivlen = 0;
-
+ }
+ }
totlen = 0;
/* Clear our SSL3_RECORD structures */
- memset(wr, 0, sizeof wr);
- for (j=0; j < numpipes; j++) {
- /* write the header */
- *(outbuf[j]++) = type & 0xff;
- SSL3_RECORD_set_type(&wr[j], type);
+ memset(wr, 0, sizeof(wr));
+ for (j = 0; j < numpipes; j++) {
+ unsigned int version = SSL_TREAT_AS_TLS13(s) ? TLS1_VERSION : s->version;
+ unsigned char *compressdata = NULL;
+ size_t maxcomplen;
+ unsigned int rectype;
- *(outbuf[j]++) = (s->version >> 8);
+ thispkt = &pkt[j];
+ thiswr = &wr[j];
+
+ SSL3_RECORD_set_type(thiswr, type);
+ /*
+ * In TLSv1.3, once encrypting, we always use application data for the
+ * record type
+ */
+ if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL)
+ rectype = SSL3_RT_APPLICATION_DATA;
+ else
+ rectype = type;
/*
* Some servers hang if initial client hello is larger than 256 bytes
* and record version number > TLS 1.0
*/
if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO
&& !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION)
- *(outbuf[j]++) = 0x1;
- else
- *(outbuf[j]++) = s->version & 0xff;
+ version = TLS1_VERSION;
- /* field where we are to write out packet length */
- plen[j] = outbuf[j];
- outbuf[j] += 2;
+ maxcomplen = pipelens[j];
+ if (s->compress != NULL)
+ maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+
+ /* write the header */
+ if (!WPACKET_put_bytes_u8(thispkt, rectype)
+ || !WPACKET_put_bytes_u16(thispkt, version)
+ || !WPACKET_start_sub_packet_u16(thispkt)
+ || (eivlen > 0
+ && !WPACKET_allocate_bytes(thispkt, eivlen, NULL))
+ || (maxcomplen > 0
+ && !WPACKET_reserve_bytes(thispkt, maxcomplen,
+ &compressdata))) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
/* lets setup the record stuff. */
- SSL3_RECORD_set_data(&wr[j], outbuf[j] + eivlen);
- SSL3_RECORD_set_length(&wr[j], (int)pipelens[j]);
- SSL3_RECORD_set_input(&wr[j], (unsigned char *)&buf[totlen]);
+ SSL3_RECORD_set_data(thiswr, compressdata);
+ SSL3_RECORD_set_length(thiswr, pipelens[j]);
+ SSL3_RECORD_set_input(thiswr, (unsigned char *)&buf[totlen]);
totlen += pipelens[j];
/*
- * we now 'read' from wr->input, wr->length bytes into wr->data
+ * we now 'read' from thiswr->input, thiswr->length bytes into
+ * thiswr->data
*/
/* first we compress */
if (s->compress != NULL) {
- if (!ssl3_do_compress(s, &wr[j])) {
+ if (!ssl3_do_compress(s, thiswr)
+ || !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) {
SSLerr(SSL_F_DO_SSL3_WRITE, SSL_R_COMPRESSION_FAILURE);
goto err;
}
} else {
- memcpy(wr[j].data, wr[j].input, wr[j].length);
+ if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
SSL3_RECORD_reset_input(&wr[j]);
}
+ if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
+ size_t rlen, max_send_fragment;
+
+ if (!WPACKET_put_bytes_u8(thispkt, type)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ SSL3_RECORD_add_length(thiswr, 1);
+
+ /* Add TLS1.3 padding */
+ max_send_fragment = ssl_get_max_send_fragment(s);
+ rlen = SSL3_RECORD_get_length(thiswr);
+ if (rlen < max_send_fragment) {
+ size_t padding = 0;
+ size_t max_padding = max_send_fragment - rlen;
+ if (s->record_padding_cb != NULL) {
+ padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg);
+ } else if (s->block_padding > 0) {
+ size_t mask = s->block_padding - 1;
+ size_t remainder;
+
+ /* optimize for power of 2 */
+ if ((s->block_padding & mask) == 0)
+ remainder = rlen & mask;
+ else
+ remainder = rlen % s->block_padding;
+ /* don't want to add a block of padding if we don't have to */
+ if (remainder == 0)
+ padding = 0;
+ else
+ padding = s->block_padding - remainder;
+ }
+ if (padding > 0) {
+ /* do not allow the record to exceed max plaintext length */
+ if (padding > max_padding)
+ padding = max_padding;
+ if (!WPACKET_memset(thispkt, 0, padding)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ SSL3_RECORD_add_length(thiswr, padding);
+ }
+ }
+ }
+
/*
- * we should still have the output to wr->data and the input from
- * wr->input. Length should be wr->length. wr->data still points in the
- * wb->buf
+ * we should still have the output to thiswr->data and the input from
+ * wr->input. Length should be thiswr->length. thiswr->data still points
+ * in the wb->buf
*/
- if (!SSL_USE_ETM(s) && mac_size != 0) {
- if (s->method->ssl3_enc->mac(s, &wr[j],
- &(outbuf[j][wr[j].length + eivlen]), 1) < 0)
+ if (!SSL_WRITE_ETM(s) && mac_size != 0) {
+ unsigned char *mac;
+
+ if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
+ || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
- SSL3_RECORD_add_length(&wr[j], mac_size);
+ }
}
+ /*
+ * Reserve some bytes for any growth that may occur during encryption.
+ * This will be at most one cipher block or the tag length if using
+ * AEAD. SSL_RT_MAX_CIPHER_BLOCK_SIZE covers either case.
+ */
+ if (!WPACKET_reserve_bytes(thispkt, SSL_RT_MAX_CIPHER_BLOCK_SIZE,
+ NULL)
+ /*
+ * We also need next the amount of bytes written to this
+ * sub-packet
+ */
+ || !WPACKET_get_length(thispkt, &len)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- SSL3_RECORD_set_data(&wr[j], outbuf[j]);
- SSL3_RECORD_reset_input(&wr[j]);
+ /* Get a pointer to the start of this record excluding header */
+ recordstart = WPACKET_get_curr(thispkt) - len;
- if (eivlen) {
- /*
- * if (RAND_pseudo_bytes(p, eivlen) <= 0) goto err;
- */
- SSL3_RECORD_add_length(&wr[j], eivlen);
- }
+ SSL3_RECORD_set_data(thiswr, recordstart);
+ SSL3_RECORD_reset_input(thiswr);
+ SSL3_RECORD_set_length(thiswr, len);
}
- if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
- goto err;
+ if (s->early_data_state == SSL_EARLY_DATA_WRITING
+ || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+ /*
+ * We haven't actually negotiated the version yet, but we're trying to
+ * send early data - so we need to use the tls13enc function.
+ */
+ if (tls13_enc(s, wr, numpipes, 1) < 1)
+ goto err;
+ } else {
+ if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
+ goto err;
+ }
- for (j=0; j < numpipes; j++) {
- if (SSL_USE_ETM(s) && mac_size != 0) {
- if (s->method->ssl3_enc->mac(s, &wr[j],
- outbuf[j] + wr[j].length, 1) < 0)
+ for (j = 0; j < numpipes; j++) {
+ size_t origlen;
+
+ thispkt = &pkt[j];
+ thiswr = &wr[j];
+
+ /* Allocate bytes for the encryption overhead */
+ if (!WPACKET_get_length(thispkt, &origlen)
+ /* Encryption should never shrink the data! */
+ || origlen > thiswr->length
+ || (thiswr->length > origlen
+ && !WPACKET_allocate_bytes(thispkt,
+ thiswr->length - origlen, NULL))) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (SSL_WRITE_ETM(s) && mac_size != 0) {
+ unsigned char *mac;
+
+ if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
+ || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
- SSL3_RECORD_add_length(&wr[j], mac_size);
+ }
+ SSL3_RECORD_add_length(thiswr, mac_size);
}
- /* record length after mac and block padding */
- s2n(SSL3_RECORD_get_length(&wr[j]), plen[j]);
+ if (!WPACKET_get_length(thispkt, &len)
+ || !WPACKET_close(thispkt)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- if (s->msg_callback)
- s->msg_callback(1, 0, SSL3_RT_HEADER, plen[j] - 5, 5, s,
+ if (s->msg_callback) {
+ recordstart = WPACKET_get_curr(thispkt) - len
+ - SSL3_RT_HEADER_LENGTH;
+ s->msg_callback(1, 0, SSL3_RT_HEADER, recordstart,
+ SSL3_RT_HEADER_LENGTH, s,
s->msg_callback_arg);
+ if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
+ unsigned char ctype = type;
+
+ s->msg_callback(1, s->version, SSL3_RT_INNER_CONTENT_TYPE,
+ &ctype, 1, s, s->msg_callback_arg);
+ }
+ }
+
+ if (!WPACKET_finish(thispkt)) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
/*
- * we should now have wr->data pointing to the encrypted data, which is
- * wr->length long
+ * we should now have thiswr->data pointing to the encrypted data, which
+ * is thiswr->length long
*/
- SSL3_RECORD_set_type(&wr[j], type); /* not needed but helps for debugging */
- SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
+ SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
+ * debugging */
+ SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH);
if (create_empty_fragment) {
/*
SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
}
- return SSL3_RECORD_get_length(wr);
+ *written = SSL3_RECORD_get_length(thiswr);
+ return 1;
}
/* now let's set up wb */
SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
- prefix_len + SSL3_RECORD_get_length(&wr[j]));
+ prefix_len + SSL3_RECORD_get_length(thiswr));
}
-
-
/*
* memorize arguments so that ssl3_write_pending can detect bad write
* retries later
s->rlayer.wpend_ret = totlen;
/* we now just need to write the buffer */
- return ssl3_write_pending(s, type, buf, totlen);
+ return ssl3_write_pending(s, type, buf, totlen, written);
err:
+ for (j = 0; j < wpinited; j++)
+ WPACKET_cleanup(&pkt[j]);
return -1;
}
-/* if s->s3->wbuf.left != 0, we need to call this */
-int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
- unsigned int len)
+/* if s->s3->wbuf.left != 0, we need to call this
+ *
+ * Return values are as per SSL_write()
+ */
+int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
+ size_t *written)
{
int i;
SSL3_BUFFER *wb = s->rlayer.wbuf;
- unsigned int currbuf = 0;
+ size_t currbuf = 0;
+ size_t tmpwrit = 0;
-/* XXXX */
- if ((s->rlayer.wpend_tot > (int)len)
+ if ((s->rlayer.wpend_tot > len)
|| ((s->rlayer.wpend_buf != buf) &&
!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
|| (s->rlayer.wpend_type != type)) {
SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BAD_WRITE_RETRY);
- return (-1);
+ return -1;
}
for (;;) {
/* Loop until we find a buffer we haven't written out yet */
if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0
- && currbuf < s->rlayer.numwpipes - 1) {
+ && currbuf < s->rlayer.numwpipes - 1) {
currbuf++;
continue;
}
clear_sys_error();
if (s->wbio != NULL) {
s->rwstate = SSL_WRITING;
- i = BIO_write(s->wbio,
- (char *)&(SSL3_BUFFER_get_buf(&wb[currbuf])[
- SSL3_BUFFER_get_offset(&wb[currbuf])]),
- (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf]));
+ /* TODO(size_t): Convert this call */
+ i = BIO_write(s->wbio, (char *)
+ &(SSL3_BUFFER_get_buf(&wb[currbuf])
+ [SSL3_BUFFER_get_offset(&wb[currbuf])]),
+ (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf]));
+ if (i >= 0)
+ tmpwrit = i;
} else {
SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET);
i = -1;
}
- if (i == SSL3_BUFFER_get_left(&wb[currbuf])) {
+ if (i > 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
SSL3_BUFFER_set_left(&wb[currbuf], 0);
- SSL3_BUFFER_add_offset(&wb[currbuf], i);
+ SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
if (currbuf + 1 < s->rlayer.numwpipes)
continue;
s->rwstate = SSL_NOTHING;
- return (s->rlayer.wpend_ret);
+ *written = s->rlayer.wpend_ret;
+ return 1;
} else if (i <= 0) {
if (SSL_IS_DTLS(s)) {
/*
*/
SSL3_BUFFER_set_left(&wb[currbuf], 0);
}
- return (i);
+ return i;
}
- SSL3_BUFFER_add_offset(&wb[currbuf], i);
- SSL3_BUFFER_add_left(&wb[currbuf], -i);
+ SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
+ SSL3_BUFFER_sub_left(&wb[currbuf], tmpwrit);
}
}
* none of our business
*/
int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
- int len, int peek)
+ size_t len, int peek, size_t *readbytes)
{
int al, i, j, ret;
- unsigned int n, curr_rec, num_recs, read_bytes;
+ size_t n, curr_rec, num_recs, totalbytes;
SSL3_RECORD *rr;
SSL3_BUFFER *rbuf;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
if (!SSL3_BUFFER_is_initialised(rbuf)) {
/* Not initialized yet */
if (!ssl3_setup_read_buffer(s))
- return (-1);
+ return -1;
}
if ((type && (type != SSL3_RT_APPLICATION_DATA)
if (recvd_type != NULL)
*recvd_type = SSL3_RT_HANDSHAKE;
- return n;
+ *readbytes = n;
+ return 1;
}
/*
/* type == SSL3_RT_APPLICATION_DATA */
i = s->handshake_func(s);
if (i < 0)
- return (i);
+ return i;
if (i == 0) {
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
- return (-1);
+ return -1;
}
}
start:
if (num_recs == 0) {
ret = ssl3_get_record(s);
if (ret <= 0)
- return (ret);
+ return ret;
num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
if (num_recs == 0) {
/* Shouldn't happen */
/* Skip over any records we have already read */
for (curr_rec = 0;
curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]);
- curr_rec++);
+ curr_rec++) ;
if (curr_rec == num_recs) {
RECORD_LAYER_set_numrpipes(&s->rlayer, 0);
num_recs = 0;
} while (num_recs == 0);
rr = &rr[curr_rec];
+ /*
+ * Reset the count of consecutive warning alerts if we've got a non-empty
+ * record that isn't an alert.
+ */
+ if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
+ && SSL3_RECORD_get_length(rr) != 0)
+ s->rlayer.alert_count = 0;
+
/* we now have a packet which can be read and processed */
if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
SSL3_RECORD_set_length(rr, 0);
s->rwstate = SSL_NOTHING;
- return (0);
+ return 0;
}
if (type == SSL3_RECORD_get_type(rr)
- || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
- && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
+ || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ && type == SSL3_RT_HANDSHAKE && recvd_type != NULL
+ && !SSL_IS_TLS13(s))) {
/*
* SSL3_RT_APPLICATION_DATA or
* SSL3_RT_HANDSHAKE or
}
if (type == SSL3_RT_HANDSHAKE
- && SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
- && s->rlayer.handshake_fragment_len > 0) {
+ && SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ && s->rlayer.handshake_fragment_len > 0) {
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_CCS_RECEIVED_EARLY);
goto f_err;
if (recvd_type != NULL)
*recvd_type = SSL3_RECORD_get_type(rr);
- if (len <= 0)
- return (len);
+ if (len == 0) {
+ /*
+ * Mark a zero length record as read. This ensures multiple calls to
+ * SSL_read() with a zero length buffer will eventually cause
+ * SSL_pending() to report data as being available.
+ */
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
+ return 0;
+ }
- read_bytes = 0;
+ totalbytes = 0;
do {
- if ((unsigned int)len - read_bytes > SSL3_RECORD_get_length(rr))
+ if (len - totalbytes > SSL3_RECORD_get_length(rr))
n = SSL3_RECORD_get_length(rr);
else
- n = (unsigned int)len - read_bytes;
+ n = len - totalbytes;
memcpy(buf, &(rr->data[rr->off]), n);
buf += n;
- if (!peek) {
+ if (peek) {
+ /* Mark any zero length record as consumed CVE-2016-6305 */
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
+ } else {
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
curr_rec++;
rr++;
}
- read_bytes += n;
+ totalbytes += n;
} while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs
- && read_bytes < (unsigned int)len);
- if (read_bytes == 0) {
+ && totalbytes < len);
+ if (totalbytes == 0) {
/* We must have read empty records. Get more data */
goto start;
}
if (!peek && curr_rec == num_recs
- && (s->mode & SSL_MODE_RELEASE_BUFFERS)
- && SSL3_BUFFER_get_left(rbuf) == 0)
+ && (s->mode & SSL_MODE_RELEASE_BUFFERS)
+ && SSL3_BUFFER_get_left(rbuf) == 0)
ssl3_release_read_buffer(s);
- return read_bytes;
+ *readbytes = totalbytes;
+ return 1;
}
/*
* were actually expecting a CCS).
*/
- if (rr->type == SSL3_RT_HANDSHAKE && type == SSL3_RT_CHANGE_CIPHER_SPEC) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
-
/*
* Lets just double check that we've not got an SSLv2 record
*/
goto f_err;
}
- if(s->method->version == TLS_ANY_VERSION
- && (s->server || rr->type != SSL3_RT_ALERT)) {
+ if (s->method->version == TLS_ANY_VERSION
+ && (s->server || rr->type != SSL3_RT_ALERT)) {
/*
* If we've got this far and still haven't decided on what version
* we're using then this must be a client side alert we're dealing with
* that so that we can process the data at a fixed place.
*/
{
- unsigned int dest_maxlen = 0;
+ size_t dest_maxlen = 0;
unsigned char *dest = NULL;
- unsigned int *dest_len = NULL;
+ size_t *dest_len = NULL;
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
- dest_maxlen = sizeof s->rlayer.handshake_fragment;
+ dest_maxlen = sizeof(s->rlayer.handshake_fragment);
dest = s->rlayer.handshake_fragment;
dest_len = &s->rlayer.handshake_fragment_len;
- } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
- dest_maxlen = sizeof s->rlayer.alert_fragment;
- dest = s->rlayer.alert_fragment;
- dest_len = &s->rlayer.alert_fragment_len;
}
if (dest_maxlen > 0) {
n = SSL3_RECORD_get_length(rr); /* available bytes */
/* now move 'n' bytes: */
- while (n-- > 0) {
- dest[(*dest_len)++] =
- SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
- SSL3_RECORD_add_off(rr, 1);
- SSL3_RECORD_add_length(rr, -1);
- }
+ memcpy(dest + *dest_len,
+ SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n);
+ SSL3_RECORD_add_off(rr, n);
+ SSL3_RECORD_sub_length(rr, n);
+ *dest_len += n;
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
/*-
* s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
- * s->rlayer.alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT.
* (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
*/
- /* If we are a client, check for an incoming 'Hello Request': */
- if ((!s->server) &&
- (s->rlayer.handshake_fragment_len >= 4) &&
- (s->rlayer.handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
- (s->session != NULL) && (s->session->cipher != NULL)) {
- s->rlayer.handshake_fragment_len = 0;
-
- if ((s->rlayer.handshake_fragment[1] != 0) ||
- (s->rlayer.handshake_fragment[2] != 0) ||
- (s->rlayer.handshake_fragment[3] != 0)) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
- goto f_err;
- }
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- s->rlayer.handshake_fragment, 4, s,
- s->msg_callback_arg);
-
- if (SSL_is_init_finished(s) &&
- !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
- !s->s3->renegotiate) {
- ssl3_renegotiate(s);
- if (ssl3_renegotiate_check(s)) {
- i = s->handshake_func(s);
- if (i < 0)
- return (i);
- if (i == 0) {
- SSLerr(SSL_F_SSL3_READ_BYTES,
- SSL_R_SSL_HANDSHAKE_FAILURE);
- return (-1);
- }
-
- if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
- if (SSL3_BUFFER_get_left(rbuf) == 0) {
- /* no read-ahead left? */
- BIO *bio;
- /*
- * In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world
- */
- s->rwstate = SSL_READING;
- bio = SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return (-1);
- }
- }
- }
- }
- /*
- * we either finished a handshake or ignored the request, now try
- * again to obtain the (application) data we were asked for
- */
- goto start;
- }
/*
* If we are a server and get a client hello when renegotiation isn't
* allowed send back a no renegotiation alert and carry on. WARNING:
*/
if (s->server &&
SSL_is_init_finished(s) &&
- !s->s3->send_connection_binding &&
(s->version > SSL3_VERSION) &&
+ !SSL_IS_TLS13(s) &&
+ (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
(s->rlayer.handshake_fragment_len >= 4) &&
(s->rlayer.handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
(s->session != NULL) && (s->session->cipher != NULL) &&
- !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ ((!s->s3->send_connection_binding &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) ||
+ (s->options & SSL_OP_NO_RENEGOTIATION))) {
SSL3_RECORD_set_length(rr, 0);
+ SSL3_RECORD_set_read(rr);
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
goto start;
}
- if (s->rlayer.alert_fragment_len >= 2) {
- int alert_level = s->rlayer.alert_fragment[0];
- int alert_descr = s->rlayer.alert_fragment[1];
-
- s->rlayer.alert_fragment_len = 0;
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ unsigned int alert_level, alert_descr;
+ unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ + SSL3_RECORD_get_off(rr);
+ PACKET alert;
+
+ if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
+ || !PACKET_get_1(&alert, &alert_level)
+ || !PACKET_get_1(&alert, &alert_descr)
+ || PACKET_remaining(&alert) != 0) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INVALID_ALERT);
+ goto f_err;
+ }
if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_ALERT,
- s->rlayer.alert_fragment, 2, s,
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)
if (alert_level == SSL3_AL_WARNING) {
s->s3->warn_alert = alert_descr;
+ SSL3_RECORD_set_read(rr);
+
+ s->rlayer.alert_count++;
+ if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+ goto f_err;
+ }
+
if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- return (0);
+ return 0;
+ }
+ /*
+ * Apart from close_notify the only other warning alert in TLSv1.3
+ * is user_cancelled - which we just ignore.
+ */
+ if (SSL_IS_TLS13(s) && alert_descr != SSL_AD_USER_CANCELLED) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
}
/*
* This is a warning but we receive it if we requested
* future we might have a renegotiation where we don't care if
* the peer refused it where we carry on.
*/
- else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
+ if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_NO_RENEGOTIATION);
goto f_err;
}
-#ifdef SSL_AD_MISSING_SRP_USERNAME
- else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME)
- return (0);
-#endif
} else if (alert_level == SSL3_AL_FATAL) {
char tmp[16];
s->rwstate = SSL_NOTHING;
s->s3->fatal_alert = alert_descr;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
+ BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
ERR_add_error_data(2, "SSL alert number ", tmp);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(s->ctx, s->session);
- return (0);
+ SSL3_RECORD_set_read(rr);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ return 0;
} else {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
* shutdown */
s->rwstate = SSL_NOTHING;
SSL3_RECORD_set_length(rr, 0);
- return (0);
+ SSL3_RECORD_set_read(rr);
+ return 0;
}
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
}
/*
- * Unexpected handshake message (Client Hello, or protocol violation)
+ * Unexpected handshake message (ClientHello, NewSessionTicket (TLS1.3) or
+ * protocol violation)
*/
if ((s->rlayer.handshake_fragment_len >= 4)
&& !ossl_statem_get_in_handshake(s)) {
- if (SSL_is_init_finished(s) &&
- !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
- ossl_statem_set_in_init(s, 1);
- s->renegotiate = 1;
- s->new_session = 1;
- }
+ int ined = (s->early_data_state == SSL_EARLY_DATA_READING);
+
+ /* We found handshake data, so we're going back into init */
+ ossl_statem_set_in_init(s, 1);
+
i = s->handshake_func(s);
if (i < 0)
- return (i);
+ return i;
if (i == 0) {
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
- return (-1);
+ return -1;
}
+ /*
+ * If we were actually trying to read early data and we found a
+ * handshake message, then we don't want to continue to try and read
+ * the application data any more. It won't be "early" now.
+ */
+ if (ined)
+ return -1;
+
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(rbuf) == 0) {
/* no read-ahead left? */
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
- return (-1);
+ return -1;
}
}
goto start;
switch (SSL3_RECORD_get_type(rr)) {
default:
/*
- * TLS up to v1.1 just ignores unknown message types: TLS v1.2 give
- * an unexpected message alert.
+ * TLS 1.0 and 1.1 say you SHOULD ignore unrecognised record types, but
+ * TLS 1.2 says you MUST send an unexpected message alert. We use the
+ * TLS 1.2 behaviour for all protocol versions to prevent issues where
+ * no progress is being made and the peer continually sends unrecognised
+ * record types, using up resources processing them.
*/
- if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION) {
- SSL3_RECORD_set_length(rr, 0);
- goto start;
- }
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
goto f_err;
*/
if (ossl_statem_app_data_allowed(s)) {
s->s3->in_read_app_data = 2;
- return (-1);
+ return -1;
+ } else if (ossl_statem_skip_early_data(s)) {
+ /*
+ * This can happen after a client sends a CH followed by early_data,
+ * but the server responds with a HelloRetryRequest. The server
+ * reads the next record from the client expecting to find a
+ * plaintext ClientHello but gets a record which appears to be
+ * application data. The trial decrypt "works" because null
+ * decryption was applied. We just skip it and move on to the next
+ * record.
+ */
+ if (!early_data_count_ok(s, rr->length,
+ EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+ goto f_err;
+ SSL3_RECORD_set_read(rr);
+ goto start;
} else {
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return (-1);
+ return -1;
}
void ssl3_record_sequence_update(unsigned char *seq)
/*
* Returns the length in bytes of the current rrec
*/
-unsigned int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl)
+size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl)
{
return SSL3_RECORD_get_length(&rl->rrec[0]);
}