-/* $OpenBSD: d1_lib.c,v 1.62 2022/10/02 16:36:41 jsing Exp $ */
+/* $OpenBSD: d1_lib.c,v 1.63 2022/11/11 17:15:26 jsing Exp $ */
/*
* DTLS implementation written by Nagendra Modadugu
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
return (0);
}
+static void
+dtls1_drain_rcontents(pqueue queue)
+{
+ DTLS1_RCONTENT_DATA_INTERNAL *rdata;
+ pitem *item;
+
+ if (queue == NULL)
+ return;
+
+ while ((item = pqueue_pop(queue)) != NULL) {
+ rdata = (DTLS1_RCONTENT_DATA_INTERNAL *)item->data;
+ tls_content_free(rdata->rcontent);
+ free(item->data);
+ pitem_free(item);
+ }
+}
+
static void
dtls1_drain_records(pqueue queue)
{
dtls1_drain_records(s->d1->unprocessed_rcds.q);
dtls1_drain_fragments(s->d1->buffered_messages);
dtls1_drain_fragments(s->d1->sent_messages);
- dtls1_drain_records(s->d1->buffered_app_data.q);
+ dtls1_drain_rcontents(s->d1->buffered_app_data.q);
}
void
-/* $OpenBSD: d1_pkt.c,v 1.124 2022/10/02 16:36:41 jsing Exp $ */
+/* $OpenBSD: d1_pkt.c,v 1.125 2022/11/11 17:15:26 jsing Exp $ */
/*
* DTLS implementation written by Nagendra Modadugu
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
#include <endian.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <openssl/buffer.h>
#include "dtls_locl.h"
#include "pqueue.h"
#include "ssl_locl.h"
+#include "tls_content.h"
/* mod 128 saturating subtract of two 64-bit values in big-endian order */
static int
return (-1);
}
+static int
+dtls1_buffer_rcontent(SSL *s, rcontent_pqueue *queue, unsigned char *priority)
+{
+ DTLS1_RCONTENT_DATA_INTERNAL *rdata;
+ pitem *item;
+
+ /* Limit the size of the queue to prevent DOS attacks */
+ if (pqueue_size(queue->q) >= 100)
+ return 0;
+
+ rdata = malloc(sizeof(DTLS1_RCONTENT_DATA_INTERNAL));
+ item = pitem_new(priority, rdata);
+ if (rdata == NULL || item == NULL)
+ goto init_err;
+
+ rdata->rcontent = s->s3->rcontent;
+ s->s3->rcontent = NULL;
+
+ item->data = rdata;
+
+ /* insert should not fail, since duplicates are dropped */
+ if (pqueue_insert(queue->q, item) == NULL)
+ goto err;
+
+ if ((s->s3->rcontent = tls_content_new()) == NULL)
+ goto err;
+
+ return (1);
+
+ err:
+ tls_content_free(rdata->rcontent);
+
+ init_err:
+ SSLerror(s, ERR_R_INTERNAL_ERROR);
+ free(rdata);
+ pitem_free(item);
+ return (-1);
+}
static int
dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
return (0);
}
+static int
+dtls1_retrieve_buffered_rcontent(SSL *s, rcontent_pqueue *queue)
+{
+ DTLS1_RCONTENT_DATA_INTERNAL *rdata;
+ pitem *item;
+
+ item = pqueue_pop(queue->q);
+ if (item) {
+ rdata = item->data;
+
+ tls_content_free(s->s3->rcontent);
+ s->s3->rcontent = rdata->rcontent;
+ s->s3->rrec.epoch = tls_content_epoch(s->s3->rcontent);
+
+ free(item->data);
+ pitem_free(item);
+
+ return (1);
+ }
+
+ return (0);
+}
+
static int
dtls1_process_buffered_record(SSL *s)
{
{
SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec);
uint8_t alert_desc;
- uint8_t *out;
- size_t out_len;
tls12_record_layer_set_version(s->rl, s->version);
- if (!tls12_record_layer_open_record(s->rl, s->packet,
- s->packet_length, &out, &out_len)) {
+ if (!tls12_record_layer_open_record(s->rl, s->packet, s->packet_length,
+ s->s3->rcontent)) {
tls12_record_layer_alert(s->rl, &alert_desc);
if (alert_desc == 0)
* DTLS should silently discard invalid records, including those
* with a bad MAC, as per RFC 6347 section 4.1.2.1.
*/
- if (alert_desc == SSL_AD_BAD_RECORD_MAC) {
- out_len = 0;
+ if (alert_desc == SSL_AD_BAD_RECORD_MAC)
goto done;
- }
if (alert_desc == SSL_AD_RECORD_OVERFLOW)
SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto fatal_err;
}
- done:
- rr->data = out;
- rr->length = out_len;
- rr->off = 0;
+ /* XXX move to record layer. */
+ tls_content_set_epoch(s->s3->rcontent, rr->epoch);
+ done:
s->packet_length = 0;
return (1);
static int
dtls1_read_handshake_unexpected(SSL *s)
{
- SSL3_RECORD_INTERNAL *rr = &s->s3->rrec;
struct hm_header_st hs_msg_hdr;
CBS cbs;
int ret;
return -1;
}
- if (rr->off != 0) {
- SSLerror(s, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
/* Parse handshake message header. */
- CBS_init(&cbs, rr->data, rr->length);
+ CBS_dup(&cbs, tls_content_cbs(s->s3->rcontent));
if (!dtls1_get_message_header(&cbs, &hs_msg_hdr))
return -1; /* XXX - probably should drop/continue. */
/* This may just be a stale retransmit. */
- if (rr->epoch != tls12_record_layer_read_epoch(s->rl)) {
- rr->length = 0;
+ if (tls_content_epoch(s->s3->rcontent) !=
+ tls12_record_layer_read_epoch(s->rl)) {
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return 1;
}
return -1;
}
- ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, rr->data,
- DTLS1_HM_HEADER_LENGTH);
+ ssl_msg_callback_cbs(s, 0, SSL3_RT_HANDSHAKE,
+ tls_content_cbs(s->s3->rcontent));
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
/*
* It should be impossible to hit this, but keep the safety
dtls1_retransmit_buffered_messages(s);
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return 1;
int
dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
{
- SSL3_RECORD_INTERNAL *rr;
int rrcount = 0;
- unsigned int n;
+ ssize_t ssret;
int ret;
if (s->s3->rbuf.buf == NULL) {
return -1;
}
+ if (s->s3->rcontent == NULL) {
+ if ((s->s3->rcontent = tls_content_new()) == NULL)
+ return -1;
+ }
+
if (len < 0) {
SSLerror(s, ERR_R_INTERNAL_ERROR);
return -1;
s->rwstate = SSL_NOTHING;
- rr = &s->s3->rrec;
-
/*
* We are not handshaking and have no data yet, so process data buffered
* during the last handshake in advance, if any.
*/
- if (s->s3->hs.state == SSL_ST_OK && rr->length == 0)
- dtls1_retrieve_buffered_record(s, &s->d1->buffered_app_data);
+ if (s->s3->hs.state == SSL_ST_OK &&
+ tls_content_remaining(s->s3->rcontent) == 0)
+ dtls1_retrieve_buffered_rcontent(s, &s->d1->buffered_app_data);
if (dtls1_handle_timeout(s) > 0)
goto start;
- if (rr->length == 0 || s->rstate == SSL_ST_READ_BODY) {
+ if (tls_content_remaining(s->s3->rcontent) == 0) {
if ((ret = dtls1_get_record(s)) <= 0) {
/* Anything other than a timeout is an error. */
if ((ret = dtls1_read_failed(s, ret)) <= 0)
}
}
- if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) {
- rr->length = 0;
+ if (s->d1->listen &&
+ tls_content_type(s->s3->rcontent) != SSL3_RT_HANDSHAKE) {
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
goto start;
}
/* We now have a packet which can be read and processed. */
- if (s->s3->change_cipher_spec && rr->type != SSL3_RT_HANDSHAKE) {
+ if (s->s3->change_cipher_spec &&
+ tls_content_type(s->s3->rcontent) != 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(s, &s->d1->buffered_app_data,
- rr->seq_num) < 0) {
+ if (dtls1_buffer_rcontent(s, &s->d1->buffered_app_data,
+ s->s3->rrec.seq_num) < 0) {
SSLerror(s, ERR_R_INTERNAL_ERROR);
return (-1);
}
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
goto start;
}
*/
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return 0;
}
/* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
- if (type == rr->type) {
+ if (tls_content_type(s->s3->rcontent) == type) {
/*
* Make sure that we are not getting application data when we
* are doing a handshake for the first time.
if (len <= 0)
return len;
- if ((unsigned int)len > rr->length)
- n = rr->length;
- else
- n = (unsigned int)len;
-
- memcpy(buf, &rr->data[rr->off], n);
- if (!peek) {
- memset(&rr->data[rr->off], 0, n);
- rr->length -= n;
- rr->off += n;
- if (rr->length == 0) {
- s->rstate = SSL_ST_READ_HEADER;
- rr->off = 0;
- }
+ if (peek) {
+ ssret = tls_content_peek(s->s3->rcontent, buf, len);
+ } else {
+ ssret = tls_content_read(s->s3->rcontent, buf, len);
}
+ if (ssret < INT_MIN || ssret > INT_MAX)
+ return -1;
+ if (ssret < 0)
+ return (int)ssret;
- return n;
- }
+ if (tls_content_remaining(s->s3->rcontent) == 0)
+ s->rstate = SSL_ST_READ_HEADER;
- /*
- * If we get here, then type != rr->type; if we have a handshake
- * message, then it was unexpected (Hello Request or Client Hello).
- */
+ return (int)ssret;
+ }
- if (rr->type == SSL3_RT_ALERT) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_ALERT) {
if ((ret = ssl3_read_alert(s)) <= 0)
return ret;
goto start;
if (s->shutdown & SSL_SENT_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return (0);
}
- if (rr->type == SSL3_RT_APPLICATION_DATA) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_APPLICATION_DATA) {
/*
* At this point, we were expecting handshake data, but have
* application data. If the library was running inside
}
}
- if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_CHANGE_CIPHER_SPEC) {
if ((ret = ssl3_read_change_cipher_spec(s)) <= 0)
return ret;
goto start;
}
- if (rr->type == SSL3_RT_HANDSHAKE) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_HANDSHAKE) {
if ((ret = dtls1_read_handshake_unexpected(s)) <= 0)
return ret;
goto start;
{
int i;
- if (SSL_in_init(s) && !s->in_handshake)
- {
+ if (SSL_in_init(s) && !s->in_handshake) {
i = s->handshake_func(s);
if (i < 0)
return (i);
-/* $OpenBSD: dtls_locl.h,v 1.10 2021/10/23 13:45:44 jsing Exp $ */
+/* $OpenBSD: dtls_locl.h,v 1.11 2022/11/11 17:15:26 jsing Exp $ */
/*
* DTLS implementation written by Nagendra Modadugu
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
#include <openssl/dtls1.h>
#include "ssl_locl.h"
+#include "tls_content.h"
__BEGIN_HIDDEN_DECLS
struct _pqueue *q;
} record_pqueue;
+typedef struct rcontent_pqueue_st {
+ unsigned short epoch;
+ struct _pqueue *q;
+} rcontent_pqueue;
+
typedef struct hm_fragment_st {
struct hm_header_st msg_header;
unsigned char *fragment;
SSL3_RECORD_INTERNAL rrec;
} DTLS1_RECORD_DATA_INTERNAL;
+typedef struct dtls1_rcontent_data_internal_st {
+ struct tls_content *rcontent;
+} DTLS1_RCONTENT_DATA_INTERNAL;
+
struct dtls1_state_st {
/* Buffered (sent) handshake records */
struct _pqueue *sent_messages;
* to prevent either protocol violation or
* unnecessary message loss.
*/
- record_pqueue buffered_app_data;
+ rcontent_pqueue buffered_app_data;
/* Is set when listening for new connections with dtls1_listen() */
unsigned int listen;
-/* $OpenBSD: s3_lib.c,v 1.240 2022/11/10 18:06:37 jsing Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.241 2022/11/11 17:15:26 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#include "ssl_locl.h"
#include "ssl_sigalgs.h"
#include "ssl_tlsext.h"
+#include "tls_content.h"
#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER))
int
ssl3_pending(const SSL *s)
{
- if (s->rstate == SSL_ST_READ_BODY)
+ if (s->s3->rcontent == NULL)
+ return 0;
+ if (tls_content_type(s->s3->rcontent) != SSL3_RT_APPLICATION_DATA)
return 0;
- return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ?
- s->s3->rrec.length : 0;
+ return tls_content_remaining(s->s3->rcontent);
}
int
ssl3_release_read_buffer(s);
ssl3_release_write_buffer(s);
+ tls_content_free(s->s3->rcontent);
+
tls_buffer_free(s->s3->alert_fragment);
tls_buffer_free(s->s3->handshake_fragment);
rlen = s->s3->rbuf.len;
wlen = s->s3->wbuf.len;
+ tls_content_free(s->s3->rcontent);
+ s->s3->rcontent = NULL;
+
tls1_transcript_free(s);
tls1_transcript_hash_free(s);
-/* $OpenBSD: ssl_locl.h,v 1.431 2022/11/10 18:06:37 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.432 2022/11/11 17:15:26 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#include <openssl/stack.h>
#include "bytestring.h"
+#include "tls_content.h"
#include "tls13_internal.h"
__BEGIN_HIDDEN_DECLS
int tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
CBS *mac_key, CBS *key, CBS *iv);
int tls12_record_layer_open_record(struct tls12_record_layer *rl,
- uint8_t *buf, size_t buf_len, uint8_t **out, size_t *out_len);
+ uint8_t *buf, size_t buf_len, struct tls_content *out);
int tls12_record_layer_seal_record(struct tls12_record_layer *rl,
uint8_t content_type, const uint8_t *content, size_t content_len,
CBB *out);
SSL3_BUFFER_INTERNAL rbuf; /* read IO goes into here */
SSL3_BUFFER_INTERNAL wbuf; /* write IO goes into here */
+ SSL3_RECORD_INTERNAL rrec; /* each decoded record goes in here */
+
+ struct tls_content *rcontent; /* Content from opened TLS records. */
+
/* we allow one fatal and one warning alert to be outstanding,
* send close alert via the warning alert */
int alert_dispatch;
int need_empty_fragments;
int empty_fragment_done;
- SSL3_RECORD_INTERNAL rrec; /* each decoded record goes in here */
-
/* Unprocessed Alert/Handshake protocol data. */
struct tls_buffer *alert_fragment;
struct tls_buffer *handshake_fragment;
-/* $OpenBSD: ssl_pkt.c,v 1.63 2022/11/10 18:06:37 jsing Exp $ */
+/* $OpenBSD: ssl_pkt.c,v 1.64 2022/11/11 17:15:26 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
*/
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <openssl/buffer.h>
#include "bytestring.h"
#include "dtls_locl.h"
#include "ssl_locl.h"
+#include "tls_content.h"
static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
unsigned int len);
SSL3_BUFFER_INTERNAL *rb = &(s->s3->rbuf);
SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec);
uint8_t alert_desc;
- uint8_t *out;
- size_t out_len;
int al, n;
int ret = -1;
*/
tls12_record_layer_set_version(s->rl, s->version);
- if (!tls12_record_layer_open_record(s->rl, s->packet,
- s->packet_length, &out, &out_len)) {
+ if (!tls12_record_layer_open_record(s->rl, s->packet, s->packet_length,
+ s->s3->rcontent)) {
tls12_record_layer_alert(s->rl, &alert_desc);
if (alert_desc == 0)
goto fatal_err;
}
- rr->data = out;
- rr->length = out_len;
- rr->off = 0;
-
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
- if (rr->length == 0) {
+ if (tls_content_remaining(s->s3->rcontent) == 0) {
/*
* Zero-length fragments are only permitted for application
* data, as per RFC 5246 section 6.2.1.
goto fatal_err;
}
+ tls_content_clear(s->s3->rcontent);
+
/*
* CBC countermeasures for known IV weaknesses can legitimately
* insert a single empty record, so we allow ourselves to read
static ssize_t
ssl3_read_cb(void *buf, size_t n, void *cb_arg)
{
- SSL3_RECORD_INTERNAL *rr;
SSL *s = cb_arg;
- rr = &s->s3->rrec;
-
- if (n > rr->length)
- n = rr->length;
-
- memcpy(buf, &rr->data[rr->off], n);
-
- rr->off += n;
- rr->length -= n;
-
- return n;
+ return tls_content_read(s->s3->rcontent, buf, n);
}
#define SSL3_ALERT_LENGTH 2
int
ssl3_read_change_cipher_spec(SSL *s)
{
- SSL3_RECORD_INTERNAL *rr = &s->s3->rrec;
- const uint8_t ccs[] = { SSL3_MT_CCS };
- CBS cbs;
+ const uint8_t ccs[1] = { SSL3_MT_CCS };
/*
* 'Change Cipher Spec' is just a single byte, so we know exactly what
* the record payload has to look like.
*/
- CBS_init(&cbs, rr->data, rr->length);
- if (rr->off != 0 || CBS_len(&cbs) != sizeof(ccs)) {
+ if (tls_content_remaining(s->s3->rcontent) != sizeof(ccs)) {
SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
}
- if (!CBS_mem_equal(&cbs, ccs, sizeof(ccs))) {
+ if (!tls_content_equal(s->s3->rcontent, ccs, sizeof(ccs))) {
SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
/* XDTLS: check that epoch is consistent */
- ssl_msg_callback_cbs(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC, &cbs);
+ ssl_msg_callback_cbs(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC,
+ tls_content_cbs(s->s3->rcontent));
/* Check that we have a cipher to change to. */
if (s->s3->hs.cipher == NULL) {
* handshake messages are still missing, so just
* drop it.
*/
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
return 1;
}
s->d1->change_cipher_spec_ok = 0;
s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
}
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
s->s3->change_cipher_spec = 1;
if (!ssl3_do_change_cipher_spec(s))
int
ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
{
- SSL3_RECORD_INTERNAL *rr;
int rrcount = 0;
- unsigned int n;
+ ssize_t ssret;
int ret;
if (s->s3->rbuf.buf == NULL) {
return -1;
}
+ if (s->s3->rcontent == NULL) {
+ if ((s->s3->rcontent = tls_content_new()) == NULL)
+ return -1;
+ }
+
if (len < 0) {
SSLerror(s, ERR_R_INTERNAL_ERROR);
return -1;
s->rwstate = SSL_NOTHING;
- rr = &s->s3->rrec;
-
- if (rr->length == 0 || s->rstate == SSL_ST_READ_BODY) {
+ if (tls_content_remaining(s->s3->rcontent) == 0) {
if ((ret = ssl3_get_record(s)) <= 0)
return ret;
}
/* We now have a packet which can be read and processed. */
- if (s->s3->change_cipher_spec && rr->type != SSL3_RT_HANDSHAKE) {
+ if (s->s3->change_cipher_spec &&
+ tls_content_type(s->s3->rcontent) != SSL3_RT_HANDSHAKE) {
SSLerror(s, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
return -1;
*/
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return 0;
}
/* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
- if (type == rr->type) {
+ if (tls_content_type(s->s3->rcontent) == type) {
/*
* Make sure that we are not getting application data when we
* are doing a handshake for the first time.
if (len <= 0)
return len;
- if ((unsigned int)len > rr->length)
- n = rr->length;
- else
- n = (unsigned int)len;
-
- memcpy(buf, &rr->data[rr->off], n);
- if (!peek) {
- memset(&rr->data[rr->off], 0, n);
- rr->length -= n;
- rr->off += n;
- if (rr->length == 0) {
- s->rstate = SSL_ST_READ_HEADER;
- rr->off = 0;
- if (s->mode & SSL_MODE_RELEASE_BUFFERS &&
- s->s3->rbuf.left == 0)
- ssl3_release_read_buffer(s);
- }
+ if (peek) {
+ ssret = tls_content_peek(s->s3->rcontent, buf, len);
+ } else {
+ ssret = tls_content_read(s->s3->rcontent, buf, len);
}
+ if (ssret < INT_MIN || ssret > INT_MAX)
+ return -1;
+ if (ssret < 0)
+ return (int)ssret;
- return n;
- }
+ if (tls_content_remaining(s->s3->rcontent) == 0) {
+ s->rstate = SSL_ST_READ_HEADER;
- /*
- * If we get here, then type != rr->type; if we have a handshake
- * message, then it was unexpected (Hello Request or Client Hello).
- */
+ if (s->mode & SSL_MODE_RELEASE_BUFFERS &&
+ s->s3->rbuf.left == 0)
+ ssl3_release_read_buffer(s);
+ }
+
+ return ssret;
+ }
- if (rr->type == SSL3_RT_ALERT) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_ALERT) {
if ((ret = ssl3_read_alert(s)) <= 0)
return ret;
goto start;
if (s->shutdown & SSL_SENT_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
+ s->s3->rrec.length = 0;
return 0;
}
- if (rr->type == SSL3_RT_APPLICATION_DATA) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_APPLICATION_DATA) {
/*
* At this point, we were expecting handshake data, but have
* application data. If the library was running inside
}
}
- if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_CHANGE_CIPHER_SPEC) {
if ((ret = ssl3_read_change_cipher_spec(s)) <= 0)
return ret;
goto start;
}
- if (rr->type == SSL3_RT_HANDSHAKE) {
+ if (tls_content_type(s->s3->rcontent) == SSL3_RT_HANDSHAKE) {
if ((ret = ssl3_read_handshake_unexpected(s)) <= 0)
return ret;
goto start;
* earlier versions silently ignore the record.
*/
if (ssl_effective_tls_version(s) <= TLS1_1_VERSION) {
- rr->length = 0;
+ tls_content_clear(s->s3->rcontent);
goto start;
}
SSLerror(s, SSL_R_UNEXPECTED_RECORD);
-/* $OpenBSD: tls12_record_layer.c,v 1.36 2022/01/14 09:12:15 tb Exp $ */
+/* $OpenBSD: tls12_record_layer.c,v 1.37 2022/11/11 17:15:26 jsing Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
*
static int
tls12_record_layer_open_record_plaintext(struct tls12_record_layer *rl,
- uint8_t content_type, CBS *fragment, uint8_t **out, size_t *out_len)
+ uint8_t content_type, CBS *fragment, struct tls_content *out)
{
if (tls12_record_protection_engaged(rl->read))
return 0;
- /* XXX - decrypt/process in place for now. */
- *out = (uint8_t *)CBS_data(fragment);
- *out_len = CBS_len(fragment);
-
- return 1;
+ return tls_content_dup_data(out, content_type, CBS_data(fragment),
+ CBS_len(fragment));
}
static int
tls12_record_layer_open_record_protected_aead(struct tls12_record_layer *rl,
- uint8_t content_type, CBS *seq_num, CBS *fragment, uint8_t **out,
- size_t *out_len)
+ uint8_t content_type, CBS *seq_num, CBS *fragment, struct tls_content *out)
{
struct tls12_record_protection *rp = rl->read;
uint8_t *header = NULL;
size_t header_len = 0;
- uint8_t *plain;
- size_t plain_len;
+ uint8_t *content = NULL;
+ size_t content_len = 0;
+ size_t out_len = 0;
CBS var_nonce;
int ret = 0;
goto err;
}
- /* XXX - decrypt/process in place for now. */
- plain = (uint8_t *)CBS_data(fragment);
- plain_len = CBS_len(fragment) - rp->aead_tag_len;
+ content_len = CBS_len(fragment) - rp->aead_tag_len;
+ if ((content = calloc(1, CBS_len(fragment))) == NULL) {
+ content_len = 0;
+ goto err;
+ }
- if (!tls12_record_layer_pseudo_header(rl, content_type, plain_len,
+ if (!tls12_record_layer_pseudo_header(rl, content_type, content_len,
seq_num, &header, &header_len))
goto err;
- if (!EVP_AEAD_CTX_open(rp->aead_ctx, plain, out_len, plain_len,
+ if (!EVP_AEAD_CTX_open(rp->aead_ctx, content, &out_len, content_len,
rp->aead_nonce, rp->aead_nonce_len, CBS_data(fragment),
CBS_len(fragment), header, header_len)) {
rl->alert_desc = SSL_AD_BAD_RECORD_MAC;
goto err;
}
- if (*out_len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ if (out_len > SSL3_RT_MAX_PLAIN_LENGTH) {
rl->alert_desc = SSL_AD_RECORD_OVERFLOW;
goto err;
}
- if (*out_len != plain_len)
+ if (out_len != content_len)
goto err;
- *out = plain;
+ tls_content_set_data(out, content_type, content, content_len);
+ content = NULL;
+ content_len = 0;
ret = 1;
err:
freezero(header, header_len);
+ freezero(content, content_len);
return ret;
}
static int
tls12_record_layer_open_record_protected_cipher(struct tls12_record_layer *rl,
- uint8_t content_type, CBS *seq_num, CBS *fragment, uint8_t **out,
- size_t *out_len)
+ uint8_t content_type, CBS *seq_num, CBS *fragment, struct tls_content *out)
{
EVP_CIPHER_CTX *enc = rl->read->cipher_ctx;
SSL3_RECORD_INTERNAL rrec;
size_t mac_len = 0;
uint8_t *out_mac = NULL;
size_t out_mac_len = 0;
- uint8_t *plain;
- size_t plain_len;
+ uint8_t *content = NULL;
+ size_t content_len = 0;
size_t min_len;
CBB cbb_mac;
int ret = 0;
goto err;
}
- /* XXX - decrypt/process in place for now. */
- plain = (uint8_t *)CBS_data(fragment);
- plain_len = CBS_len(fragment);
+ if ((content = calloc(1, CBS_len(fragment))) == NULL)
+ goto err;
+ content_len = CBS_len(fragment);
- if (!EVP_Cipher(enc, plain, CBS_data(fragment), plain_len))
+ if (!EVP_Cipher(enc, content, CBS_data(fragment), CBS_len(fragment)))
goto err;
- rrec.data = plain;
- rrec.input = plain;
- rrec.length = plain_len;
+ rrec.data = content;
+ rrec.input = content;
+ rrec.length = content_len;
/*
* We now have to remove padding, extract MAC, calculate MAC
goto err;
}
- *out = rrec.data;
- *out_len = rrec.length;
+ tls_content_set_data(out, content_type, content, content_len);
+ content = NULL;
+ content_len = 0;
+
+ /* Actual content is after EIV, minus padding and MAC. */
+ if (!tls_content_set_bounds(out, eiv_len, rrec.length))
+ goto err;
ret = 1;
CBB_cleanup(&cbb_mac);
freezero(mac, mac_len);
freezero(out_mac, out_mac_len);
+ freezero(content, content_len);
return ret;
}
int
tls12_record_layer_open_record(struct tls12_record_layer *rl, uint8_t *buf,
- size_t buf_len, uint8_t **out, size_t *out_len)
+ size_t buf_len, struct tls_content *out)
{
CBS cbs, fragment, seq_num;
uint16_t version;
if (rl->read->aead_ctx != NULL) {
if (!tls12_record_layer_open_record_protected_aead(rl,
- content_type, &seq_num, &fragment, out, out_len))
+ content_type, &seq_num, &fragment, out))
return 0;
} else if (rl->read->cipher_ctx != NULL) {
if (!tls12_record_layer_open_record_protected_cipher(rl,
- content_type, &seq_num, &fragment, out, out_len))
+ content_type, &seq_num, &fragment, out))
return 0;
} else {
if (!tls12_record_layer_open_record_plaintext(rl,
- content_type, &fragment, out, out_len))
+ content_type, &fragment, out))
return 0;
}
-/* $OpenBSD: tls13_record_layer.c,v 1.71 2022/09/11 13:50:41 jsing Exp $ */
+/* $OpenBSD: tls13_record_layer.c,v 1.72 2022/11/11 17:15:27 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
if (!tls13_record_content(rl->rrec, &enc_record))
goto err;
+ /* XXX - minus tag len? */
if ((content = calloc(1, CBS_len(&enc_record))) == NULL)
goto err;
content_len = CBS_len(&enc_record);
-/* $OpenBSD: tls_content.c,v 1.1 2021/09/04 16:26:12 jsing Exp $ */
+/* $OpenBSD: tls_content.c,v 1.2 2022/11/11 17:15:27 jsing Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
*
uint16_t epoch;
const uint8_t *data;
- size_t len;
+ size_t data_len;
CBS cbs;
};
void
tls_content_clear(struct tls_content *content)
{
- freezero((void *)content->data, content->len);
+ freezero((void *)content->data, content->data_len);
memset(content, 0, sizeof(*content));
}
content->type = type;
content->data = data;
- content->len = data_len;
+ content->data_len = data_len;
- CBS_init(&content->cbs, content->data, content->len);
+ CBS_init(&content->cbs, content->data, content->data_len);
+}
+
+int
+tls_content_set_bounds(struct tls_content *content, size_t offset, size_t len)
+{
+ size_t content_len;
+
+ content_len = offset + len;
+ if (content_len < len)
+ return 0;
+ if (content_len > content->data_len)
+ return 0;
+
+ CBS_init(&content->cbs, content->data, content_len);
+ return CBS_skip(&content->cbs, offset);
}
static ssize_t
-/* $OpenBSD: tls_content.h,v 1.1 2021/09/04 16:26:12 jsing Exp $ */
+/* $OpenBSD: tls_content.h,v 1.2 2022/11/11 17:15:27 jsing Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
*
const uint8_t *data, size_t data_len);
void tls_content_set_data(struct tls_content *content, uint8_t type,
const uint8_t *data, size_t data_len);
+int tls_content_set_bounds(struct tls_content *content, size_t offset,
+ size_t len);
void tls_content_set_epoch(struct tls_content *content, uint16_t epoch);
ssize_t tls_content_peek(struct tls_content *content, uint8_t *buf, size_t n);