#include <openssl/buffer.h>
#include "record_locl.h"
#include <assert.h>
+#include "../packet_locl.h"
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
{
memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
}
-static size_t have_handshake_fragment(SSL *s, int type, unsigned char *buf,
- size_t len);
-
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
{
size_t len, int peek, size_t *readbytes)
{
int al, i, j, iret;
- size_t ret, n;
+ size_t n;
SSL3_RECORD *rr;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
return -1;
}
- /*
- * check whether there's a handshake message (client hello?) waiting
- */
- ret = have_handshake_fragment(s, type, buf, len);
- if (ret > 0) {
- *recvd_type = SSL3_RT_HANDSHAKE;
- *readbytes = ret;
- return 1;
- }
-
- /*
- * Now s->rlayer.d->handshake_fragment_len == 0 if
- * type == SSL3_RT_HANDSHAKE.
- */
-
if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s))
{
/* type == SSL3_RT_APPLICATION_DATA */
* then it was unexpected (Hello Request or Client Hello).
*/
- /*
- * In case of record types for which we have 'fragment' storage, fill
- * that so that we can process the data at a fixed place.
- */
- {
- size_t k, dest_maxlen = 0;
- unsigned char *dest = NULL;
- size_t *dest_len = NULL;
-
- if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
- dest_maxlen = sizeof s->rlayer.d->handshake_fragment;
- dest = s->rlayer.d->handshake_fragment;
- dest_len = &s->rlayer.d->handshake_fragment_len;
- } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
- dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
- dest = s->rlayer.d->alert_fragment;
- dest_len = &s->rlayer.d->alert_fragment_len;
- }
- /* else it's a CCS message, or application data or wrong */
- else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) {
- /*
- * Application data while renegotiating is allowed. Try again
- * reading.
- */
- if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) {
- BIO *bio;
- s->s3->in_read_app_data = 2;
- bio = SSL_get_rbio(s);
- s->rwstate = SSL_READING;
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return -1;
- }
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ unsigned int alert_level, alert_descr;
+ unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ + SSL3_RECORD_get_off(rr);
+ PACKET alert;
- /* Not certain if this is the right error handling */
+ if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
+ || !PACKET_get_1(&alert, &alert_level)
+ || !PACKET_get_1(&alert, &alert_descr)
+ || PACKET_remaining(&alert) != 0) {
al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_INVALID_ALERT);
goto f_err;
}
- if (dest_maxlen > 0) {
- /*
- * XDTLS: In a pathological case, the Client Hello may be
- * fragmented--don't always expect dest_maxlen bytes
- */
- if (SSL3_RECORD_get_length(rr) < dest_maxlen) {
- s->rlayer.rstate = SSL_ST_READ_HEADER;
- SSL3_RECORD_set_length(rr, 0);
- goto start;
- }
-
- /* now move 'n' bytes: */
- for (k = 0; k < dest_maxlen; k++) {
- dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
- SSL3_RECORD_add_off(rr, 1);
- SSL3_RECORD_add_length(rr, -1);
- }
- *dest_len = dest_maxlen;
- }
- }
-
- /*-
- * s->rlayer.d->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE;
- * s->rlayer.d->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT.
- * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
- */
-
- if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
- int alert_level = s->rlayer.d->alert_fragment[0];
- int alert_descr = s->rlayer.d->alert_fragment[1];
-
- s->rlayer.d->alert_fragment_len = 0;
-
if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_ALERT,
- s->rlayer.d->alert_fragment, 2, s,
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)
/*
* Unexpected handshake message (Client Hello, or protocol violation)
*/
- if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
- !ossl_statem_get_in_handshake(s)) {
+ if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
+ !ossl_statem_get_in_handshake(s)) {
struct hm_header_st msg_hdr;
- /* this may just be a stale retransmit */
- dtls1_get_message_header(rr->data, &msg_hdr);
- if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) {
+ /*
+ * 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) != s->rlayer.d->r_epoch
+ || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) {
SSL3_RECORD_set_length(rr, 0);
goto start;
}
+ dtls1_get_message_header(rr->data, &msg_hdr);
+
/*
* If we are server, we may have a repeated FINISHED of the client
* here, then retransmit our CCS and FINISHED.
switch (SSL3_RECORD_get_type(rr)) {
default:
- /* TLS just ignores unknown message types */
- if (s->version == TLS1_VERSION) {
- SSL3_RECORD_set_length(rr, 0);
- goto start;
- }
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
goto f_err;
return -1;
}
-/*
- * this only happens when a client hello is received and a handshake
- * is started.
- */
-static size_t have_handshake_fragment(SSL *s, int type, unsigned char *buf,
- size_t len)
-{
-
- if ((type == SSL3_RT_HANDSHAKE)
- && (s->rlayer.d->handshake_fragment_len > 0))
- /* (partially) satisfy request from storage */
- {
- unsigned char *src = s->rlayer.d->handshake_fragment;
- unsigned char *dst = buf;
- size_t k, n;
-
- /* peek == 0 */
- n = 0;
- while ((len > 0) && (s->rlayer.d->handshake_fragment_len > 0)) {
- *dst++ = *src++;
- len--;
- s->rlayer.d->handshake_fragment_len--;
- n++;
- }
- /* move any remaining fragment bytes: */
- for (k = 0; k < s->rlayer.d->handshake_fragment_len; k++)
- s->rlayer.d->handshake_fragment[k] = *src++;
- return n;
- }
-
- return 0;
-}
-
/*
* Call this to write data in records of type 'type' It will return <= 0 if
* not all data has been sent or non-blocking IO.
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include "record_locl.h"
+#include "../packet_locl.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) || \
!( defined(AES_ASM) && ( \
rl->packet = NULL;
rl->packet_length = 0;
rl->wnum = 0;
- memset(rl->alert_fragment, 0, sizeof(rl->alert_fragment));
- rl->alert_fragment_len = 0;
memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment));
rl->handshake_fragment_len = 0;
rl->wpend_tot = 0;
dest_maxlen = sizeof s->rlayer.handshake_fragment;
dest = s->rlayer.handshake_fragment;
dest_len = &s->rlayer.handshake_fragment_len;
- } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
- dest_maxlen = sizeof s->rlayer.alert_fragment;
- dest = s->rlayer.alert_fragment;
- dest_len = &s->rlayer.alert_fragment_len;
}
if (dest_maxlen > 0) {
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
- if (SSL_IS_TLS13(s)
- && SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
- if (*dest_len < dest_maxlen
- || SSL3_RECORD_get_length(rr) != 0) {
- /*
- * TLSv1.3 forbids fragmented alerts, and only one alert
- * may be present in a record
- */
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INVALID_ALERT);
- goto f_err;
- }
- }
-
if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
}
/*-
* s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
- * s->rlayer.alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT.
* (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
*/
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
goto start;
}
- if (s->rlayer.alert_fragment_len >= 2) {
- int alert_level = s->rlayer.alert_fragment[0];
- int alert_descr = s->rlayer.alert_fragment[1];
-
- s->rlayer.alert_fragment_len = 0;
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ unsigned int alert_level, alert_descr;
+ unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ + SSL3_RECORD_get_off(rr);
+ PACKET alert;
+
+ if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
+ || !PACKET_get_1(&alert, &alert_level)
+ || !PACKET_get_1(&alert, &alert_descr)
+ || PACKET_remaining(&alert) != 0) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INVALID_ALERT);
+ goto f_err;
+ }
if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_ALERT,
- s->rlayer.alert_fragment, 2, s,
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)