BIO_ADDR_clear(client);
/* Buffer the record in the processed_rcds queue */
+ /* TODO(RECLAYER): This is nasty and reaches inside the record layer. FIXME */
if (!dtls_buffer_listen_record(s, reclen, seq, align))
return -1;
SOURCE[../../libssl]=\
rec_layer_s3.c rec_layer_d1.c ssl3_buffer.c ssl3_record.c \
- dtls1_bitmap.c ssl3_record_tls13.c
+ ssl3_record_tls13.c
# For shared builds we need to include the sources needed in providers
# (tls_pad.c) in libssl as well.
SOURCE[../../../libssl]=\
tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c \
- $KTLSSRC
+ dtls_meth.c $KTLSSRC
# For shared builds we need to include the sources needed in providers
# (ssl3_cbc.c) in libssl as well.
--- /dev/null
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "../../ssl_local.h"
+#include "../record_local.h"
+#include "recmethod_local.h"
+
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+{
+ int64_t ret;
+ uint64_t l1, l2;
+
+ n2l8(v1, l1);
+ n2l8(v2, l2);
+
+ ret = l1 - l2;
+
+ /* We do not permit wrap-around */
+ if (l1 > l2 && ret < 0)
+ return 128;
+ else if (l2 > l1 && ret > 0)
+ return -128;
+
+ if (ret > 128)
+ return 128;
+ else if (ret < -128)
+ return -128;
+ else
+ return (int)ret;
+}
+
+static int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = s->rlayer.read_sequence;
+ OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ SSL3_RECORD_set_seq_num(&rl->rrec[0], seq);
+ return 1; /* this record in new */
+ }
+ shift = -cmp;
+ if (shift >= sizeof(bitmap->map) * 8)
+ return 0; /* stale, outside the window */
+ else if (bitmap->map & (1UL << shift))
+ return 0; /* record previously received */
+
+ SSL3_RECORD_set_seq_num(&rl->rrec[0], seq);
+ return 1;
+}
+
+static void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ shift = cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map <<= shift, bitmap->map |= 1UL;
+ else
+ bitmap->map = 1UL;
+ memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE);
+ } else {
+ shift = -cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map |= 1UL << shift;
+ }
+}
+
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch)
+{
+ OSSL_RECORD_LAYER *rl = s->rrl;
+ *is_next_epoch = 0;
+
+ /* In current epoch, accept HM, CCS, DATA, & ALERT */
+ if (rr->epoch == s->rlayer.d->r_epoch)
+ return &s->rlayer.d->bitmap;
+
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
+ else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
+ rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
+ (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+ *is_next_epoch = 1;
+ return &s->rlayer.d->next_bitmap;
+ }
+
+ return NULL;
+}
+
+static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
+{
+ int i;
+ int enc_err;
+ SSL_SESSION *sess;
+ SSL3_RECORD *rr;
+ int imac_size;
+ size_t mac_size = 0;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
+ SSL_MAC_BUF macbuf = { NULL, 0 };
+ int ret = 0;
+ OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+ SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+ rr = &rl->rrec[0];
+ sess = s->session;
+
+ /*
+ * At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+ * and we have that many bytes in s->rlayer.packet
+ */
+ rr->input = &(s->rrlmethod->get0_packet(s->rrl)[DTLS1_RT_HEADER_LENGTH]);
+
+ /*
+ * ok, we can now read from 's->rlayer.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) {
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ /* decrypt in place in 'rr->input' */
+ rr->data = rr->input;
+ rr->orig_len = rr->length;
+
+ if (s->read_hash != NULL) {
+ const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
+
+ if (tmpmd != NULL) {
+ imac_size = EVP_MD_get_size(tmpmd);
+ if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+ mac_size = (size_t)imac_size;
+ }
+ }
+
+ if (SSL_READ_ETM(s) && s->read_hash) {
+ unsigned char *mac;
+
+ if (rr->orig_len < mac_size) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
+ return 0;
+ }
+ rr->length -= mac_size;
+ mac = rr->data + rr->length;
+ i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
+ if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ return 0;
+ }
+ /*
+ * We've handled the mac now - there is no MAC inside the encrypted
+ * record
+ */
+ mac_size = 0;
+ }
+
+ /*
+ * Set a mark around the packet decryption attempt. This is DTLS, so
+ * bad packets are just ignored, and we don't want to leave stray
+ * errors in the queue from processing bogus junk that we ignored.
+ */
+ ERR_set_mark();
+ enc_err = ssl->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
+
+ /*-
+ * enc_err is:
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or ETM decryption failed.
+ * 1: Success or MTE decryption failed (MAC will be randomised)
+ */
+ if (enc_err == 0) {
+ ERR_pop_to_mark();
+ if (ossl_statem_in_error(s)) {
+ /* SSLfatal() got called */
+ goto end;
+ }
+ /* For DTLS we simply ignore bad packets. */
+ rr->length = 0;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto end;
+ }
+ ERR_clear_last_mark();
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "dec %zd\n", rr->length);
+ BIO_dump_indent(trc_out, rr->data, rr->length, 4);
+ } OSSL_TRACE_END(TLS);
+
+ /* r->length is now the compressed data plus mac */
+ if ((sess != NULL)
+ && !SSL_READ_ETM(s)
+ && (s->enc_read_ctx != NULL)
+ && (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
+ /* s->read_hash != NULL => mac_size != -1 */
+
+ i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
+ if (i == 0 || macbuf.mac == NULL
+ || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
+ enc_err = 0;
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+ enc_err = 0;
+ }
+
+ if (enc_err == 0) {
+ /* decryption failed, silently discard message */
+ rr->length = 0;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto end;
+ }
+
+ /* r->length is now just compressed */
+ if (s->expand != NULL) {
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
+ SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+ goto end;
+ }
+ if (!ssl3_do_uncompress(s, rr)) {
+ SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
+ goto end;
+ }
+ }
+
+ /* use current Max Fragment Length setting if applicable */
+ if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
+ max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
+
+ /* send overflow if the plaintext is too long now it has passed MAC */
+ if (rr->length > max_plain_length) {
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
+ }
+
+ 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->rrlmethod->reset_packet_length(s->rrl);
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
+ ret = 1;
+ end:
+ if (macbuf.alloced)
+ OPENSSL_free(macbuf.mac);
+ return ret;
+}
+
+static int dtls_rlayer_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
+ unsigned char *priority)
+{
+ DTLS_RLAYER_RECORD_DATA *rdata;
+ pitem *item;
+ OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
+
+ /* Limit the size of the queue to prevent DOS attacks */
+ if (pqueue_size(queue->q) >= 100)
+ return 0;
+
+ rdata = OPENSSL_malloc(sizeof(*rdata));
+ item = pitem_new(priority, rdata);
+ if (rdata == NULL || item == NULL) {
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ rdata->packet = s->rrlmethod->get0_packet(s->rrl);
+ rdata->packet_length = s->rrlmethod->get_packet_length(s->rrl);
+ memcpy(&(rdata->rbuf), s->rrlmethod->get0_rbuf(s->rrl), sizeof(SSL3_BUFFER));
+ memcpy(&(rdata->rrec), &rl->rrec[0], sizeof(SSL3_RECORD));
+
+ item->data = rdata;
+
+ s->rrlmethod->set0_packet(s->rrl, NULL, 0);
+ memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
+ memset(&rl->rrec[0], 0, sizeof(rl->rrec[0]));
+
+ if (!ssl3_setup_buffers(s)) {
+ /* SSLfatal() already called */
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return -1;
+ }
+
+ if (pqueue_insert(queue->q, item) == NULL) {
+ /* Must be a duplicate so ignore it */
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ }
+
+ return 1;
+}
+
+/* copy buffered record into SSL structure */
+static int dtls_copy_rlayer_record(OSSL_RECORD_LAYER *rl, pitem *item)
+{
+ DTLS_RLAYER_RECORD_DATA *rdata;
+ SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
+
+ rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+
+ SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
+
+ s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
+ memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&rl->rrec[0], &(rdata->rrec), sizeof(SSL3_RECORD));
+
+ /* Set proper sequence number for mac calculation */
+ memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
+
+ return 1;
+}
+
+static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl,
+ record_pqueue *queue)
+{
+ pitem *item;
+
+ item = pqueue_pop(queue->q);
+ if (item) {
+ dtls_copy_rlayer_record(rl, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
+{
+ pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
+ OSSL_RECORD_LAYER *rl = s->rrl;
+
+ item = pqueue_peek(rl->unprocessed_rcds.q);
+ if (item) {
+ /* Check if epoch is current. */
+ if (rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
+ return 1; /* Nothing to do. */
+
+ rr = rl->rrec;
+
+ rb = s->rrlmethod->get0_rbuf(s->rrl);
+
+ if (SSL3_BUFFER_get_left(rb) > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
+ /* Process all the records. */
+ while (pqueue_peek(rl->unprocessed_rcds.q)) {
+ dtls_retrieve_rlayer_buffered_record(rl, &(rl->unprocessed_rcds));
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ if (ossl_statem_in_error(s)) {
+ /* dtls1_process_record called SSLfatal() */
+ return 0;
+ }
+ /* dump this record */
+ rr->length = 0;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ continue;
+ }
+
+ if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
+ SSL3_RECORD_get_seq_num(&rl->rrec[0])) < 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * sync epoch numbers once all the unprocessed records have been
+ * processed
+ */
+ rl->processed_rcds.epoch = s->rlayer.d->r_epoch;
+ rl->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
+
+ return 1;
+}
+
+int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq, size_t off)
+{
+ SSL3_RECORD *rr;
+ OSSL_RECORD_LAYER *rl = s->rrl;
+
+ rr = &rl->rrec[0];
+ memset(rr, 0, sizeof(SSL3_RECORD));
+
+ rr->length = len;
+ rr->type = SSL3_RT_HANDSHAKE;
+ memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
+ rr->off = off;
+
+ s->rrlmethod->set0_packet(s->rrl, s->rrlmethod->get0_rbuf(s->rrl)->buf,
+ DTLS1_RT_HEADER_LENGTH + len);
+ rr->data = s->rrlmethod->get0_packet(s->rrl) + DTLS1_RT_HEADER_LENGTH;
+
+ if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
+ SSL3_RECORD_get_seq_num(rr)) <= 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-
+ * 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 dtls1_read_bytes */
+static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
+{
+ int ssl_major, ssl_minor;
+ int rret;
+ size_t more, n;
+ SSL3_RECORD *rr;
+ unsigned char *p = NULL;
+ unsigned short version;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
+ SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+ rl->num_recs = 0;
+ rl->curr_rec = 0;
+ rl->num_released = 0;
+
+ rr = rl->rrec;
+
+ again:
+ /*
+ * The epoch may have changed. If so, process all the pending records.
+ * This is a non-blocking operation.
+ */
+ if (!dtls_process_rlayer_buffered_records(s)) {
+ /* SSLfatal() already called */
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+
+ /* if we're renegotiating, then there may be buffered records */
+ if (dtls_retrieve_rlayer_buffered_record(rl, &rl->processed_rcds)) {
+ rl->num_recs = 1;
+ return OSSL_RECORD_RETURN_SUCCESS;
+ }
+
+ /* get something from the wire */
+
+ /* check if we have the header */
+ if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+ (s->rrlmethod->get_packet_length(s->rrl) < DTLS1_RT_HEADER_LENGTH)) {
+ rret = s->rrlmethod->read_n(s->rrl, DTLS1_RT_HEADER_LENGTH,
+ SSL3_BUFFER_get_len(s->rrlmethod->get0_rbuf(s->rrl)),
+ 0, 1, &n);
+ /* read timeout is handled by dtls1_read_bytes */
+ if (rret < OSSL_RECORD_RETURN_SUCCESS) {
+ /* SSLfatal() already called if appropriate */
+ return rret; /* error or non-blocking */
+ }
+
+ /* this packet contained a partial record, dump it */
+ if (s->rrlmethod->get_packet_length(s->rrl) != DTLS1_RT_HEADER_LENGTH) {
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+ p = s->rrlmethod->get0_packet(s->rrl);
+
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
+ ssl, s->msg_callback_arg);
+
+ /* Pull apart the header into the DTLS1_RECORD */
+ rr->type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+
+ /* sequence number is 64 bits, with top 2 bytes = epoch */
+ n2s(p, rr->epoch);
+
+ memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
+ p += 6;
+
+ n2s(p, rr->length);
+ rr->read = 0;
+
+ /*
+ * Lets check the version. We tolerate alerts that don't have the exact
+ * version number (e.g. because of protocol version errors)
+ */
+ if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
+ if (version != s->version) {
+ /* unexpected version, silently discard */
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+ }
+
+ if ((version & 0xff00) != (s->version & 0xff00)) {
+ /* wrong version, silently discard record */
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ /* record too long, silently discard it */
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ /* If received packet overflows own-client Max Fragment Length setting */
+ if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
+ && rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
+ /* record too long, silently discard it */
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+ }
+
+ /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
+
+ if (rr->length >
+ s->rrlmethod->get_packet_length(s->rrl) - DTLS1_RT_HEADER_LENGTH) {
+ /* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
+ more = rr->length;
+ rret = s->rrlmethod->read_n(s->rrl, more, more, 1, 1, &n);
+ /* this packet contained a partial record, dump it */
+ if (rret < OSSL_RECORD_RETURN_SUCCESS || n != more) {
+ if (ossl_statem_in_error(s)) {
+ /* read_n() called SSLfatal() */
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ /*
+ * now n == rr->length, and s->rlayer.packet_length ==
+ * DTLS1_RT_HEADER_LENGTH + rr->length
+ */
+ }
+ /* set state for later operations */
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+ /* match epochs. NULL means the packet is dropped on the floor */
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ rr->length = 0;
+ s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+ goto again; /* get another record */
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+#endif
+ /* Check whether this is a repeat, or aged record. */
+ if (!dtls1_record_replay_check(s, bitmap)) {
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+ goto again; /* get another record */
+ }
+#ifndef OPENSSL_NO_SCTP
+ }
+#endif
+
+ /* just read a 0 length packet */
+ if (rr->length == 0) {
+ rr->read = 1;
+ goto again;
+ }
+
+ /*
+ * If this record is from the next epoch (either HM or ALERT), and a
+ * handshake is currently in progress, buffer it since it cannot be
+ * processed at this time.
+ */
+ if (is_next_epoch) {
+ if ((SSL_in_init(ssl) || ossl_statem_get_in_handshake(s))) {
+ if (dtls_rlayer_buffer_record (s,
+ &(rl->unprocessed_rcds),
+ rr->seq_num) < 0) {
+ /* SSLfatal() already called */
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ }
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl);
+ goto again;
+ }
+
+ if (!dtls1_process_record(s, bitmap)) {
+ if (ossl_statem_in_error(s)) {
+ /* dtls1_process_record() called SSLfatal */
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ rr->length = 0;
+ rr->read = 1;
+ s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
+ goto again; /* get another record */
+ }
+
+ rl->num_recs = 1;
+ return OSSL_RECORD_RETURN_SUCCESS;
+
+}
+
+static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
+{
+ rl->version = version;
+ return 1;
+}
+
+static struct record_functions_st dtls_funcs = {
+ NULL,
+ NULL,
+ dtls_get_more_records,
+ NULL,
+ NULL,
+ dtls_set_protocol_version,
+ NULL
+};
+
+static int dtls_free(OSSL_RECORD_LAYER *rl)
+{
+ pitem *item;
+ DTLS_RLAYER_RECORD_DATA *rdata;
+
+ if (rl->unprocessed_rcds.q == NULL) {
+ while ((item = pqueue_pop(rl->unprocessed_rcds.q)) != NULL) {
+ rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ pqueue_free(rl->unprocessed_rcds.q);
+ }
+
+ if (rl->processed_rcds.q == NULL) {
+ while ((item = pqueue_pop(rl->processed_rcds.q)) != NULL) {
+ rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ pqueue_free(rl->processed_rcds.q);
+ }
+
+ return tls_free(rl);
+}
+
+static int
+dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+ int role, int direction, int level, unsigned char *key,
+ size_t keylen, unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph, size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+ BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
+ const OSSL_PARAM *settings, const OSSL_PARAM *options,
+ const OSSL_DISPATCH *fns, void *cbarg,
+ OSSL_RECORD_LAYER **retrl)
+{
+ int ret;
+
+
+ ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
+ key, keylen, iv, ivlen, mackey, mackeylen,
+ ciph, taglen, mactype, md, comp, prev,
+ transport, next, local, peer, settings,
+ options, fns, cbarg, retrl);
+
+ if (ret != OSSL_RECORD_RETURN_SUCCESS)
+ return ret;
+
+ (*retrl)->unprocessed_rcds.q = pqueue_new();
+ (*retrl)->processed_rcds.q = pqueue_new();
+ if ((*retrl)->unprocessed_rcds.q == NULL || (*retrl)->processed_rcds.q == NULL) {
+ dtls_free(*retrl);
+ *retrl = NULL;
+ RLAYERfatal(*retrl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+
+ (*retrl)->isdtls = 1;
+ (*retrl)->funcs = &dtls_funcs;
+
+ return OSSL_RECORD_RETURN_SUCCESS;
+}
+
+const OSSL_RECORD_METHOD ossl_dtls_record_method = {
+ dtls_new_record_layer,
+ dtls_free,
+ tls_reset,
+ tls_unprocessed_read_pending,
+ tls_processed_read_pending,
+ tls_app_data_pending,
+ tls_write_pending,
+ tls_get_max_record_len,
+ tls_get_max_records,
+ tls_write_records,
+ tls_retry_write_records,
+ tls_read_record,
+ tls_release_record,
+ tls_get_alert_code,
+ tls_set1_bio,
+ tls_set_protocol_version,
+ NULL,
+ tls_set_first_handshake,
+ tls_set_max_pipelines,
+
+ /*
+ * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
+ * during the record layer refactoring. They need to be removed before the
+ * refactor is complete.
+ */
+ tls_default_read_n,
+ tls_get0_rbuf,
+ tls_get0_packet,
+ tls_set0_packet,
+ tls_get_packet_length,
+ tls_reset_packet_length
+};
static struct record_functions_st ossl_ktls_funcs = {
ktls_set_crypto_state,
ktls_read_n,
+ tls_get_more_records,
ktls_cipher,
NULL,
tls_default_set_protocol_version,
int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
+
+ int (*get_more_records)(OSSL_RECORD_LAYER *rl);
+
/*
* Returns:
* 0: if the record is publicly invalid, or an internal error, or AEAD
size_t taglen;
+ /* DTLS eceived handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+
/* Callbacks */
void *cbarg;
OSSL_FUNC_rlayer_skip_early_data_fn *skip_early_data;
struct record_functions_st *funcs;
};
+typedef struct dtls_rlayer_record_data_st {
+ unsigned char *packet;
+ size_t packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+} DTLS_RLAYER_RECORD_DATA;
+
+
extern struct record_functions_st ssl_3_0_funcs;
extern struct record_functions_st tls_1_funcs;
extern struct record_functions_st tls_1_3_funcs;
int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
+int tls_get_more_records(OSSL_RECORD_LAYER *rl);
int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *re);
struct record_functions_st ssl_3_0_funcs = {
ssl3_set_crypto_state,
tls_default_read_n,
+ tls_get_more_records,
ssl3_cipher,
ssl3_mac,
tls_default_set_protocol_version,
struct record_functions_st tls_1_3_funcs = {
tls13_set_crypto_state,
tls_default_read_n,
+ tls_get_more_records,
tls13_cipher,
NULL,
tls_default_set_protocol_version,
struct record_functions_st tls_1_funcs = {
tls1_set_crypto_state,
tls_default_read_n,
+ tls_get_more_records,
tls1_cipher,
tls1_mac,
tls_default_set_protocol_version,
* SSL3_RT_APPLICATION_DATA. The number of records returned will always be <=
* |max_pipelines|
*/
-static int tls_get_more_records(OSSL_RECORD_LAYER *rl)
+int tls_get_more_records(OSSL_RECORD_LAYER *rl)
{
int enc_err, rret;
int i;
return OSSL_RECORD_RETURN_FATAL;
}
- ret = tls_get_more_records(rl);
+ ret = rl->funcs->get_more_records(rl);
if (ret != OSSL_RECORD_RETURN_SUCCESS)
return ret;
*rechandle = rec;
*rversion = rec->rec_version;
*type = rec->type;
- *data = rec->data;
+ *data = rec->data + rec->off;
*datalen = rec->length;
+ if (rl->isdtls) {
+ *epoch = (uint16_t)rec->epoch;
+ memcpy(seq_num, rec->seq_num, sizeof(rec->seq_num));
+ }
return OSSL_RECORD_RETURN_SUCCESS;
}
return ret;
}
-/* TODO(RECLAYER): Temporary funcs */
-static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
-{
- rl->version = version;
- return 1;
-}
-static struct record_functions_st dtls_funcs = {
- NULL,
- NULL,
- NULL,
- NULL,
- dtls_set_protocol_version,
- NULL
-};
-
-static int
-dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
- int role, int direction, int level, unsigned char *key,
- size_t keylen, unsigned char *iv, size_t ivlen,
- unsigned char *mackey, size_t mackeylen,
- const EVP_CIPHER *ciph, size_t taglen,
- /* TODO(RECLAYER): This probably should not be an int */
- int mactype,
- const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
- BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
- const OSSL_PARAM *settings, const OSSL_PARAM *options,
- const OSSL_DISPATCH *fns, void *cbarg,
- OSSL_RECORD_LAYER **retrl)
-{
- int ret;
-
-
- ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
- key, keylen, iv, ivlen, mackey, mackeylen,
- ciph, taglen, mactype, md, comp, prev,
- transport, next, local, peer, settings,
- options, fns, cbarg, retrl);
-
- if (ret != OSSL_RECORD_RETURN_SUCCESS)
- return ret;
-
- (*retrl)->isdtls = 1;
- (*retrl)->funcs = &dtls_funcs;
-
- return OSSL_RECORD_RETURN_SUCCESS;
-}
-
static void tls_int_free(OSSL_RECORD_LAYER *rl)
{
/* TODO(RECLAYER): Cleanse sensitive fields */
tls_get_packet_length,
tls_reset_packet_length
};
-
-const OSSL_RECORD_METHOD ossl_dtls_record_method = {
- dtls_new_record_layer,
- tls_free,
- tls_reset,
- tls_unprocessed_read_pending,
- tls_processed_read_pending,
- tls_app_data_pending,
- tls_write_pending,
- tls_get_max_record_len,
- tls_get_max_records,
- tls_write_records,
- tls_retry_write_records,
- tls_read_record,
- tls_release_record,
- tls_get_alert_code,
- tls_set1_bio,
- tls_set_protocol_version,
- NULL,
- tls_set_first_handshake,
- tls_set_max_pipelines,
-
- /*
- * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
- * during the record layer refactoring. They need to be removed before the
- * refactor is complete.
- */
- tls_default_read_n,
- tls_get0_rbuf,
- tls_get0_packet,
- tls_set0_packet,
- tls_get_packet_length,
- tls_reset_packet_length
-};
struct record_functions_st tls_any_funcs = {
tls_any_set_crypto_state,
tls_default_read_n,
+ tls_get_more_records,
tls_any_cipher,
NULL,
tls_any_set_protocol_version,
rl->d = d;
- d->unprocessed_rcds.q = pqueue_new();
- d->processed_rcds.q = pqueue_new();
d->buffered_app_data.q = pqueue_new();
- if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL
- || d->buffered_app_data.q == NULL) {
- pqueue_free(d->unprocessed_rcds.q);
- pqueue_free(d->processed_rcds.q);
- pqueue_free(d->buffered_app_data.q);
+ if (d->buffered_app_data.q == NULL) {
OPENSSL_free(d);
rl->d = NULL;
return 0;
return;
DTLS_RECORD_LAYER_clear(rl);
- pqueue_free(rl->d->unprocessed_rcds.q);
- pqueue_free(rl->d->processed_rcds.q);
pqueue_free(rl->d->buffered_app_data.q);
OPENSSL_free(rl->d);
rl->d = NULL;
{
DTLS_RECORD_LAYER *d;
pitem *item = NULL;
- DTLS1_RECORD_DATA *rdata;
- pqueue *unprocessed_rcds;
- pqueue *processed_rcds;
+ TLS_RECORD *rec;
pqueue *buffered_app_data;
d = rl->d;
- while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- OPENSSL_free(rdata->rbuf.buf);
- OPENSSL_free(item->data);
- pitem_free(item);
- }
-
- while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
- OPENSSL_free(rdata->rbuf.buf);
- OPENSSL_free(item->data);
- pitem_free(item);
- }
-
while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
+ rec = (TLS_RECORD *)item->data;
if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
- OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_cleanse(rec->data, rec->length);
+ OPENSSL_free(rec->data);
OPENSSL_free(item->data);
pitem_free(item);
}
- unprocessed_rcds = d->unprocessed_rcds.q;
- processed_rcds = d->processed_rcds.q;
buffered_app_data = d->buffered_app_data.q;
memset(d, 0, sizeof(*d));
- d->unprocessed_rcds.q = unprocessed_rcds;
- d->processed_rcds.q = processed_rcds;
d->buffered_app_data.q = buffered_app_data;
}
memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
}
-/* copy buffered record into SSL structure */
-static int dtls1_copy_record(SSL_CONNECTION *s, pitem *item)
+int dtls_buffer_record(SSL_CONNECTION *s, TLS_RECORD *rec)
{
- DTLS1_RECORD_DATA *rdata;
-
- rdata = (DTLS1_RECORD_DATA *)item->data;
-
- SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
-
- s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
- memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
- memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
-
- /* Set proper sequence number for mac calculation */
- memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
-
- return 1;
-}
-
-int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
- unsigned char *priority)
-{
- DTLS1_RECORD_DATA *rdata;
+ TLS_RECORD *rdata;
pitem *item;
-#ifndef OPENSSL_NO_SCTP
- SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-#endif
+ record_pqueue *queue = &(s->rlayer.d->buffered_app_data);
/* Limit the size of the queue to prevent DOS attacks */
if (pqueue_size(queue->q) >= 100)
return 0;
+ /* We don't buffer partially read records */
+ if (!ossl_assert(rec->off == 0))
+ return -1;
+
rdata = OPENSSL_malloc(sizeof(*rdata));
- item = pitem_new(priority, rdata);
+ item = pitem_new(rec->seq_num, rdata);
if (rdata == NULL || item == NULL) {
OPENSSL_free(rdata);
pitem_free(item);
return -1;
}
- rdata->packet = s->rrlmethod->get0_packet(s->rrl);
- rdata->packet_length = s->rrlmethod->get_packet_length(s->rrl);
- memcpy(&(rdata->rbuf), s->rrlmethod->get0_rbuf(s->rrl), sizeof(SSL3_BUFFER));
- memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
+ *rdata = *rec;
+ /*
+ * We will release the record from the record layer soon, so we take a copy
+ * now. Copying data isn't good - but this should be infrequent so we
+ * accept it here.
+ */
+ rdata->data = OPENSSL_memdup(rec->data, rec->length);
+ if (rdata->data == NULL) {
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ /*
+ * We use a NULL rechandle to indicate that the data field has been
+ * allocated by us.
+ */
+ rdata->rechandle = NULL;
item->data = rdata;
}
#endif
- s->rrlmethod->set0_packet(s->rrl, NULL, 0);
- memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
- memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));
-
- if (!ssl3_setup_buffers(s)) {
- /* SSLfatal() already called */
- OPENSSL_free(rdata->rbuf.buf);
- OPENSSL_free(rdata);
- pitem_free(item);
- return -1;
- }
-
if (pqueue_insert(queue->q, item) == NULL) {
/* Must be a duplicate so ignore it */
- OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata->data);
OPENSSL_free(rdata);
pitem_free(item);
}
return 1;
}
-int dtls1_retrieve_buffered_record(SSL_CONNECTION *s, record_pqueue *queue)
+/* Unbuffer a previously buffered TLS_RECORD structure if any */
+static void dtls_unbuffer_record(SSL_CONNECTION *s)
{
+ TLS_RECORD *rdata;
pitem *item;
- item = pqueue_pop(queue->q);
- if (item) {
- dtls1_copy_record(s, item);
-
- OPENSSL_free(item->data);
- pitem_free(item);
-
- return 1;
- }
-
- return 0;
-}
-
-/*
- * retrieve a buffered record that belongs to the new epoch, i.e., not
- * processed yet
- */
-#define dtls1_get_unprocessed_record(s) \
- dtls1_retrieve_buffered_record((s), \
- &((s)->rlayer.d->unprocessed_rcds))
-
-int dtls1_process_buffered_records(SSL_CONNECTION *s)
-{
- pitem *item;
- SSL3_BUFFER *rb;
- SSL3_RECORD *rr;
- DTLS1_BITMAP *bitmap;
- unsigned int is_next_epoch;
- int replayok = 1;
-
- item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
- if (item) {
- /* Check if epoch is current. */
- if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
- return 1; /* Nothing to do. */
+ /* If we already have records to handle then do nothing */
+ if (s->rlayer.curr_rec < s->rlayer.num_recs)
+ return;
- rr = RECORD_LAYER_get_rrec(&s->rlayer);
+ item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
+ if (item != NULL) {
+ rdata = (TLS_RECORD *)item->data;
- rb = s->rrlmethod->get0_rbuf(s->rrl);
+ s->rlayer.tlsrecs[0] = *rdata;
+ s->rlayer.num_recs = 1;
+ s->rlayer.curr_rec = 0;
- if (SSL3_BUFFER_get_left(rb) > 0) {
- /*
- * We've still got data from the current packet to read. There could
- * be a record from the new epoch in it - so don't overwrite it
- * with the unprocessed records yet (we'll do it when we've
- * finished reading the current packet).
- */
- return 1;
- }
-
- /* Process all the records. */
- while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
- dtls1_get_unprocessed_record(s);
- bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
- if (bitmap == NULL) {
- /*
- * Should not happen. This will only ever be NULL when the
- * current record is from a different epoch. But that cannot
- * be the case because we already checked the epoch above
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
- }
#ifndef OPENSSL_NO_SCTP
- /* Only do replay check if no SCTP bio */
- if (!BIO_dgram_is_sctp(SSL_get_rbio(SSL_CONNECTION_GET_SSL(s))))
+ /* Restore bio_dgram_sctp_rcvinfo struct */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+ DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
+ sizeof(rdata->recordinfo), &rdata->recordinfo);
+ }
#endif
- {
- /*
- * Check whether this is a repeat, or aged record. We did this
- * check once already when we first received the record - but
- * we might have updated the window since then due to
- * records we subsequently processed.
- */
- replayok = dtls1_record_replay_check(s, bitmap);
- }
- if (!replayok || !dtls1_process_record(s, bitmap)) {
- if (ossl_statem_in_error(s)) {
- /* dtls1_process_record called SSLfatal() */
- return 0;
- }
- /* dump this record */
- rr->length = 0;
- s->rrlmethod->reset_packet_length(s->rrl);
- continue;
- }
+ /* Set proper sequence number for mac calculation */
+ memcpy(&(s->rlayer.read_sequence[2]), &(rdata->seq_num[2]), 6);
- if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) {
- /* SSLfatal() already called */
- return 0;
- }
- }
+ OPENSSL_free(item->data);
+ pitem_free(item);
}
-
- /*
- * sync epoch numbers once all the unprocessed records have been
- * processed
- */
- s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
- s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
-
- return 1;
}
/*-
int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
size_t len, int peek, size_t *readbytes)
{
- int i, j, iret;
+ int i, j, ret;
size_t n;
- SSL3_RECORD *rr;
+ TLS_RECORD *rr;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
start:
sc->rwstate = SSL_NOTHING;
- /*-
- * 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.
- */
- rr = sc->rlayer.rrec;
-
/*
* We are not handshaking and have no data yet, so process data buffered
* during the last handshake in advance, if any.
*/
- if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
- pitem *item;
- item = pqueue_pop(sc->rlayer.d->buffered_app_data.q);
- if (item) {
-#ifndef OPENSSL_NO_SCTP
- /* Restore bio_dgram_sctp_rcvinfo struct */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
- DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
- sizeof(rdata->recordinfo), &rdata->recordinfo);
- }
-#endif
-
- dtls1_copy_record(sc, item);
-
- OPENSSL_free(item->data);
- pitem_free(item);
- }
- }
+ if (SSL_is_init_finished(s))
+ dtls_unbuffer_record(sc);
/* Check for timeout */
if (dtls1_handle_timeout(sc) > 0) {
}
/* get new packet if necessary */
- if ((SSL3_RECORD_get_length(rr) == 0)
- || (sc->rlayer.rstate == SSL_ST_READ_BODY)) {
- RECORD_LAYER_set_numrpipes(&sc->rlayer, 0);
- iret = dtls1_get_record(sc);
- if (iret <= 0) {
- iret = dtls1_read_failed(sc, iret);
- /*
- * Anything other than a timeout is an error. SSLfatal() already
- * called if appropriate.
- */
- if (iret <= 0)
- return iret;
- else
- goto start;
- }
- RECORD_LAYER_set_numrpipes(&sc->rlayer, 1);
+ if (sc->rlayer.curr_rec >= sc->rlayer.num_recs) {
+ sc->rlayer.curr_rec = sc->rlayer.num_recs = 0;
+ do {
+ rr = &sc->rlayer.tlsrecs[sc->rlayer.num_recs];
+
+ /* TODO(RECLAYER): Check HANDLE_RLAYER_RETURN for DTLS */
+ ret = HANDLE_RLAYER_RETURN(sc,
+ sc->rrlmethod->read_record(sc->rrl, &rr->rechandle,
+ &rr->version, &rr->type,
+ &rr->data, &rr->length,
+ &rr->epoch, rr->seq_num));
+ if (ret <= 0) {
+ ret = dtls1_read_failed(sc, ret);
+ /*
+ * Anything other than a timeout is an error. SSLfatal() already
+ * called if appropriate.
+ */
+ if (ret <= 0)
+ return ret;
+ else
+ goto start;
+ }
+ rr->off = 0;
+ sc->rlayer.num_recs++;
+ } while (sc->rrlmethod->processed_read_pending(sc->rrl)
+ && sc->rlayer.num_recs < SSL_MAX_PIPELINES);
}
+ rr = &sc->rlayer.tlsrecs[sc->rlayer.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)
+ if (rr->type != SSL3_RT_ALERT && rr->length != 0)
sc->rlayer.alert_count = 0;
/* we now have a packet which can be read and processed */
if (sc->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
* reset by ssl3_get_finished */
- && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
+ && (rr->type != SSL3_RT_HANDSHAKE)) {
/*
* We now have application data between CCS and Finished. Most likely
* the packets were reordered on their way, so buffer the application
* data for later processing rather than dropping the connection.
*/
- if (dtls1_buffer_record(sc, &(sc->rlayer.d->buffered_app_data),
- SSL3_RECORD_get_seq_num(rr)) < 0) {
+ if (dtls_buffer_record(sc, rr) < 0) {
/* SSLfatal() already called */
return -1;
}
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
goto start;
}
* 'peek' mode)
*/
if (sc->shutdown & SSL_RECEIVED_SHUTDOWN) {
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
sc->rwstate = SSL_NOTHING;
return 0;
}
- if (type == SSL3_RECORD_get_type(rr)
- || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ if (type == rr->type
+ || (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC
&& type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
/*
* SSL3_RT_APPLICATION_DATA or
}
if (recvd_type != NULL)
- *recvd_type = SSL3_RECORD_get_type(rr);
+ *recvd_type = rr->type;
if (len == 0) {
/*
- * Mark a zero length record as read. This ensures multiple calls to
+ * Release a zero length record. 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);
+ if (rr->length == 0)
+ ssl_release_record(sc, rr);
return 0;
}
- if (len > SSL3_RECORD_get_length(rr))
- n = SSL3_RECORD_get_length(rr);
+ if (len > rr->length)
+ n = rr->length;
else
n = len;
- memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
+ memcpy(buf, &(rr->data[rr->off]), n);
if (peek) {
- if (SSL3_RECORD_get_length(rr) == 0)
- SSL3_RECORD_set_read(rr);
+ if (rr->length == 0)
+ ssl_release_record(sc, rr);
} else {
if (sc->options & SSL_OP_CLEANSE_PLAINTEXT)
- OPENSSL_cleanse(&(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
- SSL3_RECORD_sub_length(rr, n);
- SSL3_RECORD_add_off(rr, n);
- if (SSL3_RECORD_get_length(rr) == 0) {
+ OPENSSL_cleanse(&(rr->data[rr->off]), n);
+ rr->length -= n;
+ rr->off += n;
+ if (rr->length == 0) {
+ /* TODO(RECLAYER): Do something with this? */
sc->rlayer.rstate = SSL_ST_READ_HEADER;
- SSL3_RECORD_set_off(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
}
}
#ifndef OPENSSL_NO_SCTP
* then it was unexpected (Hello Request or Client Hello).
*/
- if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ if (rr->type == SSL3_RT_ALERT) {
unsigned int alert_level, alert_descr;
- unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
- + SSL3_RECORD_get_off(rr);
+ unsigned char *alert_bytes = rr->data + rr->off;
PACKET alert;
- if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
+ if (!PACKET_buf_init(&alert, alert_bytes, rr->length)
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
if (alert_level == SSL3_AL_WARNING) {
sc->s3.warn_alert = alert_descr;
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
sc->rlayer.alert_count++;
if (sc->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
SSL_AD_REASON_OFFSET + alert_descr,
"SSL alert number %d", alert_descr);
sc->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
SSL_CTX_remove_session(sc->session_ctx, sc->session);
return 0;
} else {
if (sc->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
* shutdown */
sc->rwstate = SSL_NOTHING;
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
return 0;
}
- if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
/*
* We can't process a CCS now, because previous handshake messages
* are still missing, so just drop it.
*/
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
goto start;
}
/*
* Unexpected handshake message (Client Hello, or protocol violation)
*/
- if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
- !ossl_statem_get_in_handshake(sc)) {
+ if (rr->type == SSL3_RT_HANDSHAKE && !ossl_statem_get_in_handshake(sc)) {
struct hm_header_st msg_hdr;
/*
* This may just be a stale retransmit. Also sanity check that we have
* at least enough record bytes for a message header
*/
- if (SSL3_RECORD_get_epoch(rr) != sc->rlayer.d->r_epoch
- || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) {
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ if (rr->epoch != sc->rlayer.d->r_epoch
+ || rr->length < DTLS1_HM_HEADER_LENGTH) {
+ ssl_release_record(sc, rr);
goto start;
}
if (ossl_statem_in_error(sc))
return -1;
}
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
+ ssl_release_record(sc, rr);
if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
/* no read-ahead left? */
goto start;
}
- switch (SSL3_RECORD_get_type(rr)) {
+ switch (rr->type) {
default:
SSLfatal(sc, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
return ssl3_write_pending(sc, type, buf, len, written);
}
-DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
- unsigned int *is_next_epoch)
-{
-
- *is_next_epoch = 0;
-
- /* In current epoch, accept HM, CCS, DATA, & ALERT */
- if (rr->epoch == s->rlayer.d->r_epoch)
- return &s->rlayer.d->bitmap;
-
- /*
- * Only HM and ALERT messages can be from the next epoch and only if we
- * have already processed all of the unprocessed records from the last
- * epoch
- */
- else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
- s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
- (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
- *is_next_epoch = 1;
- return &s->rlayer.d->next_bitmap;
- }
-
- return NULL;
-}
-
void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw)
{
unsigned char *seq;
/* Checks if we have unprocessed read ahead data pending */
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl)
{
- /*
- * TODO(RECLAYER): Temporarily do it the old way until DTLS is converted to
- * the new record layer code
- */
- if (SSL_CONNECTION_IS_DTLS(rl->s))
- return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
-
return rl->s->rrlmethod->unprocessed_read_pending(rl->s->rrl);
}
/* Checks if we have decrypted unread record data pending */
int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
{
- /*
- * TODO(RECLAYER): Temporarily do it the old way until DTLS is converted to
- * the new record layer code
- */
- if (SSL_CONNECTION_IS_DTLS(rl->s)) {
- const SSL3_RECORD *rr = rl->rrec;
-
- size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl);
-
- while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]))
- curr_rec++;
-
- return curr_rec < num_recs;
- }
-
return (rl->curr_rec < rl->num_recs)
|| rl->s->rrlmethod->processed_read_pending(rl->s->rrl);
}
if (sc->rlayer.rstate == SSL_ST_READ_BODY)
return 0;
- /*
- * TODO(RECLAYER): We need to do it the old way temporary for DTLS until
- * that is converted to use the new record layer code
- */
if (SSL_CONNECTION_IS_DTLS(sc)) {
- DTLS1_RECORD_DATA *rdata;
+ TLS_RECORD *rdata;
pitem *item, *iter;
iter = pqueue_iterator(sc->rlayer.d->buffered_app_data.q);
while ((item = pqueue_next(&iter)) != NULL) {
rdata = item->data;
- num += rdata->rrec.length;
+ num += rdata->length;
}
+ }
- for (i = 0; i < RECORD_LAYER_get_numrpipes(&sc->rlayer); i++) {
- if (SSL3_RECORD_get_type(&sc->rlayer.rrec[i])
- != SSL3_RT_APPLICATION_DATA)
- return 0;
- num += SSL3_RECORD_get_length(&sc->rlayer.rrec[i]);
- }
- } else {
- for (i = 0; i <sc->rlayer.num_recs; i++) {
- if (sc->rlayer.tlsrecs[i].type != SSL3_RT_APPLICATION_DATA)
- return 0;
- num += sc->rlayer.tlsrecs[i].length;
- }
+ for (i = 0; i < sc->rlayer.num_recs; i++) {
+ if (sc->rlayer.tlsrecs[i].type != SSL3_RT_APPLICATION_DATA)
+ return num;
+ num += sc->rlayer.tlsrecs[i].length;
}
return num;
return ret;
}
+void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr)
+{
+ if (rr->rechandle != NULL) {
+ /* The record layer allocated the buffers for this record */
+ s->rrlmethod->release_record(s->rrl, rr->rechandle);
+ } else {
+ /* We allocated the buffers for this record (only happens with DTLS) */
+ OPENSSL_free(rr->data);
+ }
+ s->rlayer.curr_rec++;
+}
+
/*-
* Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
* SSL_read() with a zero length buffer will eventually cause
* SSL_pending() to report data as being available.
*/
- if (rr->length == 0) {
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
- }
+ if (rr->length == 0)
+ ssl_release_record(s, rr);
+
return 0;
}
buf += n;
if (peek) {
/* Mark any zero length record as consumed CVE-2016-6305 */
- if (rr->length == 0) {
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
- }
+ if (rr->length == 0)
+ ssl_release_record(s, rr);
} else {
if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(&(rr->data[rr->off]), n);
#if 0
s->rlayer.rstate = SSL_ST_READ_HEADER;
#endif
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
}
}
if (rr->length == 0
if ((!is_tls13 && alert_level == SSL3_AL_WARNING)
|| (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) {
s->s3.warn_alert = alert_descr;
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
SSL_AD_REASON_OFFSET + alert_descr,
"SSL alert number %d", alert_descr);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
return 0;
} else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
* sent close_notify.
*/
if (!SSL_CONNECTION_IS_TLS13(s)) {
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
if ((s->mode & SSL_MODE_AUTO_RETRY) != 0)
goto start;
* above.
* No alert sent because we already sent close_notify
*/
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
return -1;
rr->off += n;
rr->length -= n;
*dest_len += n;
- if (rr->length == 0) {
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
- }
+ if (rr->length == 0)
+ ssl_release_record(s, rr);
if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
/* SSLfatal() already called */
return -1;
}
- s->rrlmethod->release_record(s->rrl, rr->rechandle);
- s->rlayer.curr_rec++;
+ ssl_release_record(s, rr);
goto start;
} else {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
size_t length;
/* Offset into the data buffer where to start reading */
size_t off;
+ /* epoch number. DTLS only */
+ uint16_t epoch;
+ /* sequence number. DTLS only */
+ unsigned char seq_num[SEQ_NUM_SIZE];
+#ifndef OPENSSL_NO_SCTP
+ struct bio_dgram_sctp_rcvinfo recordinfo;
+#endif
} TLS_RECORD;
typedef struct dtls1_bitmap_st {
DTLS1_BITMAP bitmap;
/* renegotiation starts a new set of sequence numbers */
DTLS1_BITMAP next_bitmap;
- /* Received handshake records (processed and unprocessed) */
- record_pqueue unprocessed_rcds;
- record_pqueue processed_rcds;
/*
* Buffered application records. Only for records between CCS and
* Finished to prevent either protocol violation or unnecessary message
#define RECORD_LAYER_get_packet_length(rl) ((rl)->packet_length)
#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
#define DTLS_RECORD_LAYER_get_w_epoch(rl) ((rl)->d->w_epoch)
-#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
- ((rl)->d->processed_rcds)
-#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
- ((rl)->d->unprocessed_rcds)
#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw);
int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
size_t off);
-
+void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr);
# define HANDLE_RLAYER_RETURN(s, ret) \
ossl_tls_handle_rlayer_return(s, ret, OPENSSL_FILE, OPENSSL_LINE)
#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)
-DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
- unsigned int *is_next_epoch);
-int dtls1_process_buffered_records(SSL_CONNECTION *s);
-int dtls1_retrieve_buffered_record(SSL_CONNECTION *s, record_pqueue *queue);
-int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *q,
- unsigned char *priority);
+int dtls_buffer_record(SSL_CONNECTION *s, TLS_RECORD *rec);
void ssl3_record_sequence_update(unsigned char *seq);
-/* Functions provided by the DTLS1_BITMAP component */
-
-int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-
/* Macros/functions provided by the SSL3_BUFFER component */
#define SSL3_BUFFER_get_buf(b) ((b)->buf)
size_t block_size, size_t mac_size,
int aead,
OSSL_LIB_CTX *libctx);
-int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap);
-__owur int dtls1_get_record(SSL_CONNECTION *s);
uint32_t ossl_get_max_early_data(SSL_CONNECTION *s);
int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length, size_t overhead,
int send);
EVP_MD_CTX_free(hmac);
return ret;
}
-
-int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
-{
- int i;
- int enc_err;
- SSL_SESSION *sess;
- SSL3_RECORD *rr;
- int imac_size;
- size_t mac_size = 0;
- unsigned char md[EVP_MAX_MD_SIZE];
- size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
- SSL_MAC_BUF macbuf = { NULL, 0 };
- int ret = 0;
- SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-
- rr = RECORD_LAYER_get_rrec(&s->rlayer);
- sess = s->session;
-
- /*
- * At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
- * and we have that many bytes in s->rlayer.packet
- */
- rr->input = &(s->rrlmethod->get0_packet(s->rrl)[DTLS1_RT_HEADER_LENGTH]);
-
- /*
- * ok, we can now read from 's->rlayer.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) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
- return 0;
- }
-
- /* decrypt in place in 'rr->input' */
- rr->data = rr->input;
- rr->orig_len = rr->length;
-
- if (s->read_hash != NULL) {
- const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
-
- if (tmpmd != NULL) {
- imac_size = EVP_MD_get_size(tmpmd);
- if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
- return 0;
- }
- mac_size = (size_t)imac_size;
- }
- }
-
- if (SSL_READ_ETM(s) && s->read_hash) {
- unsigned char *mac;
-
- if (rr->orig_len < mac_size) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
- return 0;
- }
- rr->length -= mac_size;
- mac = rr->data + rr->length;
- i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
- if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
- SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
- return 0;
- }
- /*
- * We've handled the mac now - there is no MAC inside the encrypted
- * record
- */
- mac_size = 0;
- }
-
- /*
- * Set a mark around the packet decryption attempt. This is DTLS, so
- * bad packets are just ignored, and we don't want to leave stray
- * errors in the queue from processing bogus junk that we ignored.
- */
- ERR_set_mark();
- enc_err = ssl->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
-
- /*-
- * enc_err is:
- * 0: if the record is publicly invalid, or an internal error, or AEAD
- * decryption failed, or ETM decryption failed.
- * 1: Success or MTE decryption failed (MAC will be randomised)
- */
- if (enc_err == 0) {
- ERR_pop_to_mark();
- if (ossl_statem_in_error(s)) {
- /* SSLfatal() got called */
- goto end;
- }
- /* For DTLS we simply ignore bad packets. */
- rr->length = 0;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto end;
- }
- ERR_clear_last_mark();
- OSSL_TRACE_BEGIN(TLS) {
- BIO_printf(trc_out, "dec %zd\n", rr->length);
- BIO_dump_indent(trc_out, rr->data, rr->length, 4);
- } OSSL_TRACE_END(TLS);
-
- /* r->length is now the compressed data plus mac */
- if ((sess != NULL)
- && !SSL_READ_ETM(s)
- && (s->enc_read_ctx != NULL)
- && (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
- /* s->read_hash != NULL => mac_size != -1 */
-
- i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
- if (i == 0 || macbuf.mac == NULL
- || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
- enc_err = 0;
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
- enc_err = 0;
- }
-
- if (enc_err == 0) {
- /* decryption failed, silently discard message */
- rr->length = 0;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto end;
- }
-
- /* r->length is now just compressed */
- if (s->expand != NULL) {
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
- SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- goto end;
- }
- if (!ssl3_do_uncompress(s, rr)) {
- SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
- goto end;
- }
- }
-
- /* use current Max Fragment Length setting if applicable */
- if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
- max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
-
- /* send overflow if the plaintext is too long now it has passed MAC */
- if (rr->length > max_plain_length) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
- goto end;
- }
-
- 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->rrlmethod->reset_packet_length(s->rrl);
-
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
-
- ret = 1;
- end:
- if (macbuf.alloced)
- OPENSSL_free(macbuf.mac);
- return ret;
-}
-
-/*
- * Retrieve a buffered record that belongs to the current epoch, i.e. processed
- */
-#define dtls1_get_processed_record(s) \
- dtls1_retrieve_buffered_record((s), \
- &(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
-
-/*-
- * 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 dtls1_read_bytes */
-int dtls1_get_record(SSL_CONNECTION *s)
-{
- int ssl_major, ssl_minor;
- int rret;
- size_t more, n;
- SSL3_RECORD *rr;
- unsigned char *p = NULL;
- unsigned short version;
- DTLS1_BITMAP *bitmap;
- unsigned int is_next_epoch;
- SSL *ssl = SSL_CONNECTION_GET_SSL(s);
-
- rr = RECORD_LAYER_get_rrec(&s->rlayer);
-
- again:
- /*
- * The epoch may have changed. If so, process all the pending records.
- * This is a non-blocking operation.
- */
- if (!dtls1_process_buffered_records(s)) {
- /* SSLfatal() already called */
- return -1;
- }
-
- /* if we're renegotiating, then there may be buffered records */
- if (dtls1_get_processed_record(s))
- return 1;
-
- /* get something from the wire */
-
- /* check if we have the header */
- if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
- (s->rrlmethod->get_packet_length(s->rrl) < DTLS1_RT_HEADER_LENGTH)) {
- rret = HANDLE_RLAYER_RETURN(s,
- s->rrlmethod->read_n(s->rrl, DTLS1_RT_HEADER_LENGTH,
- SSL3_BUFFER_get_len(s->rrlmethod->get0_rbuf(s->rrl)), 0, 1, &n));
- /* read timeout is handled by dtls1_read_bytes */
- if (rret <= 0) {
- /* SSLfatal() already called if appropriate */
- return rret; /* error or non-blocking */
- }
-
- /* this packet contained a partial record, dump it */
- if (s->rrlmethod->get_packet_length(s->rrl) != DTLS1_RT_HEADER_LENGTH) {
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
-
- p = s->rrlmethod->get0_packet(s->rrl);
-
- if (s->msg_callback)
- s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
- ssl, s->msg_callback_arg);
-
- /* Pull apart the header into the DTLS1_RECORD */
- rr->type = *(p++);
- ssl_major = *(p++);
- ssl_minor = *(p++);
- version = (ssl_major << 8) | ssl_minor;
-
- /* sequence number is 64 bits, with top 2 bytes = epoch */
- n2s(p, rr->epoch);
-
- memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
- p += 6;
-
- n2s(p, rr->length);
- rr->read = 0;
-
- /*
- * Lets check the version. We tolerate alerts that don't have the exact
- * version number (e.g. because of protocol version errors)
- */
- if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
- if (version != s->version) {
- /* unexpected version, silently discard */
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
- }
-
- if ((version & 0xff00) != (s->version & 0xff00)) {
- /* wrong version, silently discard record */
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
- /* record too long, silently discard it */
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- /* If received packet overflows own-client Max Fragment Length setting */
- if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
- && rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
- /* record too long, silently discard it */
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- /* now s->rlayer.rstate == SSL_ST_READ_BODY */
- }
-
- /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
-
- if (rr->length >
- s->rrlmethod->get_packet_length(s->rrl) - DTLS1_RT_HEADER_LENGTH) {
- /* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
- more = rr->length;
- rret = HANDLE_RLAYER_RETURN(s,
- s->rrlmethod->read_n(s->rrl, more, more, 1, 1, &n));
- /* this packet contained a partial record, dump it */
- if (rret <= 0 || n != more) {
- if (ossl_statem_in_error(s)) {
- /* read_n() called SSLfatal() */
- return -1;
- }
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- /*
- * now n == rr->length, and s->rlayer.packet_length ==
- * DTLS1_RT_HEADER_LENGTH + rr->length
- */
- }
- /* set state for later operations */
- RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
-
- /* match epochs. NULL means the packet is dropped on the floor */
- bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
- if (bitmap == NULL) {
- rr->length = 0;
- s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
- goto again; /* get another record */
- }
-#ifndef OPENSSL_NO_SCTP
- /* Only do replay check if no SCTP bio */
- if (!BIO_dgram_is_sctp(SSL_get_rbio(ssl))) {
-#endif
- /* Check whether this is a repeat, or aged record. */
- if (!dtls1_record_replay_check(s, bitmap)) {
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
- goto again; /* get another record */
- }
-#ifndef OPENSSL_NO_SCTP
- }
-#endif
-
- /* just read a 0 length packet */
- if (rr->length == 0) {
- rr->read = 1;
- goto again;
- }
-
- /*
- * If this record is from the next epoch (either HM or ALERT), and a
- * handshake is currently in progress, buffer it since it cannot be
- * processed at this time.
- */
- if (is_next_epoch) {
- if ((SSL_in_init(ssl) || ossl_statem_get_in_handshake(s))) {
- if (dtls1_buffer_record (s,
- &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
- rr->seq_num) < 0) {
- /* SSLfatal() already called */
- return -1;
- }
- }
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl);
- goto again;
- }
-
- if (!dtls1_process_record(s, bitmap)) {
- if (ossl_statem_in_error(s)) {
- /* dtls1_process_record() called SSLfatal */
- return -1;
- }
- rr->length = 0;
- rr->read = 1;
- s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
- goto again; /* get another record */
- }
-
- return 1;
-
-}
-
-int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
- size_t off)
-{
- SSL3_RECORD *rr;
-
- rr = RECORD_LAYER_get_rrec(&s->rlayer);
- memset(rr, 0, sizeof(SSL3_RECORD));
-
- rr->length = len;
- rr->type = SSL3_RT_HANDSHAKE;
- memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
- rr->off = off;
-
- s->rrlmethod->set0_packet(s->rrl, s->rrlmethod->get0_rbuf(s->rrl)->buf,
- DTLS1_RT_HEADER_LENGTH + len);
- rr->data = s->rrlmethod->get0_packet(s->rrl) + DTLS1_RT_HEADER_LENGTH;
-
- if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
/* Check buffered app data if any first */
if (SSL_CONNECTION_IS_DTLS(sc)) {
- DTLS1_RECORD_DATA *rdata;
+ TLS_RECORD *rdata;
pitem *item, *iter;
iter = pqueue_iterator(sc->rlayer.d->buffered_app_data.q);
while ((item = pqueue_next(&iter)) != NULL) {
rdata = item->data;
- if (rdata->rrec.length > 0)
+ if (rdata->length > 0)
return 1;
}
}
* We must have at least frag_len bytes left in the record to be read.
* Fragments must not span records.
*/
- if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
+ if (frag_len > s->rlayer.tlsrecs[s->rlayer.curr_rec].length) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH);
goto f_err;
}
int testresult = 0;
void *zbuf;
SSL_CONNECTION *serversc;
+ TLS_RECORD *rr;
static unsigned char cbuf[16000];
static unsigned char sbuf[16000];
*/
if (!TEST_ptr(serversc = SSL_CONNECTION_FROM_SSL_ONLY(serverssl)))
goto end;
+ rr = serversc->rlayer.tlsrecs;
- /*
- * TODO(RECLAYER): This is temporary until DTLS is converted to use the new
- * record layer code.
- */
- if (!SSL_is_dtls(serverssl)) {
- TLS_RECORD *rr = serversc->rlayer.tlsrecs;
-
- zbuf = &rr->data[rr->off];
- if (!TEST_int_eq(rr->length, sizeof(cbuf)))
- goto end;
- } else {
- SSL3_RECORD *rr = serversc->rlayer.rrec;
-
- zbuf = &rr->data[rr->off];
- if (!TEST_int_eq(rr->length, sizeof(cbuf)))
- goto end;
- }
+ zbuf = &rr->data[rr->off];
+ if (!TEST_int_eq(rr->length, sizeof(cbuf)))
+ goto end;
/*
* After SSL_peek() the plaintext must still be stored in the