*/
#include <stdio.h>
+#include <limits.h>
#include <errno.h>
#define USE_SOCKETS
#include "ssl_locl.h"
* at once (as long as it fits into the buffer). */
if (SSL_IS_DTLS(s))
{
+ if (left == 0 && extend)
+ return 0;
if (left > 0 && n > left)
n = left;
}
* ssl3_get_record to loop forever. */
#define MAX_EMPTY_RECORDS 32
-/* Call this to get a new input record.
+/*-
+ * 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
}
enc_err = s->method->ssl3_enc->enc(s,0);
- /* enc_err is:
+ /*-
+ * 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 */
+ * -1: if the padding is invalid
+ */
if (enc_err == 0)
{
al=SSL_AD_DECRYPTION_FAILED;
}
rr->off=0;
- /* So at this point the following is true
+ /*-
+ * 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
if (empty_record_count > MAX_EMPTY_RECORDS)
{
al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
+ SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_RECORD_TOO_SMALL);
goto f_err;
}
goto again;
#endif
SSL3_BUFFER *wb=&(s->s3->wbuf);
int i;
+ unsigned int u_len = (unsigned int)len;
+
+ if (len < 0)
+ {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_NEGATIVE_LENGTH);
+ return -1;
+ }
s->rwstate=SSL_NOTHING;
+ OPENSSL_assert(s->s3->wnum <= INT_MAX);
tot=s->s3->wnum;
s->s3->wnum=0;
}
}
+ /* 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 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 (len < tot)
+ {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_BAD_LENGTH);
+ return(-1);
+ }
+
/* first check if there is a SSL3_BUFFER still being written
* out. This will happen with non blocking IO */
if (wb->left != 0)
* compromise is considered worthy.
*/
if (type==SSL3_RT_APPLICATION_DATA &&
- len >= 4*(max_send_fragment=s->max_send_fragment) &&
+ u_len >= 4*(max_send_fragment=s->max_send_fragment) &&
s->compress==NULL && s->msg_callback==NULL &&
!SSL_USE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
EVP_CIPHER_flags(s->enc_write_ctx->cipher)&EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
int packlen;
/* minimize address aliasing conflicts */
- if ((max_send_fragment&0xffff) == 0)
+ if ((max_send_fragment&0xfff) == 0)
max_send_fragment -= 512;
if (tot==0 || wb->buf==NULL) /* allocate jumbo buffer */
EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
max_send_fragment,NULL);
- if (len>=8*max_send_fragment) packlen *= 8;
+ if (u_len >= 8*max_send_fragment) packlen *= 8;
else packlen *= 4;
wb->buf=OPENSSL_malloc(packlen);
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param),&mb_param);
- if (packlen<=0 || packlen>wb->len) /* never happens */
+ if (packlen<=0 || packlen>(int)wb->len) /* never happens */
{
OPENSSL_free(wb->buf); /* free jumbo buffer */
wb->buf = NULL;
mb_param.inp = &buf[tot];
mb_param.len = nw;
- EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
- EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
- sizeof(mb_param),&mb_param);
+ if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+ sizeof(mb_param),&mb_param)<=0)
+ return -1;
s->s3->write_sequence[7] += mb_param.interleave;
if (s->s3->write_sequence[7] < mb_param.interleave)
return tot;
}
+
n=(len-tot);
for (;;)
{
SSL3_BUFFER *wb=&(s->s3->wbuf);
SSL_SESSION *sess;
- if (wb->buf == NULL)
- if (!ssl3_setup_write_buffer(s))
- return -1;
/* first check if there is a SSL3_BUFFER still being written
* out. This will happen with non blocking IO */
/* if it went, fall through and send more stuff */
}
+ if (wb->buf == NULL)
+ if (!ssl3_setup_write_buffer(s))
+ return -1;
+
if (len == 0 && !create_empty_fragment)
return 0;
#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) && /*!SSL_IS_DTLS(s) &&*/
+ !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];
wr->length += eivlen;
}
- /* ssl3_enc can only have an error on read */
- s->method->ssl3_enc->enc(s,1);
+ if(s->method->ssl3_enc->enc(s,1)<1) goto err;
if (SSL_USE_ETM(s) && mac_size != 0)
{
}
}
-/* Return up to 'len' payload bytes received in 'type' records.
+/*-
+ * Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
if (!ssl3_setup_read_buffer(s))
return(-1);
- if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) ||
+ if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE)) ||
(peek && (type != SSL3_RT_APPLICATION_DATA)))
{
SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
start:
s->rwstate=SSL_NOTHING;
- /* s->s3->rrec.type - is the type of record
+ /*-
+ * s->s3->rrec.type - is the type of record
* s->s3->rrec.data, - data
* s->s3->rrec.off, - offset into 'data' for next read
- * s->s3->rrec.length, - number of bytes. */
+ * s->s3->rrec.length, - number of bytes.
+ */
rr = &(s->s3->rrec);
/* get new packet if necessary */
{
s->rstate=SSL_ST_READ_HEADER;
rr->off=0;
- if (s->mode & SSL_MODE_RELEASE_BUFFERS)
+ if (s->mode & SSL_MODE_RELEASE_BUFFERS && s->s3->rbuf.left == 0)
ssl3_release_read_buffer(s);
}
}
}
}
- /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
+ /*-
+ * s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
* s->s3->alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT.
- * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
+ * (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) &&
goto f_err;
}
+ if (!(s->s3->flags & SSL3_FLAGS_CCS_OK))
+ {
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
+
rr->length=0;
if (s->msg_callback)
if (s->s3->tmp.key_block == NULL)
{
- if (s->session == 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);
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 == 2) && (s->session != NULL))
+ if ((level == SSL3_AL_FATAL) && (s->session != NULL))
SSL_CTX_remove_session(s->ctx,s->session);
s->s3->alert_dispatch=1;