if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
OPENSSL_assert(s->init_num ==
- (int)s->d1->w_msg_hdr.msg_len +
- DTLS1_HM_HEADER_LENGTH);
+ (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
if (s->write_hash) {
if (s->enc_write_ctx
*/
return -1;
}
- dtls1_fix_message_header(s, frag_off,
- len - DTLS1_HM_HEADER_LENGTH);
+ dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH);
dtls1_write_message_header(s,
(unsigned char *)&s->init_buf->
data[s->init_off]);
}
- ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off],
- len);
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len);
if (ret < 0) {
/*
* might need to update MTU here, but we don't know which
again:
ok = dtls_get_reassembled_message(s, &tmplen);
- if (tmplen == DTLS1_HM_BAD_FRAGMENT
- || tmplen == DTLS1_HM_FRAGMENT_RETRY) {
+ if (tmplen == DTLS1_HM_BAD_FRAGMENT || tmplen == DTLS1_HM_FRAGMENT_RETRY) {
/* bad fragment received */
goto again;
} else if (tmplen <= 0 && !ok) {
s->d1->handshake_read_seq++;
-
s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
*len = s->init_num;
return 1;
}
+/*
+ * dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
+ * may be greater if the maximum certificate list size requires it.
+ */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+{
+ unsigned long max_len =
+ DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+}
+
static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
{
size_t frag_off, frag_len, msg_len;
frag_len = msg_hdr->frag_len;
/* sanity checking */
- if ((frag_off + frag_len) > msg_len) {
+ if ((frag_off + frag_len) > msg_len
+ || msg_len > dtls1_max_handshake_message_len(s)) {
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
return SSL_AD_ILLEGAL_PARAMETER;
}
if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
/*
- * msg_len is limited to 2^24, but is effectively checked against max
- * above
+ * msg_len is limited to 2^24, but is effectively checked against
+ * dtls_max_handshake_message_len(s) above
*/
- if (!BUF_MEM_grow_clean
- (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
return SSL_AD_INTERNAL_ERROR;
}
int al;
*ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
- frag = (hm_fragment *)item->data;
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
return 0;
}
-/*
- * dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
- * may be greater if the maximum certificate list size requires it.
- */
-static unsigned long dtls1_max_handshake_message_len(const SSL *s)
-{
- unsigned long max_len =
- DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
- if (max_len < (unsigned long)s->max_cert_list)
- return s->max_cert_list;
- return max_len;
-}
-
static int
dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
{
*/
if (msg_hdr->seq <= s->d1->handshake_read_seq ||
msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
- (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
- {
+ (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) {
unsigned char devnull[256];
while (frag_len) {
*/
int dtls_construct_change_cipher_spec(SSL *s)
{
- unsigned char *p;
+ WPACKET pkt;
+
+ if (!WPACKET_init(&pkt, s->init_buf)
+ || !WPACKET_put_bytes_u8(&pkt, SSL3_MT_CCS)) {
+ SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- p = (unsigned char *)s->init_buf->data;
- *p++ = SSL3_MT_CCS;
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
s->init_num = DTLS1_CCS_HEADER_LENGTH;
if (s->version == DTLS1_BAD_VER) {
s->d1->next_handshake_write_seq++;
- s2n(s->d1->handshake_write_seq, p);
+
+ if (!WPACKET_put_bytes_u16(&pkt, s->d1->handshake_write_seq)) {
+ SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
s->init_num += 2;
}
+ if (!WPACKET_finish(&pkt)) {
+ SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
s->init_off = 0;
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
/* buffer the message to handle re-xmits */
if (!dtls1_buffer_message(s, 1)) {
SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
- return 0;
+ goto err ;
}
return 1;
+ err:
+ WPACKET_cleanup(&pkt);
+ ossl_statem_set_error(s);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+
+ return 0;
}
#ifndef OPENSSL_NO_SCTP
if (dtls1_retransmit_message(s, (unsigned short)
dtls1_get_queue_priority
(frag->msg_header.seq,
- frag->msg_header.is_ccs),
- &found) <= 0)
+ frag->msg_header.is_ccs), &found) <= 0)
return -1;
}
if (is_ccs) {
/* For DTLS1_BAD_VER the header length is non-standard */
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
- ((s->version==DTLS1_BAD_VER)?3:DTLS1_CCS_HEADER_LENGTH)
+ ((s->version ==
+ DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
== (unsigned int)s->init_num);
} else {
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
return 1;
}
-int
-dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
+int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
{
int ret;
/* XDTLS: for now assuming that read/writes are blocking */
s->compress = frag->msg_header.saved_retransmit_state.compress;
s->session = frag->msg_header.saved_retransmit_state.session;
DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer,
- frag->msg_header.saved_retransmit_state.epoch);
+ frag->msg_header.
+ saved_retransmit_state.epoch);
ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
return ret;
}
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *s)
-{
- pitem *item;
-
- for (item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
-}
-
void dtls1_set_message_header(SSL *s,
unsigned char mt, unsigned long len,
- unsigned long frag_off,
- unsigned long frag_len)
+ unsigned long frag_off, unsigned long frag_len)
{
if (frag_off == 0) {
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
}
static void
-dtls1_fix_message_header(SSL *s, unsigned long frag_off,
- unsigned long frag_len)
+dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len)
{
struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
return p;
}
-void
-dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
+void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
{
memset(msg_hdr, 0, sizeof(*msg_hdr));
msg_hdr->type = *(data++);
n2l3(data, msg_hdr->frag_len);
}
+/*
+ * Temporary name. To be renamed dtls1_set_handshake_header() once all WPACKET
+ * conversion is complete. The old dtls1_set_handshake_heder() can be deleted
+ * at that point.
+ * TODO - RENAME ME
+ */
+int dtls1_set_handshake_header2(SSL *s, WPACKET *pkt, int htype)
+{
+ unsigned char *header;
+
+ dtls1_set_message_header(s, htype, 0, 0, 0);
+ /*
+ * We allocate space at the start for the message header. This gets filled
+ * in later
+ */
+ if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
+ || !WPACKET_start_sub_packet(pkt))
+ return 0;
+
+ return 1;
+}
+
+int dtls1_close_construct_packet(SSL *s, WPACKET *pkt)
+{
+ size_t msglen;
+
+ if (!WPACKET_close(pkt)
+ || !WPACKET_get_length(pkt, &msglen)
+ || msglen > INT_MAX
+ || !WPACKET_finish(pkt))
+ return 0;
+ s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
+ s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
+ s->init_num = (int)msglen;
+ s->init_off = 0;
+
+ /* Buffer the message to handle re-xmits */
+ if (!dtls1_buffer_message(s, 0))
+ return 0;
+
+ return 1;
+}