aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssl/ssl/record
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssl/ssl/record')
-rw-r--r--crypto/openssl/ssl/record/rec_layer_s3.c137
-rw-r--r--crypto/openssl/ssl/record/record.h2
-rw-r--r--crypto/openssl/ssl/record/record_local.h3
-rw-r--r--crypto/openssl/ssl/record/ssl3_buffer.c33
-rw-r--r--crypto/openssl/ssl/record/ssl3_record.c47
5 files changed, 165 insertions, 57 deletions
diff --git a/crypto/openssl/ssl/record/rec_layer_s3.c b/crypto/openssl/ssl/record/rec_layer_s3.c
index b2a7a47eb075..f53c40200675 100644
--- a/crypto/openssl/ssl/record/rec_layer_s3.c
+++ b/crypto/openssl/ssl/record/rec_layer_s3.c
@@ -268,11 +268,15 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
return -1;
}
- /* We always act like read_ahead is set for DTLS */
- if (!s->rlayer.read_ahead && !SSL_IS_DTLS(s))
+ /*
+ * Ktls always reads full records.
+ * Also, we always act like read_ahead is set for DTLS.
+ */
+ if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
+ && !SSL_IS_DTLS(s)) {
/* ignore max parameter */
max = n;
- else {
+ } else {
if (max < n)
max = n;
if (max > rb->len - rb->offset)
@@ -422,6 +426,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) &&
s->compress == NULL && s->msg_callback == NULL &&
!SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
+ (BIO_get_ktls_send(s->wbio) == 0) &&
EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
unsigned char aad[13];
@@ -751,6 +756,19 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
s->s3->empty_fragment_done = 1;
}
+ if (BIO_get_ktls_send(s->wbio)) {
+ /*
+ * ktls doesn't modify the buffer, but to avoid a warning we need to
+ * discard the const qualifier.
+ * This doesn't leak memory because the buffers have been released when
+ * switching to ktls.
+ */
+ SSL3_BUFFER_set_buf(&s->rlayer.wbuf[0], (unsigned char *)buf);
+ SSL3_BUFFER_set_offset(&s->rlayer.wbuf[0], 0);
+ SSL3_BUFFER_set_app_buffer(&s->rlayer.wbuf[0], 1);
+ goto wpacket_init_complete;
+ }
+
if (create_empty_fragment) {
wb = &s->rlayer.wbuf[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
@@ -820,6 +838,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
}
}
+ wpacket_init_complete:
+
totlen = 0;
/* Clear our SSL3_RECORD structures */
memset(wr, 0, sizeof(wr));
@@ -861,15 +881,19 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (s->compress != NULL)
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
- /* write the header */
- if (!WPACKET_put_bytes_u8(thispkt, rectype)
+ /*
+ * When using offload kernel will write the header.
+ * Otherwise write the header now
+ */
+ if (!BIO_get_ktls_send(s->wbio)
+ && (!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))) {
+ &compressdata)))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
ERR_R_INTERNAL_ERROR);
goto err;
@@ -895,15 +919,20 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
goto err;
}
} else {
- if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
- goto err;
+ if (BIO_get_ktls_send(s->wbio)) {
+ SSL3_RECORD_reset_data(&wr[j]);
+ } else {
+ if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ SSL3_RECORD_reset_input(&wr[j]);
}
- SSL3_RECORD_reset_input(&wr[j]);
}
if (SSL_TREAT_AS_TLS13(s)
+ && !BIO_get_ktls_send(s->wbio)
&& s->enc_write_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| type != SSL3_RT_ALERT)) {
@@ -959,7 +988,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
* in the wb->buf
*/
- if (!SSL_WRITE_ETM(s) && mac_size != 0) {
+ if (!BIO_get_ktls_send(s->wbio) && !SSL_WRITE_ETM(s) && mac_size != 0) {
unsigned char *mac;
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
@@ -975,24 +1004,26 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
* 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
- */
+ if (!BIO_get_ktls_send(s->wbio)) {
+ 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)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
ERR_R_INTERNAL_ERROR);
goto err;
- }
-
- /* Get a pointer to the start of this record excluding header */
- recordstart = WPACKET_get_curr(thispkt) - len;
+ }
- SSL3_RECORD_set_data(thiswr, recordstart);
- SSL3_RECORD_reset_input(thiswr);
- SSL3_RECORD_set_length(thiswr, len);
+ /* Get a pointer to the start of this record excluding header */
+ recordstart = WPACKET_get_curr(thispkt) - len;
+ SSL3_RECORD_set_data(thiswr, recordstart);
+ SSL3_RECORD_reset_input(thiswr);
+ SSL3_RECORD_set_length(thiswr, len);
+ }
}
if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
@@ -1008,12 +1039,14 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
goto err;
}
} else {
- if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) {
- if (!ossl_statem_in_error(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ if (!BIO_get_ktls_send(s->wbio)) {
+ if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) {
+ if (!ossl_statem_in_error(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
+ ERR_R_INTERNAL_ERROR);
+ }
+ goto err;
}
- goto err;
}
}
@@ -1023,13 +1056,17 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
thispkt = &pkt[j];
thiswr = &wr[j];
+ if (BIO_get_ktls_send(s->wbio))
+ goto mac_done;
+
/* 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))) {
+ thiswr->length - origlen,
+ NULL))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
ERR_R_INTERNAL_ERROR);
goto err;
@@ -1074,13 +1111,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
goto err;
}
- /*
- * we should now have thiswr->data pointing to the encrypted data, which
- * is thiswr->length long
- */
- SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
- * debugging */
- SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH);
+ /* header is added by the kernel when using offload */
+ SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
if (create_empty_fragment) {
/*
@@ -1097,6 +1129,14 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
return 1;
}
+ mac_done:
+ /*
+ * we should now have thiswr->data pointing to the encrypted data, which
+ * is thiswr->length long
+ */
+ SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
+ * debugging */
+
/* now let's set up wb */
SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
prefix_len + SSL3_RECORD_get_length(thiswr));
@@ -1150,6 +1190,17 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
clear_sys_error();
if (s->wbio != NULL) {
s->rwstate = SSL_WRITING;
+
+ /*
+ * To prevent coalescing of control and data messages,
+ * such as in buffer_write, we flush the BIO
+ */
+ if (BIO_get_ktls_send(s->wbio) && type != SSL3_RT_APPLICATION_DATA) {
+ i = BIO_flush(s->wbio);
+ if (i <= 0)
+ return i;
+ BIO_set_ktls_ctrl_msg(s->wbio, type);
+ }
/* TODO(size_t): Convert this call */
i = BIO_write(s->wbio, (char *)
&(SSL3_BUFFER_get_buf(&wb[currbuf])
@@ -1162,7 +1213,15 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
SSL_R_BIO_NOT_SET);
i = -1;
}
- if (i > 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
+
+ /*
+ * When an empty fragment is sent on a connection using KTLS,
+ * it is sent as a write of zero bytes. If this zero byte
+ * write succeeds, i will be 0 rather than a non-zero value.
+ * Treat i == 0 as success rather than an error for zero byte
+ * writes to permit this case.
+ */
+ if (i >= 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
SSL3_BUFFER_set_left(&wb[currbuf], 0);
SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
if (currbuf + 1 < s->rlayer.numwpipes)
diff --git a/crypto/openssl/ssl/record/record.h b/crypto/openssl/ssl/record/record.h
index af56206e07c9..10fdde71a8d2 100644
--- a/crypto/openssl/ssl/record/record.h
+++ b/crypto/openssl/ssl/record/record.h
@@ -25,6 +25,8 @@ typedef struct ssl3_buffer_st {
size_t offset;
/* how many bytes left */
size_t left;
+ /* 'buf' is from application for KTLS */
+ int app_buffer;
} SSL3_BUFFER;
#define SEQ_NUM_SIZE 8
diff --git a/crypto/openssl/ssl/record/record_local.h b/crypto/openssl/ssl/record/record_local.h
index 5e8dd7f70442..4760eeb7d88b 100644
--- a/crypto/openssl/ssl/record/record_local.h
+++ b/crypto/openssl/ssl/record/record_local.h
@@ -65,6 +65,8 @@ void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
+#define SSL3_BUFFER_set_app_buffer(b, l) ((b)->app_buffer = (l))
+#define SSL3_BUFFER_is_app_buffer(b) ((b)->app_buffer)
void SSL3_BUFFER_clear(SSL3_BUFFER *b);
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n);
@@ -88,6 +90,7 @@ int ssl3_release_write_buffer(SSL *s);
#define SSL3_RECORD_get_input(r) ((r)->input)
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
+#define SSL3_RECORD_reset_data(r) ((r)->data = (r)->input)
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
#define SSL3_RECORD_get_off(r) ((r)->off)
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
diff --git a/crypto/openssl/ssl/record/ssl3_buffer.c b/crypto/openssl/ssl/record/ssl3_buffer.c
index 9b2a6964c689..fef54e01f372 100644
--- a/crypto/openssl/ssl/record/ssl3_buffer.c
+++ b/crypto/openssl/ssl/record/ssl3_buffer.c
@@ -111,23 +111,27 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
for (currpipe = 0; currpipe < numwpipes; currpipe++) {
SSL3_BUFFER *thiswb = &wb[currpipe];
- if (thiswb->buf != NULL && thiswb->len != len) {
+ if (thiswb->len != len) {
OPENSSL_free(thiswb->buf);
thiswb->buf = NULL; /* force reallocation */
}
if (thiswb->buf == NULL) {
- p = OPENSSL_malloc(len);
- if (p == NULL) {
- s->rlayer.numwpipes = currpipe;
- /*
- * We've got a malloc failure, and we're still initialising
- * buffers. We assume we're so doomed that we won't even be able
- * to send an alert.
- */
- SSLfatal(s, SSL_AD_NO_ALERT,
- SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
- return 0;
+ if (s->wbio == NULL || !BIO_get_ktls_send(s->wbio)) {
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ s->rlayer.numwpipes = currpipe;
+ /*
+ * We've got a malloc failure, and we're still initialising
+ * buffers. We assume we're so doomed that we won't even be able
+ * to send an alert.
+ */
+ SSLfatal(s, SSL_AD_NO_ALERT,
+ SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ p = NULL;
}
memset(thiswb, 0, sizeof(SSL3_BUFFER));
thiswb->buf = p;
@@ -160,7 +164,10 @@ int ssl3_release_write_buffer(SSL *s)
while (pipes > 0) {
wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
- OPENSSL_free(wb->buf);
+ if (SSL3_BUFFER_is_app_buffer(wb))
+ SSL3_BUFFER_set_app_buffer(wb, 0);
+ else
+ OPENSSL_free(wb->buf);
wb->buf = NULL;
pipes--;
}
diff --git a/crypto/openssl/ssl/record/ssl3_record.c b/crypto/openssl/ssl/record/ssl3_record.c
index ab5d22aa10cb..3d747db64bd8 100644
--- a/crypto/openssl/ssl/record/ssl3_record.c
+++ b/crypto/openssl/ssl/record/ssl3_record.c
@@ -186,9 +186,11 @@ int ssl3_get_record(SSL *s)
size_t num_recs = 0, max_recs, j;
PACKET pkt, sslv2pkt;
size_t first_rec_len;
+ int is_ktls_left;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+ is_ktls_left = (rbuf->left > 0);
max_recs = s->max_pipelines;
if (max_recs == 0)
max_recs = 1;
@@ -207,8 +209,32 @@ int ssl3_get_record(SSL *s)
rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(rbuf), 0,
num_recs == 0 ? 1 : 0, &n);
- if (rret <= 0)
- return rret; /* error or non-blocking */
+ if (rret <= 0) {
+#ifndef OPENSSL_NO_KTLS
+ if (!BIO_get_ktls_recv(s->rbio) || rret == 0)
+ return rret; /* error or non-blocking */
+ switch (errno) {
+ case EBADMSG:
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_F_SSL3_GET_RECORD,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ break;
+ case EMSGSIZE:
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
+ SSL_F_SSL3_GET_RECORD,
+ SSL_R_PACKET_LENGTH_TOO_LONG);
+ break;
+ case EINVAL:
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_SSL3_GET_RECORD,
+ SSL_R_WRONG_VERSION_NUMBER);
+ break;
+ default:
+ break;
+ }
+#endif
+ return rret;
+ }
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
@@ -386,7 +412,7 @@ int ssl3_get_record(SSL *s)
len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
- if (thisrr->length > len) {
+ if (thisrr->length > len && !BIO_get_ktls_recv(s->rbio)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
@@ -404,6 +430,7 @@ int ssl3_get_record(SSL *s)
} else {
more = thisrr->length;
}
+
if (more > 0) {
/* now s->packet_length == SSL3_RT_HEADER_LENGTH */
@@ -492,6 +519,13 @@ int ssl3_get_record(SSL *s)
}
/*
+ * KTLS reads full records. If there is any data left,
+ * then it is from before enabling ktls
+ */
+ if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
+ goto skip_decryption;
+
+ /*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
*/
@@ -678,6 +712,8 @@ int ssl3_get_record(SSL *s)
return -1;
}
+ skip_decryption:
+
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
@@ -739,7 +775,7 @@ int ssl3_get_record(SSL *s)
return -1;
}
- if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+ if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH && !BIO_get_ktls_recv(s->rbio)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_DATA_LENGTH_TOO_LONG);
return -1;
@@ -747,7 +783,8 @@ int ssl3_get_record(SSL *s)
/* If received packet overflows current Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
- && thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
+ && thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)
+ && !BIO_get_ktls_recv(s->rbio)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
SSL_R_DATA_LENGTH_TOO_LONG);
return -1;