static int
dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr)
{
    hm_fragment *frag = NULL;
    pitem *item = NULL;
	PQ_64BIT seq64;

    frag = dtls1_hm_fragment_new(msg_hdr->frag_len);
    if ( frag == NULL)
        goto err;

    memcpy(frag->fragment, &(s->init_buf->data[s->init_num]),
        msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH);

    memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

    pq_64bit_init(&seq64);
    pq_64bit_assign_word(&seq64, msg_hdr->seq);

    item = pitem_new(seq64, frag);
    if ( item == NULL)
        goto err;

    pq_64bit_free(&seq64);

    pqueue_insert(s->d1->buffered_messages, item);
    return 1;

err:
    if ( frag != NULL) dtls1_hm_fragment_free(frag);
    if ( item != NULL) OPENSSL_free(item);
    return 0;
}
Exemplo n.º 2
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	if (msg_hdr->seq <= s->d1->handshake_read_seq)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}

	frag = dtls1_hm_fragment_new(frag_len);
	if ( frag == NULL)
		goto err;

	memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

	if (frag_len)
		{
		/* read the body of the fragment (header has already been read */
		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
			frag->fragment,frag_len,0);
		if (i<=0 || (unsigned long)i!=frag_len)
			goto err;
		}

	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);

	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		goto err;

	pqueue_insert(s->d1->buffered_messages, item);
	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemplo n.º 3
0
int
dtls1_buffer_message(SSL *s, int is_ccs)
	{
	pitem *item;
	hm_fragment *frag;
	PQ_64BIT seq64;
	unsigned int epoch = s->d1->w_epoch;

	/* this function is called immediately after a message has 
	 * been serialized */
	OPENSSL_assert(s->init_off == 0);

	frag = dtls1_hm_fragment_new(s->init_num);

	memcpy(frag->fragment, s->init_buf->data, s->init_num);

	if ( is_ccs)
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
		epoch++;
		}
	else
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
		}

	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
	frag->msg_header.type = s->d1->w_msg_hdr.type;
	frag->msg_header.frag_off = 0;
	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.is_ccs = is_ccs;

	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, epoch<<16 | frag->msg_header.seq);

	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		dtls1_hm_fragment_free(frag);
		return 0;
		}

#if 0
	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
#endif

	pqueue_insert(s->d1->sent_messages, item);
	return 1;
	}
Exemplo n.º 4
0
int
dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
	int *found)
	{
	int ret;
	/* XDTLS: for now assuming that read/writes are blocking */
	pitem *item;
	hm_fragment *frag ;
	unsigned long header_length;
	PQ_64BIT seq64;

	/*
	  OPENSSL_assert(s->init_num == 0);
	  OPENSSL_assert(s->init_off == 0);
	 */

	/* XDTLS:  the requested message ought to be found, otherwise error */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, seq);

	item = pqueue_find(s->d1->sent_messages, seq64);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
		*found = 0;
		return 0;
		}

	*found = 1;
	frag = (hm_fragment *)item->data;

	if ( frag->msg_header.is_ccs)
		header_length = DTLS1_CCS_HEADER_LENGTH;
	else
		header_length = DTLS1_HM_HEADER_LENGTH;

	memcpy(s->init_buf->data, frag->fragment, 
		frag->msg_header.msg_len + header_length);
		s->init_num = frag->msg_header.msg_len + header_length;

	dtls1_set_message_header_int(s, frag->msg_header.type, 
		frag->msg_header.msg_len, frag->msg_header.seq, 0, 
		frag->msg_header.frag_len);

	s->d1->retransmitting = 1;
	ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
		SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
	s->d1->retransmitting = 0;

	(void)BIO_flush(SSL_get_wbio(s));
	return ret;
	}
