-/* ssl/record/ssl3_record.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
unsigned char md[EVP_MAX_MD_SIZE];
short version;
unsigned mac_size;
- size_t extra;
unsigned empty_record_count = 0;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
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 ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
}
if ((version >> 8) != SSL3_VERSION_MAJOR) {
+ if (s->first_packet) {
+ /* Go back to start of packet, look at the five bytes
+ * that we have. */
+ p = RECORD_LAYER_get_packet(&s->rlayer);
+ if (strncmp((char *)p, "GET ", 4) == 0 ||
+ strncmp((char *)p, "POST ", 5) == 0 ||
+ strncmp((char *)p, "HEAD ", 5) == 0 ||
+ strncmp((char *)p, "PUT ", 4) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST);
+ goto err;
+ } else if (strncmp((char *)p, "CONNE", 5) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTPS_PROXY_REQUEST);
+ goto err;
+ }
+ }
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
goto err;
}
*/
/* check is not needed I believe */
- if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto f_err;
}
rr->length -= mac_size;
mac = rr->data + rr->length;
- i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+ i = s->method->ssl3_enc->mac(s, rr, 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,
}
}
- enc_err = s->method->ssl3_enc->enc(s, 0);
+ enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
/*-
* enc_err is:
* 0: (in non-constant time) if the record is publically invalid.
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
goto f_err;
}
-#ifdef TLS_DEBUG
+#ifdef SSL_DEBUG
printf("dec %d\n", rr->length);
{
unsigned int z;
mac = &rr->data[rr->length];
}
- i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+ i = s->method->ssl3_enc->mac(s, rr, 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)
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = -1;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
goto f_err;
}
}
- if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
return (1);
}
-int ssl3_do_compress(SSL *ssl)
+int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
{
#ifndef OPENSSL_NO_COMP
int i;
- SSL3_RECORD *wr;
- wr = RECORD_LAYER_get_wrec(&ssl->rlayer);
i = COMP_compress_block(ssl->compress, wr->data,
SSL3_RT_MAX_COMPRESSED_LENGTH,
wr->input, (int)wr->length);
* -1: if the record's padding is invalid or, if sending, an internal error
* occurred.
*/
-int ssl3_enc(SSL *s, int send)
+int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, unsigned int numpipes, int send)
{
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
int bs, i, mac_size = 0;
const EVP_CIPHER *enc;
+ rec = inrecs;
if (send) {
ds = s->enc_write_ctx;
- rec = RECORD_LAYER_get_wrec(&s->rlayer);
if (s->enc_write_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
} else {
ds = s->enc_read_ctx;
- rec = RECORD_LAYER_get_rrec(&s->rlayer);
if (s->enc_read_ctx == NULL)
enc = NULL;
else
rec->input = rec->data;
} else {
l = rec->length;
- bs = EVP_CIPHER_block_size(ds->cipher);
+ bs = EVP_CIPHER_CTX_block_size(ds);
/* COMPRESS */
if (EVP_MD_CTX_md(s->read_hash) != NULL)
mac_size = EVP_MD_CTX_size(s->read_hash);
if ((bs != 1) && !send)
- return ssl3_cbc_remove_padding(s, rec, bs, mac_size);
+ return ssl3_cbc_remove_padding(rec, bs, mac_size);
}
return (1);
}
* -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
* an internal error occurred.
*/
-int tls1_enc(SSL *s, int send)
+int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int numpipes, int send)
{
- SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
- unsigned long l;
+ size_t reclen[SSL_MAX_PIPELINES];
+ unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
int bs, i, j, k, pad = 0, ret, mac_size = 0;
const EVP_CIPHER *enc;
+ unsigned int ctr;
if (send) {
if (EVP_MD_CTX_md(s->write_hash)) {
OPENSSL_assert(n >= 0);
}
ds = s->enc_write_ctx;
- rec = RECORD_LAYER_get_wrec(&s->rlayer);
if (s->enc_write_ctx == NULL)
enc = NULL;
else {
else
ivlen = 0;
if (ivlen > 1) {
- if (rec->data != rec->input)
- /*
- * we can't write into the input stream: Can this ever
- * happen?? (steve)
- */
- fprintf(stderr,
- "%s:%d: rec->data != rec->input\n",
- __FILE__, __LINE__);
- else if (RAND_bytes(rec->input, ivlen) <= 0)
- return -1;
+ for (ctr = 0; ctr < numpipes; ctr++) {
+ if (recs[ctr].data != recs[ctr].input) {
+ /*
+ * we can't write into the input stream: Can this ever
+ * happen?? (steve)
+ */
+ SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
+ return -1;
+ } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ }
}
}
} else {
OPENSSL_assert(n >= 0);
}
ds = s->enc_read_ctx;
- rec = RECORD_LAYER_get_rrec(&s->rlayer);
if (s->enc_read_ctx == NULL)
enc = NULL;
else
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
- memmove(rec->data, rec->input, rec->length);
- rec->input = rec->data;
+ for (ctr = 0; ctr < numpipes; ctr++) {
+ memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
+ recs[ctr].input = recs[ctr].data;
+ }
ret = 1;
} else {
- l = rec->length;
- bs = EVP_CIPHER_block_size(ds->cipher);
-
- if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
- unsigned char buf[EVP_AEAD_TLS1_AAD_LEN], *seq;
-
- seq = send ? RECORD_LAYER_get_write_sequence(&s->rlayer)
- : RECORD_LAYER_get_read_sequence(&s->rlayer);
-
- if (SSL_IS_DTLS(s)) {
- unsigned char dtlsseq[9], *p = dtlsseq;
-
- s2n(send ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
- DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
- memcpy(p, &seq[2], 6);
- memcpy(buf, dtlsseq, 8);
- } else {
- memcpy(buf, seq, 8);
- for (i = 7; i >= 0; i--) { /* increment */
- ++seq[i];
- if (seq[i] != 0)
- break;
- }
- }
-
- buf[8] = rec->type;
- buf[9] = (unsigned char)(s->version >> 8);
- buf[10] = (unsigned char)(s->version);
- buf[11] = rec->length >> 8;
- buf[12] = rec->length & 0xff;
- pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
- EVP_AEAD_TLS1_AAD_LEN, buf);
- if (pad <= 0)
+ bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds));
+
+ if (numpipes > 1) {
+ if(!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_PIPELINE)) {
+ /*
+ * We shouldn't have been called with pipeline data if the
+ * cipher doesn't support pipelining
+ */
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
return -1;
- if (send) {
- l += pad;
- rec->length += pad;
}
- } else if ((bs != 1) && send) {
- i = bs - ((int)l % bs);
+ }
+ for (ctr = 0; ctr < numpipes; ctr++) {
+ reclen[ctr] = recs[ctr].length;
+
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ unsigned char *seq;
+
+ seq = send ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+ : RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ if (SSL_IS_DTLS(s)) {
+ /* DTLS does not support pipelining */
+ unsigned char dtlsseq[9], *p = dtlsseq;
+
+ s2n(send ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
+ DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
+ memcpy(p, &seq[2], 6);
+ memcpy(buf[ctr], dtlsseq, 8);
+ } else {
+ memcpy(buf[ctr], seq, 8);
+ for (i = 7; i >= 0; i--) { /* increment */
+ ++seq[i];
+ if (seq[i] != 0)
+ break;
+ }
+ }
- /* Add weird padding of upto 256 bytes */
+ buf[ctr][8] = recs[ctr].type;
+ buf[ctr][9] = (unsigned char)(s->version >> 8);
+ buf[ctr][10] = (unsigned char)(s->version);
+ buf[ctr][11] = recs[ctr].length >> 8;
+ buf[ctr][12] = recs[ctr].length & 0xff;
+ pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
+ EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
+ if (pad <= 0)
+ return -1;
- /* we need to add 'i' padding bytes of value j */
- j = i - 1;
- for (k = (int)l; k < (int)(l + i); k++)
- rec->input[k] = j;
- l += i;
- rec->length += i;
+ if (send) {
+ reclen[ctr] += pad;
+ recs[ctr].length += pad;
+ }
+
+ } else if ((bs != 1) && send) {
+ i = bs - ((int)reclen[ctr] % bs);
+
+ /* Add weird padding of upto 256 bytes */
+
+ /* we need to add 'i' padding bytes of value j */
+ j = i - 1;
+ for (k = (int)reclen[ctr]; k < (int)(reclen[ctr] + i); k++)
+ recs[ctr].input[k] = j;
+ reclen[ctr] += i;
+ recs[ctr].length += i;
+ }
+
+ if (!send) {
+ if (reclen[ctr] == 0 || reclen[ctr] % bs != 0)
+ return 0;
+ }
}
+ if (numpipes > 1) {
+ unsigned char *data[SSL_MAX_PIPELINES];
- if (!send) {
- if (l == 0 || l % bs != 0)
- return 0;
+ /* Set the output buffers */
+ for(ctr = 0; ctr < numpipes; ctr++) {
+ data[ctr] = recs[ctr].data;
+ }
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
+ numpipes, data) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
+ }
+ /* Set the input buffers */
+ for(ctr = 0; ctr < numpipes; ctr++) {
+ data[ctr] = recs[ctr].input;
+ }
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS,
+ numpipes, data) <= 0
+ || EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
+ numpipes, reclen) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
+ return -1;
+ }
}
- i = EVP_Cipher(ds, rec->data, rec->input, l);
- if ((EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER)
+ i = EVP_Cipher(ds, recs[0].data, recs[0].input, reclen[0]);
+ if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_CUSTOM_CIPHER)
? (i < 0)
: (i == 0))
return -1; /* AEAD can fail to verify MAC */
if (send == 0) {
if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
- rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ for (ctr = 0; ctr < numpipes; ctr++) {
+ recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ }
} else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
- rec->data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- rec->input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- rec->length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ for (ctr = 0; ctr < numpipes; ctr++) {
+ recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ }
}
}
ret = 1;
if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)
mac_size = EVP_MD_CTX_size(s->read_hash);
- if ((bs != 1) && !send)
- ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
+ if ((bs != 1) && !send) {
+ /* TODO: We only support writing for pipelining at the moment */
+ ret = tls1_cbc_remove_padding(s, recs, bs, mac_size);
+ }
if (pad && !send)
- rec->length -= pad;
+ recs[0].length -= pad;
}
return ret;
}
-int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
+int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send)
{
- SSL3_RECORD *rec;
unsigned char *mac_sec, *seq;
const EVP_MD_CTX *hash;
unsigned char *p, rec_char;
int t;
if (send) {
- rec = RECORD_LAYER_get_wrec(&ssl->rlayer);
mac_sec = &(ssl->s3->write_mac_secret[0]);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
- rec = RECORD_LAYER_get_rrec(&ssl->rlayer);
mac_sec = &(ssl->s3->read_mac_secret[0]);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
return (md_size);
}
-int tls1_mac(SSL *ssl, unsigned char *md, int send)
+int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send)
{
- SSL3_RECORD *rec;
unsigned char *seq;
EVP_MD_CTX *hash;
size_t md_size;
int t;
if (send) {
- rec = RECORD_LAYER_get_wrec(&ssl->rlayer);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
- rec = RECORD_LAYER_get_rrec(&ssl->rlayer);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
EVP_MD_CTX_free(hmac);
-#ifdef TLS_DEBUG
+#ifdef SSL_DEBUG
fprintf(stderr, "seq=");
{
int z;
break;
}
}
-#ifdef TLS_DEBUG
+#ifdef SSL_DEBUG
{
unsigned int z;
for (z = 0; z < md_size; z++)
* 1: if the padding was valid
* -1: otherwise.
*/
-int ssl3_cbc_remove_padding(const SSL *s,
- SSL3_RECORD *rec,
+int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
unsigned block_size, unsigned mac_size)
{
unsigned padding_length, good;
padding_length = rec->data[rec->length - 1];
- if (EVP_CIPHER_flags(s->enc_read_ctx->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
/* padding is already verified */
rec->length -= padding_length + 1;
return 1;
rr->data = rr->input;
rr->orig_len = rr->length;
- enc_err = s->method->ssl3_enc->enc(s, 0);
+ enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
/*-
* enc_err is:
* 0: (in non-constant time) if the record is publically invalid.
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto err;
}
-#ifdef TLS_DEBUG
+#ifdef SSL_DEBUG
printf("dec %d\n", rr->length);
{
unsigned int z;
mac = &rr->data[rr->length];
}
- i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+ i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i < 0 || mac == NULL
|| CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
enc_err = -1;