Exemplo n.º 5
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Try to find item in queue, to prevent duplicate entries */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);

	/* If we already have an entry and this one is a fragment,
	 * don't discard it and rather try to reassemble it.
	 */
	if (item != NULL && frag_len < msg_hdr->msg_len)
		item = NULL;

	/* Discard the message if sequence number was already there, is
	 * too far in the future, already in the queue or if we received
	 * a FINISHED before the SERVER_HELLO, which then must be a stale
	 * retransmit.
	 */
	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))
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}
	else
		{
		if (frag_len && frag_len < msg_hdr->msg_len)
			return dtls1_reassemble_fragment(s, msg_hdr, ok);

		frag = dtls1_hm_fragment_new(frag_len, 0);
		if ( frag == NULL)
			goto err;

		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

		if (frag_len)
			{
			/* read the body of the fragment (header has already been read) */
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				frag->fragment,frag_len,0);
			if (i<=0 || (unsigned long)i!=frag_len)
				goto err;
			}

		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);

		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);
		if ( item == NULL)
			goto err;

		pqueue_insert(s->d1->buffered_messages, item);
		}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemplo n.º 6
0
static int
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
	{
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	int i = -1, is_complete;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len, max_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Determine maximum allowed message size. Depends on (user set)
	 * maximum certificate length, but 16k is minimum.
	 */
	if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
		max_len = s->max_cert_list;
	else
		max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;

	if ((msg_hdr->frag_off+frag_len) > max_len)
		goto err;

	/* Try to find item in queue */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);

	if (item == NULL)
		{
		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
		if ( frag == NULL)
			goto err;
		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
		frag->msg_header.frag_len = frag->msg_header.msg_len;
		frag->msg_header.frag_off = 0;
		}
	else
		{
		frag = (hm_fragment*) item->data;
		if (frag->msg_header.msg_len != msg_hdr->msg_len)
			{
			item = NULL;
			frag = NULL;
			goto err;
			}
		}


	/* If message is already reassembled, this must be a
	 * retransmit and can be dropped.
	 */
	if (frag->reassembly == NULL)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		return DTLS1_HM_FRAGMENT_RETRY;
		}

	/* read the body of the fragment (header has already been read */
	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
		frag->fragment + msg_hdr->frag_off,frag_len,0);
	if (i<=0 || (unsigned long)i!=frag_len)
		goto err;

	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
	                    (long)(msg_hdr->frag_off + frag_len));

	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
	                           is_complete);

	if (is_complete)
		{
		OPENSSL_free(frag->reassembly);
		frag->reassembly = NULL;
		}

	if (item == NULL)
		{
		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);
		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);

		if (item == NULL)
			{
			i = -1;
			goto err;
			}

		pqueue_insert(s->d1->buffered_messages, item);
		}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if (frag != NULL) dtls1_hm_fragment_free(frag);
	if (item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}
Exemplo n.º 7
0
int
dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
	int *found)
	{
	int ret;
	/* XDTLS: for now assuming that read/writes are blocking */
	pitem *item;
	hm_fragment *frag ;
	unsigned long header_length;
	PQ_64BIT seq64;
	struct dtls1_retransmit_state saved_state;
	unsigned char save_write_sequence[8];

	/*
	  OPENSSL_assert(s->init_num == 0);
	  OPENSSL_assert(s->init_off == 0);
	 */

	/* XDTLS:  the requested message ought to be found, otherwise error */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, seq);

	item = pqueue_find(s->d1->sent_messages, seq64);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
		*found = 0;
		return 0;
		}

	*found = 1;
	frag = (hm_fragment *)item->data;

	if ( frag->msg_header.is_ccs)
		header_length = DTLS1_CCS_HEADER_LENGTH;
	else
		header_length = DTLS1_HM_HEADER_LENGTH;

	memcpy(s->init_buf->data, frag->fragment, 
		frag->msg_header.msg_len + header_length);
		s->init_num = frag->msg_header.msg_len + header_length;

	dtls1_set_message_header_int(s, frag->msg_header.type, 
		frag->msg_header.msg_len, frag->msg_header.seq, 0, 
		frag->msg_header.frag_len);

	/* save current state */
	saved_state.enc_write_ctx = s->enc_write_ctx;
	saved_state.write_hash = s->write_hash;
	saved_state.compress = s->compress;
	saved_state.session = s->session;
	saved_state.epoch = s->d1->w_epoch;
	saved_state.epoch = s->d1->w_epoch;
	
	s->d1->retransmitting = 1;
	
	/* restore state in which the message was originally sent */
	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
	s->compress = frag->msg_header.saved_retransmit_state.compress;
	s->session = frag->msg_header.saved_retransmit_state.session;
	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
	
	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
	{
		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
	}
	
	ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
	
	/* restore current state */
	s->enc_write_ctx = saved_state.enc_write_ctx;
	s->write_hash = saved_state.write_hash;
	s->compress = saved_state.compress;
	s->session = saved_state.session;
	s->d1->w_epoch = saved_state.epoch;
	
	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
	{
		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
	}

	s->d1->retransmitting = 0;

	(void)BIO_flush(SSL_get_wbio(s));
	return ret;
	}
Exemplo n.º 8
0
int
dtls1_buffer_message(SSL *s, int is_ccs)
	{
	pitem *item;
	hm_fragment *frag;
	PQ_64BIT seq64;

	/* this function is called immediately after a message has 
	 * been serialized */
	OPENSSL_assert(s->init_off == 0);

	frag = dtls1_hm_fragment_new(s->init_num, 0);

	memcpy(frag->fragment, s->init_buf->data, s->init_num);

	if ( is_ccs)
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
		}
	else
		{
		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
		}

	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
	frag->msg_header.type = s->d1->w_msg_hdr.type;
	frag->msg_header.frag_off = 0;
	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
	frag->msg_header.is_ccs = is_ccs;

	/* save current state*/
	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
	frag->msg_header.saved_retransmit_state.compress = s->compress;
	frag->msg_header.saved_retransmit_state.session = s->session;
	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;

	pq_64bit_init(&seq64);

	pq_64bit_assign_word(&seq64,
						 dtls1_get_queue_priority(frag->msg_header.seq,
												  frag->msg_header.is_ccs));
		
	item = pitem_new(seq64, frag);
	pq_64bit_free(&seq64);
	if ( item == NULL)
		{
		dtls1_hm_fragment_free(frag);
		return 0;
		}

#if 0
	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
#endif

	pqueue_insert(s->d1->sent_messages, item);
	return 1;
	}
Exemplo n.º 9
0
static int
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
{
	int i=-1;
	hm_fragment *frag = NULL;
	pitem *item = NULL;
	PQ_64BIT seq64;
	unsigned long frag_len = msg_hdr->frag_len;

	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
		goto err;

	/* Try to find item in queue, to prevent duplicate entries */
	pq_64bit_init(&seq64);
	pq_64bit_assign_word(&seq64, msg_hdr->seq);
	item = pqueue_find(s->d1->buffered_messages, seq64);
	pq_64bit_free(&seq64);
	
	/* Discard the message if sequence number was already there, is
	 * too far in the future or the fragment is already in the queue */
	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL)
		{
		unsigned char devnull [256];

		while (frag_len)
			{
			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
				devnull,
				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
			if (i<=0) goto err;
			frag_len -= i;
			}
		}

	if (frag_len)
	{
		frag = dtls1_hm_fragment_new(frag_len);
		if ( frag == NULL)
			goto err;

		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));

		/* read the body of the fragment (header has already been read) */
		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
			frag->fragment,frag_len,0);
		if (i<=0 || (unsigned long)i!=frag_len)
			goto err;

		pq_64bit_init(&seq64);
		pq_64bit_assign_word(&seq64, msg_hdr->seq);

		item = pitem_new(seq64, frag);
		pq_64bit_free(&seq64);
		if ( item == NULL)
			goto err;

		pqueue_insert(s->d1->buffered_messages, item);
	}

	return DTLS1_HM_FRAGMENT_RETRY;

err:
	if ( frag != NULL) dtls1_hm_fragment_free(frag);
	if ( item != NULL) OPENSSL_free(item);
	*ok = 0;
	return i;
	}