xref: /openbsd-src/lib/libssl/d1_both.c (revision 40ca958bee889ced523da7638a7aa6d880d47ab8)
1*40ca958bSjmc /* $OpenBSD: d1_both.c,v 1.84 2022/12/26 07:31:44 jmc Exp $ */
25650a0e1Sdjm /*
35650a0e1Sdjm  * DTLS implementation written by Nagendra Modadugu
45650a0e1Sdjm  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
55650a0e1Sdjm  */
65650a0e1Sdjm /* ====================================================================
75650a0e1Sdjm  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
85650a0e1Sdjm  *
95650a0e1Sdjm  * Redistribution and use in source and binary forms, with or without
105650a0e1Sdjm  * modification, are permitted provided that the following conditions
115650a0e1Sdjm  * are met:
125650a0e1Sdjm  *
135650a0e1Sdjm  * 1. Redistributions of source code must retain the above copyright
145650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer.
155650a0e1Sdjm  *
165650a0e1Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
175650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer in
185650a0e1Sdjm  *    the documentation and/or other materials provided with the
195650a0e1Sdjm  *    distribution.
205650a0e1Sdjm  *
215650a0e1Sdjm  * 3. All advertising materials mentioning features or use of this
225650a0e1Sdjm  *    software must display the following acknowledgment:
235650a0e1Sdjm  *    "This product includes software developed by the OpenSSL Project
245650a0e1Sdjm  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
255650a0e1Sdjm  *
265650a0e1Sdjm  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
275650a0e1Sdjm  *    endorse or promote products derived from this software without
285650a0e1Sdjm  *    prior written permission. For written permission, please contact
295650a0e1Sdjm  *    openssl-core@openssl.org.
305650a0e1Sdjm  *
315650a0e1Sdjm  * 5. Products derived from this software may not be called "OpenSSL"
325650a0e1Sdjm  *    nor may "OpenSSL" appear in their names without prior written
335650a0e1Sdjm  *    permission of the OpenSSL Project.
345650a0e1Sdjm  *
355650a0e1Sdjm  * 6. Redistributions of any form whatsoever must retain the following
365650a0e1Sdjm  *    acknowledgment:
375650a0e1Sdjm  *    "This product includes software developed by the OpenSSL Project
385650a0e1Sdjm  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
395650a0e1Sdjm  *
405650a0e1Sdjm  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
415650a0e1Sdjm  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
425650a0e1Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
435650a0e1Sdjm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
445650a0e1Sdjm  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
455650a0e1Sdjm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
465650a0e1Sdjm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
475650a0e1Sdjm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485650a0e1Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
495650a0e1Sdjm  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
505650a0e1Sdjm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
515650a0e1Sdjm  * OF THE POSSIBILITY OF SUCH DAMAGE.
525650a0e1Sdjm  * ====================================================================
535650a0e1Sdjm  *
545650a0e1Sdjm  * This product includes cryptographic software written by Eric Young
555650a0e1Sdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
565650a0e1Sdjm  * Hudson (tjh@cryptsoft.com).
575650a0e1Sdjm  *
585650a0e1Sdjm  */
595650a0e1Sdjm /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
605650a0e1Sdjm  * All rights reserved.
615650a0e1Sdjm  *
625650a0e1Sdjm  * This package is an SSL implementation written
635650a0e1Sdjm  * by Eric Young (eay@cryptsoft.com).
645650a0e1Sdjm  * The implementation was written so as to conform with Netscapes SSL.
655650a0e1Sdjm  *
665650a0e1Sdjm  * This library is free for commercial and non-commercial use as long as
675650a0e1Sdjm  * the following conditions are aheared to.  The following conditions
685650a0e1Sdjm  * apply to all code found in this distribution, be it the RC4, RSA,
695650a0e1Sdjm  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
705650a0e1Sdjm  * included with this distribution is covered by the same copyright terms
715650a0e1Sdjm  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
725650a0e1Sdjm  *
735650a0e1Sdjm  * Copyright remains Eric Young's, and as such any Copyright notices in
745650a0e1Sdjm  * the code are not to be removed.
755650a0e1Sdjm  * If this package is used in a product, Eric Young should be given attribution
765650a0e1Sdjm  * as the author of the parts of the library used.
775650a0e1Sdjm  * This can be in the form of a textual message at program startup or
785650a0e1Sdjm  * in documentation (online or textual) provided with the package.
795650a0e1Sdjm  *
805650a0e1Sdjm  * Redistribution and use in source and binary forms, with or without
815650a0e1Sdjm  * modification, are permitted provided that the following conditions
825650a0e1Sdjm  * are met:
835650a0e1Sdjm  * 1. Redistributions of source code must retain the copyright
845650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer.
855650a0e1Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
865650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer in the
875650a0e1Sdjm  *    documentation and/or other materials provided with the distribution.
885650a0e1Sdjm  * 3. All advertising materials mentioning features or use of this software
895650a0e1Sdjm  *    must display the following acknowledgement:
905650a0e1Sdjm  *    "This product includes cryptographic software written by
915650a0e1Sdjm  *     Eric Young (eay@cryptsoft.com)"
925650a0e1Sdjm  *    The word 'cryptographic' can be left out if the rouines from the library
935650a0e1Sdjm  *    being used are not cryptographic related :-).
945650a0e1Sdjm  * 4. If you include any Windows specific code (or a derivative thereof) from
955650a0e1Sdjm  *    the apps directory (application code) you must include an acknowledgement:
965650a0e1Sdjm  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
975650a0e1Sdjm  *
985650a0e1Sdjm  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
995650a0e1Sdjm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1005650a0e1Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1015650a0e1Sdjm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1025650a0e1Sdjm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1035650a0e1Sdjm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1045650a0e1Sdjm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1055650a0e1Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1065650a0e1Sdjm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1075650a0e1Sdjm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1085650a0e1Sdjm  * SUCH DAMAGE.
1095650a0e1Sdjm  *
1105650a0e1Sdjm  * The licence and distribution terms for any publically available version or
1115650a0e1Sdjm  * derivative of this code cannot be changed.  i.e. this code cannot simply be
1125650a0e1Sdjm  * copied and put under another distribution licence
1135650a0e1Sdjm  * [including the GNU Public Licence.]
1145650a0e1Sdjm  */
1155650a0e1Sdjm 
1165650a0e1Sdjm #include <limits.h>
1175650a0e1Sdjm #include <stdio.h>
118c5899dbcSjsing #include <string.h>
119c5899dbcSjsing 
1205650a0e1Sdjm #include <openssl/buffer.h>
1215650a0e1Sdjm #include <openssl/evp.h>
122c5899dbcSjsing #include <openssl/objects.h>
1235650a0e1Sdjm #include <openssl/x509.h>
1245650a0e1Sdjm 
1254fd32991Sdoug #include "bytestring.h"
126c9675a23Stb #include "dtls_local.h"
1274b0cebd1Sjsing #include "pqueue.h"
128c9675a23Stb #include "ssl_local.h"
12946859c4aSjsing 
130f1535dc8Sdjm #define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
131f1535dc8Sdjm 
132f1535dc8Sdjm #define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
133f1535dc8Sdjm 			if ((end) - (start) <= 8) { \
134f1535dc8Sdjm 				long ii; \
135f1535dc8Sdjm 				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
136f1535dc8Sdjm 			} else { \
137f1535dc8Sdjm 				long ii; \
138f1535dc8Sdjm 				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
139f1535dc8Sdjm 				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
140f1535dc8Sdjm 				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
141f1535dc8Sdjm 			} }
142f1535dc8Sdjm 
143f1535dc8Sdjm #define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
144f1535dc8Sdjm 			long ii; \
145f1535dc8Sdjm 			OPENSSL_assert((msg_len) > 0); \
146f1535dc8Sdjm 			is_complete = 1; \
147f1535dc8Sdjm 			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
148f1535dc8Sdjm 			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
149f1535dc8Sdjm 				if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
150f1535dc8Sdjm 
151aade1140Stb static const unsigned char bitmask_start_values[] = {
1524a47b859Sjsing 	0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80
1534a47b859Sjsing };
154aade1140Stb static const unsigned char bitmask_end_values[] = {
1554a47b859Sjsing 	0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f
1564a47b859Sjsing };
1575650a0e1Sdjm 
1585650a0e1Sdjm /* XDTLS:  figure out the right values */
159aade1140Stb static const unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
1605650a0e1Sdjm 
1615650a0e1Sdjm static unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
1625650a0e1Sdjm static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
1635650a0e1Sdjm     unsigned long frag_len);
16433b95d8bSjsing static int dtls1_write_message_header(const struct hm_header_st *msg_hdr,
16533b95d8bSjsing     unsigned long frag_off, unsigned long frag_len, unsigned char *p);
1664a47b859Sjsing static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max,
1674a47b859Sjsing     int *ok);
1685650a0e1Sdjm 
16955a1a82cSjsing void dtls1_hm_fragment_free(hm_fragment *frag);
1701987507fSjsing 
1715650a0e1Sdjm static hm_fragment *
dtls1_hm_fragment_new(unsigned long frag_len,int reassembly)172f1535dc8Sdjm dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
1735650a0e1Sdjm {
1741987507fSjsing 	hm_fragment *frag;
1755650a0e1Sdjm 
1761987507fSjsing 	if ((frag = calloc(1, sizeof(*frag))) == NULL)
1771987507fSjsing 		goto err;
1785650a0e1Sdjm 
1791987507fSjsing 	if (frag_len > 0) {
1801987507fSjsing 		if ((frag->fragment = calloc(1, frag_len)) == NULL)
1811987507fSjsing 			goto err;
1825650a0e1Sdjm 	}
1835650a0e1Sdjm 
1841987507fSjsing 	/* Initialize reassembly bitmask if necessary. */
1854a47b859Sjsing 	if (reassembly) {
1861987507fSjsing 		if ((frag->reassembly = calloc(1,
1871987507fSjsing 		    RSMBLY_BITMASK_SIZE(frag_len))) == NULL)
1881987507fSjsing 			goto err;
189f1535dc8Sdjm 	}
190f1535dc8Sdjm 
1915650a0e1Sdjm 	return frag;
1921987507fSjsing 
1931987507fSjsing  err:
1941987507fSjsing 	dtls1_hm_fragment_free(frag);
1951987507fSjsing 	return NULL;
1965650a0e1Sdjm }
1975650a0e1Sdjm 
19855a1a82cSjsing void
dtls1_hm_fragment_free(hm_fragment * frag)1995650a0e1Sdjm dtls1_hm_fragment_free(hm_fragment *frag)
2005650a0e1Sdjm {
201dd39d9ddSdoug 	if (frag == NULL)
202dd39d9ddSdoug 		return;
203724b1063Sjca 
2046f3a6cb1Sbeck 	free(frag->fragment);
2056f3a6cb1Sbeck 	free(frag->reassembly);
2066f3a6cb1Sbeck 	free(frag);
2075650a0e1Sdjm }
2085650a0e1Sdjm 
2096f7f653bSjsing /* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
2104a47b859Sjsing int
dtls1_do_write(SSL * s,int type)2114a47b859Sjsing dtls1_do_write(SSL *s, int type)
2125650a0e1Sdjm {
2135650a0e1Sdjm 	int ret;
2145650a0e1Sdjm 	int curr_mtu;
2159123ae00Sjsing 	unsigned int len, frag_off;
2169123ae00Sjsing 	size_t overhead;
2175650a0e1Sdjm 
2185650a0e1Sdjm 	/* AHA!  Figure out the MTU, and stick to the right size */
219f19d9718Sjsing 	if (s->d1->mtu < dtls1_min_mtu() &&
220f63b7f2bSjsing 	    !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
221f19d9718Sjsing 		s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
2224a47b859Sjsing 		    BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
2235650a0e1Sdjm 
224574f5b78Sguenther 		/*
225574f5b78Sguenther 		 * I've seen the kernel return bogus numbers when it
226574f5b78Sguenther 		 * doesn't know the MTU (ie., the initial write), so just
227574f5b78Sguenther 		 * make sure we have a reasonable number
228574f5b78Sguenther 		 */
229f19d9718Sjsing 		if (s->d1->mtu < dtls1_min_mtu()) {
230f19d9718Sjsing 			s->d1->mtu = 0;
231f19d9718Sjsing 			s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
2325650a0e1Sdjm 			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
233f19d9718Sjsing 			    s->d1->mtu, NULL);
2345650a0e1Sdjm 		}
2355650a0e1Sdjm 	}
2365650a0e1Sdjm 
237f19d9718Sjsing 	OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu());
2384a47b859Sjsing 	/* should have something reasonable now */
239bad7092fSdjm 
2406f7f653bSjsing 	if (s->init_off == 0  && type == SSL3_RT_HANDSHAKE)
2416f7f653bSjsing 		OPENSSL_assert(s->init_num ==
242f19d9718Sjsing 		    (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
2435650a0e1Sdjm 
2446f7f653bSjsing 	if (!tls12_record_layer_write_overhead(s->rl, &overhead))
2459123ae00Sjsing 		return -1;
246f1535dc8Sdjm 
2475650a0e1Sdjm 	frag_off = 0;
2486f7f653bSjsing 	while (s->init_num) {
249f19d9718Sjsing 		curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -
2509123ae00Sjsing 		    DTLS1_RT_HEADER_LENGTH - overhead;
2515650a0e1Sdjm 
2524a47b859Sjsing 		if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
2535650a0e1Sdjm 			/* grr.. we could get an error if MTU picked was wrong */
2545650a0e1Sdjm 			ret = BIO_flush(SSL_get_wbio(s));
2555650a0e1Sdjm 			if (ret <= 0)
2565650a0e1Sdjm 				return ret;
257f19d9718Sjsing 			curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH -
2589123ae00Sjsing 			    overhead;
2595650a0e1Sdjm 		}
2605650a0e1Sdjm 
2616f7f653bSjsing 		if (s->init_num > curr_mtu)
2625650a0e1Sdjm 			len = curr_mtu;
2635650a0e1Sdjm 		else
2646f7f653bSjsing 			len = s->init_num;
2655650a0e1Sdjm 
2665650a0e1Sdjm 		/* XDTLS: this function is too long.  split out the CCS part */
2674a47b859Sjsing 		if (type == SSL3_RT_HANDSHAKE) {
2686f7f653bSjsing 			if (s->init_off != 0) {
2696f7f653bSjsing 				OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
2706f7f653bSjsing 				s->init_off -= DTLS1_HM_HEADER_LENGTH;
2716f7f653bSjsing 				s->init_num += DTLS1_HM_HEADER_LENGTH;
2725650a0e1Sdjm 
2736f7f653bSjsing 				if (s->init_num > curr_mtu)
27497222eddSmiod 					len = curr_mtu;
27597222eddSmiod 				else
2766f7f653bSjsing 					len = s->init_num;
2775650a0e1Sdjm 			}
2785650a0e1Sdjm 
2795650a0e1Sdjm 			dtls1_fix_message_header(s, frag_off,
2805650a0e1Sdjm 			    len - DTLS1_HM_HEADER_LENGTH);
2815650a0e1Sdjm 
282f19d9718Sjsing 			if (!dtls1_write_message_header(&s->d1->w_msg_hdr,
283f19d9718Sjsing 			    s->d1->w_msg_hdr.frag_off, s->d1->w_msg_hdr.frag_len,
2846f7f653bSjsing 			    (unsigned char *)&s->init_buf->data[s->init_off]))
28533b95d8bSjsing 				return -1;
2865650a0e1Sdjm 
2875650a0e1Sdjm 			OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH);
2885650a0e1Sdjm 		}
2895650a0e1Sdjm 
2904a47b859Sjsing 		ret = dtls1_write_bytes(s, type,
2916f7f653bSjsing 		    &s->init_buf->data[s->init_off], len);
2924a47b859Sjsing 		if (ret < 0) {
293574f5b78Sguenther 			/*
294574f5b78Sguenther 			 * Might need to update MTU here, but we don't know
295574f5b78Sguenther 			 * which previous packet caused the failure -- so
296574f5b78Sguenther 			 * can't really retransmit anything.  continue as
297574f5b78Sguenther 			 * if everything is fine and wait for an alert to
298574f5b78Sguenther 			 * handle the retransmit
2995650a0e1Sdjm 			 */
3005650a0e1Sdjm 			if (BIO_ctrl(SSL_get_wbio(s),
301f1535dc8Sdjm 			    BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0)
302f19d9718Sjsing 				s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
3035650a0e1Sdjm 				    BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
3045650a0e1Sdjm 			else
3055650a0e1Sdjm 				return (-1);
3064a47b859Sjsing 		} else {
3075650a0e1Sdjm 
308574f5b78Sguenther 			/*
309574f5b78Sguenther 			 * Bad if this assert fails, only part of the
310574f5b78Sguenther 			 * handshake message got sent.  but why would
311574f5b78Sguenther 			 * this happen?
312574f5b78Sguenther 			 */
3135650a0e1Sdjm 			OPENSSL_assert(len == (unsigned int)ret);
3145650a0e1Sdjm 
315f63b7f2bSjsing 			if (type == SSL3_RT_HANDSHAKE &&
316f19d9718Sjsing 			    !s->d1->retransmitting) {
317574f5b78Sguenther 				/*
318574f5b78Sguenther 				 * Should not be done for 'Hello Request's,
319574f5b78Sguenther 				 * but in that case we'll ignore the result
320574f5b78Sguenther 				 * anyway
321574f5b78Sguenther 				 */
3226f7f653bSjsing 				unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
323f19d9718Sjsing 				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
3245650a0e1Sdjm 				int xlen;
3255650a0e1Sdjm 
3267489cb3dSjsing 				if (frag_off == 0) {
327574f5b78Sguenther 					/*
328574f5b78Sguenther 					 * Reconstruct message header is if it
329574f5b78Sguenther 					 * is being sent in single fragment
330574f5b78Sguenther 					 */
33133b95d8bSjsing 					if (!dtls1_write_message_header(msg_hdr,
33233b95d8bSjsing 					    0, msg_hdr->msg_len, p))
33333b95d8bSjsing 						return (-1);
3345650a0e1Sdjm 					xlen = ret;
3354a47b859Sjsing 				} else {
3365650a0e1Sdjm 					p += DTLS1_HM_HEADER_LENGTH;
3375650a0e1Sdjm 					xlen = ret - DTLS1_HM_HEADER_LENGTH;
3385650a0e1Sdjm 				}
3395650a0e1Sdjm 
340cef855dcSjsing 				tls1_transcript_record(s, p, xlen);
3415650a0e1Sdjm 			}
3425650a0e1Sdjm 
3436f7f653bSjsing 			if (ret == s->init_num) {
3446f7f653bSjsing 				if (s->msg_callback)
3456f7f653bSjsing 					s->msg_callback(1, s->version, type,
3466f7f653bSjsing 					    s->init_buf->data,
3476f7f653bSjsing 					    (size_t)(s->init_off + s->init_num),
3486f7f653bSjsing 					    s, s->msg_callback_arg);
3495650a0e1Sdjm 
3506f7f653bSjsing 				s->init_off = 0;
3514a47b859Sjsing 				/* done writing this message */
3526f7f653bSjsing 				s->init_num = 0;
3535650a0e1Sdjm 
3545650a0e1Sdjm 				return (1);
3555650a0e1Sdjm 			}
3566f7f653bSjsing 			s->init_off += ret;
3576f7f653bSjsing 			s->init_num -= ret;
3585650a0e1Sdjm 			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
3595650a0e1Sdjm 		}
3605650a0e1Sdjm 	}
3615650a0e1Sdjm 	return (0);
3625650a0e1Sdjm }
3635650a0e1Sdjm 
3645650a0e1Sdjm 
365574f5b78Sguenther /*
366574f5b78Sguenther  * Obtain handshake message of message type 'mt' (any if mt == -1),
3675650a0e1Sdjm  * maximum acceptable body length 'max'.
3685650a0e1Sdjm  * Read an entire handshake message.  Handshake messages arrive in
3695650a0e1Sdjm  * fragments.
3705650a0e1Sdjm  */
371f2c3e964Sjsing int
dtls1_get_message(SSL * s,int st1,int stn,int mt,long max)372f2c3e964Sjsing dtls1_get_message(SSL *s, int st1, int stn, int mt, long max)
3735650a0e1Sdjm {
3745650a0e1Sdjm 	struct hm_header_st *msg_hdr;
375f1535dc8Sdjm 	unsigned char *p;
376f1535dc8Sdjm 	unsigned long msg_len;
377f2c3e964Sjsing 	int i, al, ok;
3785650a0e1Sdjm 
379574f5b78Sguenther 	/*
3806f7f653bSjsing 	 * s3->tmp is used to store messages that are unexpected, caused
381574f5b78Sguenther 	 * by the absence of an optional handshake message
382574f5b78Sguenther 	 */
38302876cc3Sjsing 	if (s->s3->hs.tls12.reuse_message) {
38402876cc3Sjsing 		s->s3->hs.tls12.reuse_message = 0;
38502876cc3Sjsing 		if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) {
3865650a0e1Sdjm 			al = SSL_AD_UNEXPECTED_MESSAGE;
387c9d7abb7Sbeck 			SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
388ba06b73eStb 			goto fatal_err;
3895650a0e1Sdjm 		}
3906f7f653bSjsing 		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
3916f7f653bSjsing 		s->init_num = (int)s->s3->hs.tls12.message_size;
392f2c3e964Sjsing 		return 1;
3935650a0e1Sdjm 	}
3945650a0e1Sdjm 
395f19d9718Sjsing 	msg_hdr = &s->d1->r_msg_hdr;
396b7c5dcbcSjsing 	memset(msg_hdr, 0, sizeof(struct hm_header_st));
3975650a0e1Sdjm 
398f1535dc8Sdjm  again:
399f2c3e964Sjsing 	i = dtls1_get_message_fragment(s, st1, stn, max, &ok);
4005650a0e1Sdjm 	if (i == DTLS1_HM_BAD_FRAGMENT ||
4015650a0e1Sdjm 	    i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
402f1535dc8Sdjm 		goto again;
403f2c3e964Sjsing 	else if (i <= 0 && !ok)
4045650a0e1Sdjm 		return i;
4055650a0e1Sdjm 
4066f7f653bSjsing 	p = (unsigned char *)s->init_buf->data;
407f1535dc8Sdjm 	msg_len = msg_hdr->msg_len;
4085650a0e1Sdjm 
409f1535dc8Sdjm 	/* reconstruct message header */
41033b95d8bSjsing 	if (!dtls1_write_message_header(msg_hdr, 0, msg_len, p))
41133b95d8bSjsing 		return -1;
4127489cb3dSjsing 
4135650a0e1Sdjm 	msg_len += DTLS1_HM_HEADER_LENGTH;
4145650a0e1Sdjm 
415cef855dcSjsing 	tls1_transcript_record(s, p, msg_len);
4166f7f653bSjsing 	if (s->msg_callback)
4176f7f653bSjsing 		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len,
4186f7f653bSjsing 		    s, s->msg_callback_arg);
4195650a0e1Sdjm 
420b7c5dcbcSjsing 	memset(msg_hdr, 0, sizeof(struct hm_header_st));
4215650a0e1Sdjm 
4229a0dbe41Sdjm 	/* Don't change sequence numbers while listening */
423f19d9718Sjsing 	if (!s->d1->listen)
424f19d9718Sjsing 		s->d1->handshake_read_seq++;
4255650a0e1Sdjm 
4266f7f653bSjsing 	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
427f2c3e964Sjsing 	return 1;
4285650a0e1Sdjm 
429ba06b73eStb  fatal_err:
4305650a0e1Sdjm 	ssl3_send_alert(s, SSL3_AL_FATAL, al);
4315650a0e1Sdjm 	return -1;
4325650a0e1Sdjm }
4335650a0e1Sdjm 
4344a47b859Sjsing static int
dtls1_preprocess_fragment(SSL * s,struct hm_header_st * msg_hdr,int max)435f63b7f2bSjsing dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max)
436f63b7f2bSjsing {
4375650a0e1Sdjm 	size_t frag_off, frag_len, msg_len;
4385650a0e1Sdjm 
4395650a0e1Sdjm 	msg_len = msg_hdr->msg_len;
4405650a0e1Sdjm 	frag_off = msg_hdr->frag_off;
4415650a0e1Sdjm 	frag_len = msg_hdr->frag_len;
4425650a0e1Sdjm 
4435650a0e1Sdjm 	/* sanity checking */
4444a47b859Sjsing 	if ((frag_off + frag_len) > msg_len) {
445c9d7abb7Sbeck 		SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
4465650a0e1Sdjm 		return SSL_AD_ILLEGAL_PARAMETER;
4475650a0e1Sdjm 	}
4485650a0e1Sdjm 
4494a47b859Sjsing 	if ((frag_off + frag_len) > (unsigned long)max) {
450c9d7abb7Sbeck 		SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
4515650a0e1Sdjm 		return SSL_AD_ILLEGAL_PARAMETER;
4525650a0e1Sdjm 	}
4535650a0e1Sdjm 
454f19d9718Sjsing 	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
4555650a0e1Sdjm 	{
456574f5b78Sguenther 		/*
457574f5b78Sguenther 		 * msg_len is limited to 2^24, but is effectively checked
458574f5b78Sguenther 		 * against max above
459574f5b78Sguenther 		 */
4606f7f653bSjsing 		if (!BUF_MEM_grow_clean(s->init_buf,
461f63b7f2bSjsing 		    msg_len + DTLS1_HM_HEADER_LENGTH)) {
462c9d7abb7Sbeck 			SSLerror(s, ERR_R_BUF_LIB);
4635650a0e1Sdjm 			return SSL_AD_INTERNAL_ERROR;
4645650a0e1Sdjm 		}
4655650a0e1Sdjm 
46602876cc3Sjsing 		s->s3->hs.tls12.message_size = msg_len;
467f19d9718Sjsing 		s->d1->r_msg_hdr.msg_len = msg_len;
46802876cc3Sjsing 		s->s3->hs.tls12.message_type = msg_hdr->type;
469f19d9718Sjsing 		s->d1->r_msg_hdr.type = msg_hdr->type;
470f19d9718Sjsing 		s->d1->r_msg_hdr.seq = msg_hdr->seq;
471f19d9718Sjsing 	} else if (msg_len != s->d1->r_msg_hdr.msg_len) {
472574f5b78Sguenther 		/*
473574f5b78Sguenther 		 * They must be playing with us! BTW, failure to enforce
474574f5b78Sguenther 		 * upper limit would open possibility for buffer overrun.
475574f5b78Sguenther 		 */
476c9d7abb7Sbeck 		SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
4775650a0e1Sdjm 		return SSL_AD_ILLEGAL_PARAMETER;
4785650a0e1Sdjm 	}
4795650a0e1Sdjm 
4805650a0e1Sdjm 	return 0; /* no error */
4815650a0e1Sdjm }
4825650a0e1Sdjm 
4835650a0e1Sdjm static int
dtls1_retrieve_buffered_fragment(SSL * s,long max,int * ok)4845650a0e1Sdjm dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
4855650a0e1Sdjm {
486574f5b78Sguenther 	/*
487574f5b78Sguenther 	 * (0) check whether the desired fragment is available
4885650a0e1Sdjm 	 * if so:
4896f7f653bSjsing 	 * (1) copy over the fragment to s->init_buf->data[]
4906f7f653bSjsing 	 * (2) update s->init_num
4915650a0e1Sdjm 	 */
4925650a0e1Sdjm 	pitem *item;
4935650a0e1Sdjm 	hm_fragment *frag;
4945650a0e1Sdjm 	int al;
4955650a0e1Sdjm 
4965650a0e1Sdjm 	*ok = 0;
497f19d9718Sjsing 	item = pqueue_peek(s->d1->buffered_messages);
4985650a0e1Sdjm 	if (item == NULL)
4995650a0e1Sdjm 		return 0;
5005650a0e1Sdjm 
5015650a0e1Sdjm 	frag = (hm_fragment *)item->data;
5025650a0e1Sdjm 
503f1535dc8Sdjm 	/* Don't return if reassembly still in progress */
504f1535dc8Sdjm 	if (frag->reassembly != NULL)
505f1535dc8Sdjm 		return 0;
506f1535dc8Sdjm 
507f19d9718Sjsing 	if (s->d1->handshake_read_seq == frag->msg_header.seq) {
508f1535dc8Sdjm 		unsigned long frag_len = frag->msg_header.frag_len;
509f19d9718Sjsing 		pqueue_pop(s->d1->buffered_messages);
5105650a0e1Sdjm 
5115650a0e1Sdjm 		al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
5125650a0e1Sdjm 
5135650a0e1Sdjm 		if (al == 0) /* no alert */
5145650a0e1Sdjm 		{
5156f7f653bSjsing 			unsigned char *p = (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
5165650a0e1Sdjm 			memcpy(&p[frag->msg_header.frag_off],
5175650a0e1Sdjm 			    frag->fragment, frag->msg_header.frag_len);
5185650a0e1Sdjm 		}
5195650a0e1Sdjm 
5205650a0e1Sdjm 		dtls1_hm_fragment_free(frag);
5215650a0e1Sdjm 		pitem_free(item);
5225650a0e1Sdjm 
5234a47b859Sjsing 		if (al == 0) {
5245650a0e1Sdjm 			*ok = 1;
525f1535dc8Sdjm 			return frag_len;
5265650a0e1Sdjm 		}
5275650a0e1Sdjm 
5285650a0e1Sdjm 		ssl3_send_alert(s, SSL3_AL_FATAL, al);
5296f7f653bSjsing 		s->init_num = 0;
5305650a0e1Sdjm 		*ok = 0;
5315650a0e1Sdjm 		return -1;
5324a47b859Sjsing 	} else
5335650a0e1Sdjm 		return 0;
5345650a0e1Sdjm }
5355650a0e1Sdjm 
5367dac9833Sguenther /*
5377dac9833Sguenther  * dtls1_max_handshake_message_len returns the maximum number of bytes
5387dac9833Sguenther  * permitted in a DTLS handshake message for |s|. The minimum is 16KB,
5397dac9833Sguenther  * but may be greater if the maximum certificate list size requires it.
5407dac9833Sguenther  */
5417dac9833Sguenther static unsigned long
dtls1_max_handshake_message_len(const SSL * s)5427dac9833Sguenther dtls1_max_handshake_message_len(const SSL *s)
5437dac9833Sguenther {
5447dac9833Sguenther 	unsigned long max_len;
5457dac9833Sguenther 
5467dac9833Sguenther 	max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
5476f7f653bSjsing 	if (max_len < (unsigned long)s->max_cert_list)
5486f7f653bSjsing 		return s->max_cert_list;
5497dac9833Sguenther 	return max_len;
5507dac9833Sguenther }
5515650a0e1Sdjm 
5525650a0e1Sdjm static int
dtls1_reassemble_fragment(SSL * s,struct hm_header_st * msg_hdr,int * ok)553f63b7f2bSjsing dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
554f63b7f2bSjsing {
555f1535dc8Sdjm 	hm_fragment *frag = NULL;
556f1535dc8Sdjm 	pitem *item = NULL;
557f1535dc8Sdjm 	int i = -1, is_complete;
558f1535dc8Sdjm 	unsigned char seq64be[8];
5597dac9833Sguenther 	unsigned long frag_len = msg_hdr->frag_len;
560f1535dc8Sdjm 
5617dac9833Sguenther 	if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
5627dac9833Sguenther 	    msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
563f1535dc8Sdjm 		goto err;
564f1535dc8Sdjm 
5651ad69c40Sguenther 	if (frag_len == 0) {
5661ad69c40Sguenther 		i = DTLS1_HM_FRAGMENT_RETRY;
5671ad69c40Sguenther 		goto err;
5681ad69c40Sguenther 	}
5691ad69c40Sguenther 
570f1535dc8Sdjm 	/* Try to find item in queue */
571f1535dc8Sdjm 	memset(seq64be, 0, sizeof(seq64be));
572f1535dc8Sdjm 	seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
573f1535dc8Sdjm 	seq64be[7] = (unsigned char)msg_hdr->seq;
574f19d9718Sjsing 	item = pqueue_find(s->d1->buffered_messages, seq64be);
575f1535dc8Sdjm 
5764a47b859Sjsing 	if (item == NULL) {
577f1535dc8Sdjm 		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
578f1535dc8Sdjm 		if (frag == NULL)
579f1535dc8Sdjm 			goto err;
580f1535dc8Sdjm 		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
581f1535dc8Sdjm 		frag->msg_header.frag_len = frag->msg_header.msg_len;
582f1535dc8Sdjm 		frag->msg_header.frag_off = 0;
58348e47f17Sjsing 	} else {
584f1535dc8Sdjm 		frag = (hm_fragment*)item->data;
58548e47f17Sjsing 		if (frag->msg_header.msg_len != msg_hdr->msg_len) {
58648e47f17Sjsing 			item = NULL;
58748e47f17Sjsing 			frag = NULL;
58848e47f17Sjsing 			goto err;
58948e47f17Sjsing 		}
59048e47f17Sjsing 	}
591f1535dc8Sdjm 
592574f5b78Sguenther 	/*
593574f5b78Sguenther 	 * If message is already reassembled, this must be a
594f1535dc8Sdjm 	 * retransmit and can be dropped.
595f1535dc8Sdjm 	 */
5964a47b859Sjsing 	if (frag->reassembly == NULL) {
597f1535dc8Sdjm 		unsigned char devnull [256];
598f1535dc8Sdjm 
5994a47b859Sjsing 		while (frag_len) {
6006ba40c14Sjsing 			i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
6014a47b859Sjsing 			    devnull, frag_len > sizeof(devnull) ?
6024a47b859Sjsing 			    sizeof(devnull) : frag_len, 0);
6034a47b859Sjsing 			if (i <= 0)
6044a47b859Sjsing 				goto err;
605f1535dc8Sdjm 			frag_len -= i;
606f1535dc8Sdjm 		}
6079e757219Smiod 		i = DTLS1_HM_FRAGMENT_RETRY;
6089e757219Smiod 		goto err;
609f1535dc8Sdjm 	}
610f1535dc8Sdjm 
611f1535dc8Sdjm 	/* read the body of the fragment (header has already been read */
6126ba40c14Sjsing 	i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
613f1535dc8Sdjm 	    frag->fragment + msg_hdr->frag_off, frag_len, 0);
614f1535dc8Sdjm 	if (i <= 0 || (unsigned long)i != frag_len)
615f1535dc8Sdjm 		goto err;
616f1535dc8Sdjm 
617f1535dc8Sdjm 	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
618f1535dc8Sdjm 	    (long)(msg_hdr->frag_off + frag_len));
619f1535dc8Sdjm 
620f1535dc8Sdjm 	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
621f1535dc8Sdjm 	    is_complete);
622f1535dc8Sdjm 
6234a47b859Sjsing 	if (is_complete) {
6246f3a6cb1Sbeck 		free(frag->reassembly);
625f1535dc8Sdjm 		frag->reassembly = NULL;
626f1535dc8Sdjm 	}
627f1535dc8Sdjm 
6284a47b859Sjsing 	if (item == NULL) {
629f1535dc8Sdjm 		memset(seq64be, 0, sizeof(seq64be));
630f1535dc8Sdjm 		seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
631f1535dc8Sdjm 		seq64be[7] = (unsigned char)(msg_hdr->seq);
632f1535dc8Sdjm 
633f1535dc8Sdjm 		item = pitem_new(seq64be, frag);
6344a47b859Sjsing 		if (item == NULL) {
635f1535dc8Sdjm 			i = -1;
636a5ded105Sjsg 			goto err;
637f1535dc8Sdjm 		}
638f1535dc8Sdjm 
639f19d9718Sjsing 		pqueue_insert(s->d1->buffered_messages, item);
640f1535dc8Sdjm 	}
641f1535dc8Sdjm 
642f1535dc8Sdjm 	return DTLS1_HM_FRAGMENT_RETRY;
643f1535dc8Sdjm 
644f1535dc8Sdjm  err:
64506f76ca7Smiod 	if (item == NULL && frag != NULL)
6464a47b859Sjsing 		dtls1_hm_fragment_free(frag);
647f1535dc8Sdjm 	*ok = 0;
648f1535dc8Sdjm 	return i;
649f1535dc8Sdjm }
650f1535dc8Sdjm 
651f1535dc8Sdjm 
652f1535dc8Sdjm static int
dtls1_process_out_of_seq_message(SSL * s,struct hm_header_st * msg_hdr,int * ok)653f63b7f2bSjsing dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
654f63b7f2bSjsing {
6555650a0e1Sdjm 	int i = -1;
6565650a0e1Sdjm 	hm_fragment *frag = NULL;
6575650a0e1Sdjm 	pitem *item = NULL;
658f1535dc8Sdjm 	unsigned char seq64be[8];
6595650a0e1Sdjm 	unsigned long frag_len = msg_hdr->frag_len;
6605650a0e1Sdjm 
6615650a0e1Sdjm 	if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
6625650a0e1Sdjm 		goto err;
6635650a0e1Sdjm 
664f1535dc8Sdjm 	/* Try to find item in queue, to prevent duplicate entries */
665f1535dc8Sdjm 	memset(seq64be, 0, sizeof(seq64be));
666f1535dc8Sdjm 	seq64be[6] = (unsigned char) (msg_hdr->seq >> 8);
667f1535dc8Sdjm 	seq64be[7] = (unsigned char) msg_hdr->seq;
668f19d9718Sjsing 	item = pqueue_find(s->d1->buffered_messages, seq64be);
669f1535dc8Sdjm 
670574f5b78Sguenther 	/*
671574f5b78Sguenther 	 * If we already have an entry and this one is a fragment,
672f1535dc8Sdjm 	 * don't discard it and rather try to reassemble it.
673f1535dc8Sdjm 	 */
674f1535dc8Sdjm 	if (item != NULL && frag_len < msg_hdr->msg_len)
675f1535dc8Sdjm 		item = NULL;
676f1535dc8Sdjm 
677574f5b78Sguenther 	/*
678574f5b78Sguenther 	 * Discard the message if sequence number was already there, is
679f1535dc8Sdjm 	 * too far in the future, already in the queue or if we received
680f1535dc8Sdjm 	 * a FINISHED before the SERVER_HELLO, which then must be a stale
681f1535dc8Sdjm 	 * retransmit.
682f1535dc8Sdjm 	 */
683f19d9718Sjsing 	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
684f19d9718Sjsing 	    msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
685f19d9718Sjsing 	    (s->d1->handshake_read_seq == 0 &&
686f63b7f2bSjsing 	    msg_hdr->type == SSL3_MT_FINISHED)) {
6875650a0e1Sdjm 		unsigned char devnull [256];
6885650a0e1Sdjm 
6894a47b859Sjsing 		while (frag_len) {
6906ba40c14Sjsing 			i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
6914a47b859Sjsing 			    devnull, frag_len > sizeof(devnull) ?
6924a47b859Sjsing 			    sizeof(devnull) : frag_len, 0);
6934a47b859Sjsing 			if (i <= 0)
6944a47b859Sjsing 				goto err;
6955650a0e1Sdjm 			frag_len -= i;
6965650a0e1Sdjm 		}
6974a47b859Sjsing 	} else {
6981ad69c40Sguenther 		if (frag_len < msg_hdr->msg_len)
699f1535dc8Sdjm 			return dtls1_reassemble_fragment(s, msg_hdr, ok);
7005650a0e1Sdjm 
7017dac9833Sguenther 		if (frag_len > dtls1_max_handshake_message_len(s))
7027dac9833Sguenther 			goto err;
7037dac9833Sguenther 
704f1535dc8Sdjm 		frag = dtls1_hm_fragment_new(frag_len, 0);
7055650a0e1Sdjm 		if (frag == NULL)
7065650a0e1Sdjm 			goto err;
7075650a0e1Sdjm 
7085650a0e1Sdjm 		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
7095650a0e1Sdjm 
7104a47b859Sjsing 		if (frag_len) {
7115650a0e1Sdjm 			/* read the body of the fragment (header has already been read */
7126ba40c14Sjsing 			i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
7135650a0e1Sdjm 			    frag->fragment, frag_len, 0);
7145650a0e1Sdjm 			if (i <= 0 || (unsigned long)i != frag_len)
7155650a0e1Sdjm 				goto err;
7165650a0e1Sdjm 		}
7175650a0e1Sdjm 
718f1535dc8Sdjm 		memset(seq64be, 0, sizeof(seq64be));
719f1535dc8Sdjm 		seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
720f1535dc8Sdjm 		seq64be[7] = (unsigned char)(msg_hdr->seq);
7215650a0e1Sdjm 
722f1535dc8Sdjm 		item = pitem_new(seq64be, frag);
7235650a0e1Sdjm 		if (item == NULL)
7245650a0e1Sdjm 			goto err;
7255650a0e1Sdjm 
726f19d9718Sjsing 		pqueue_insert(s->d1->buffered_messages, item);
727f1535dc8Sdjm 	}
728f1535dc8Sdjm 
7295650a0e1Sdjm 	return DTLS1_HM_FRAGMENT_RETRY;
7305650a0e1Sdjm 
7315650a0e1Sdjm  err:
73206f76ca7Smiod 	if (item == NULL && frag != NULL)
7334a47b859Sjsing 		dtls1_hm_fragment_free(frag);
7345650a0e1Sdjm 	*ok = 0;
7355650a0e1Sdjm 	return i;
7365650a0e1Sdjm }
7375650a0e1Sdjm 
7385650a0e1Sdjm 
7395650a0e1Sdjm static long
dtls1_get_message_fragment(SSL * s,int st1,int stn,long max,int * ok)7405650a0e1Sdjm dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
7415650a0e1Sdjm {
7425650a0e1Sdjm 	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
743f1535dc8Sdjm 	unsigned long len, frag_off, frag_len;
7445650a0e1Sdjm 	struct hm_header_st msg_hdr;
745ab5ddd1bSjsing 	int i, al;
746ab5ddd1bSjsing 	CBS cbs;
7475650a0e1Sdjm 
7481aa2bd19Sjsing  again:
7495650a0e1Sdjm 	/* see if we have the required fragment already */
7504a47b859Sjsing 	if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) {
7514a47b859Sjsing 		if (*ok)
7526f7f653bSjsing 			s->init_num = frag_len;
7535650a0e1Sdjm 		return frag_len;
7545650a0e1Sdjm 	}
7555650a0e1Sdjm 
7565650a0e1Sdjm 	/* read handshake message header */
7576ba40c14Sjsing 	i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire,
7585650a0e1Sdjm 	    DTLS1_HM_HEADER_LENGTH, 0);
759ab5ddd1bSjsing 	if (i <= 0) {
760ab5ddd1bSjsing 	 	/* nbio, or an error */
7616f7f653bSjsing 		s->rwstate = SSL_READING;
7625650a0e1Sdjm 		*ok = 0;
7635650a0e1Sdjm 		return i;
7645650a0e1Sdjm 	}
765ab5ddd1bSjsing 
766ab5ddd1bSjsing 	CBS_init(&cbs, wire, i);
767ab5ddd1bSjsing 	if (!dtls1_get_message_header(&cbs, &msg_hdr)) {
768ab5ddd1bSjsing 		/* Handshake fails if message header is incomplete. */
769bad7092fSdjm 		al = SSL_AD_UNEXPECTED_MESSAGE;
770c9d7abb7Sbeck 		SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
771ba06b73eStb 		goto fatal_err;
772bad7092fSdjm 	}
7735650a0e1Sdjm 
7745650a0e1Sdjm 	/*
7755650a0e1Sdjm 	 * if this is a future (or stale) message it gets buffered
7765650a0e1Sdjm 	 * (or dropped)--no further processing at this time
7779a0dbe41Sdjm 	 * While listening, we accept seq 1 (ClientHello with cookie)
7789a0dbe41Sdjm 	 * although we're still expecting seq 0 (ClientHello)
7795650a0e1Sdjm 	 */
780f19d9718Sjsing 	if (msg_hdr.seq != s->d1->handshake_read_seq &&
781f19d9718Sjsing 	    !(s->d1->listen && msg_hdr.seq == 1))
7825650a0e1Sdjm 		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
7835650a0e1Sdjm 
784f1535dc8Sdjm 	len = msg_hdr.msg_len;
7855650a0e1Sdjm 	frag_off = msg_hdr.frag_off;
7865650a0e1Sdjm 	frag_len = msg_hdr.frag_len;
7875650a0e1Sdjm 
788f1535dc8Sdjm 	if (frag_len && frag_len < len)
789f1535dc8Sdjm 		return dtls1_reassemble_fragment(s, &msg_hdr, ok);
790f1535dc8Sdjm 
791f19d9718Sjsing 	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
7924a47b859Sjsing 	    wire[0] == SSL3_MT_HELLO_REQUEST) {
793574f5b78Sguenther 		/*
794574f5b78Sguenther 		 * The server may always send 'Hello Request' messages --
7955650a0e1Sdjm 		 * we are doing a handshake anyway now, so ignore them
7965650a0e1Sdjm 		 * if their format is correct. Does not count for
797574f5b78Sguenther 		 * 'Finished' MAC.
798574f5b78Sguenther 		 */
7994a47b859Sjsing 		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
8006f7f653bSjsing 			if (s->msg_callback)
8016f7f653bSjsing 				s->msg_callback(0, s->version,
8024a47b859Sjsing 				    SSL3_RT_HANDSHAKE, wire,
8034a47b859Sjsing 				    DTLS1_HM_HEADER_LENGTH, s,
8046f7f653bSjsing 				    s->msg_callback_arg);
8055650a0e1Sdjm 
8066f7f653bSjsing 			s->init_num = 0;
8071aa2bd19Sjsing 			goto again;
8085650a0e1Sdjm 		}
809*40ca958bSjmc 		else /* Incorrectly formatted Hello request */
8105650a0e1Sdjm 		{
8115650a0e1Sdjm 			al = SSL_AD_UNEXPECTED_MESSAGE;
812c9d7abb7Sbeck 			SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
813ba06b73eStb 			goto fatal_err;
8145650a0e1Sdjm 		}
8155650a0e1Sdjm 	}
8165650a0e1Sdjm 
8175650a0e1Sdjm 	if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
818ba06b73eStb 		goto fatal_err;
8195650a0e1Sdjm 
820*40ca958bSjmc 	/* XDTLS:  resurrect this when restart is in place */
82102876cc3Sjsing 	s->s3->hs.state = stn;
8225650a0e1Sdjm 
8234a47b859Sjsing 	if (frag_len > 0) {
8246f7f653bSjsing 		unsigned char *p = (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
8255650a0e1Sdjm 
8266ba40c14Sjsing 		i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
8275650a0e1Sdjm 		    &p[frag_off], frag_len, 0);
8285650a0e1Sdjm 		/* XDTLS:  fix this--message fragments cannot span multiple packets */
8294a47b859Sjsing 		if (i <= 0) {
8306f7f653bSjsing 			s->rwstate = SSL_READING;
8315650a0e1Sdjm 			*ok = 0;
8325650a0e1Sdjm 			return i;
8335650a0e1Sdjm 		}
8344a47b859Sjsing 	} else
8355650a0e1Sdjm 		i = 0;
8365650a0e1Sdjm 
837574f5b78Sguenther 	/*
838574f5b78Sguenther 	 * XDTLS:  an incorrectly formatted fragment should cause the
839574f5b78Sguenther 	 * handshake to fail
840574f5b78Sguenther 	 */
8414a47b859Sjsing 	if (i != (int)frag_len) {
8426650b941Sjsing 		al = SSL_AD_ILLEGAL_PARAMETER;
843db8264deSjsing 		SSLerror(s, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER);
844ba06b73eStb 		goto fatal_err;
845bad7092fSdjm 	}
8465650a0e1Sdjm 
847574f5b78Sguenther 	/*
8486f7f653bSjsing 	 * Note that s->init_num is *not* used as current offset in
8496f7f653bSjsing 	 * s->init_buf->data, but as a counter summing up fragments'
8505650a0e1Sdjm 	 * lengths: as soon as they sum up to handshake packet
851574f5b78Sguenther 	 * length, we assume we have got all the fragments.
852574f5b78Sguenther 	 */
8536f7f653bSjsing 	s->init_num = frag_len;
854f2c3e964Sjsing 	*ok = 1;
8555650a0e1Sdjm 	return frag_len;
8565650a0e1Sdjm 
857ba06b73eStb  fatal_err:
8585650a0e1Sdjm 	ssl3_send_alert(s, SSL3_AL_FATAL, al);
8596f7f653bSjsing 	s->init_num = 0;
8605650a0e1Sdjm 
8615650a0e1Sdjm 	*ok = 0;
8625650a0e1Sdjm 	return (-1);
8635650a0e1Sdjm }
8645650a0e1Sdjm 
8654a47b859Sjsing int
dtls1_read_failed(SSL * s,int code)8664a47b859Sjsing dtls1_read_failed(SSL *s, int code)
8675650a0e1Sdjm {
8684a47b859Sjsing 	if (code > 0) {
86912a88955Sbeck #ifdef DEBUG
870f63b7f2bSjsing 		fprintf(stderr, "invalid state reached %s:%d",
871f63b7f2bSjsing 		    __FILE__, __LINE__);
87212a88955Sbeck #endif
8735650a0e1Sdjm 		return 1;
8745650a0e1Sdjm 	}
8755650a0e1Sdjm 
8764a47b859Sjsing 	if (!dtls1_is_timer_expired(s)) {
877574f5b78Sguenther 		/*
878574f5b78Sguenther 		 * not a timeout, none of our business, let higher layers
879574f5b78Sguenther 		 * handle this.  in fact it's probably an error
880574f5b78Sguenther 		 */
8815650a0e1Sdjm 		return code;
8825650a0e1Sdjm 	}
8835650a0e1Sdjm 
8845650a0e1Sdjm 	if (!SSL_in_init(s))  /* done, no need to send a retransmit */
8855650a0e1Sdjm 	{
8865650a0e1Sdjm 		BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
8875650a0e1Sdjm 		return code;
8885650a0e1Sdjm 	}
8895650a0e1Sdjm 
890f1535dc8Sdjm 	return dtls1_handle_timeout(s);
8915650a0e1Sdjm }
8925650a0e1Sdjm 
893f1535dc8Sdjm int
dtls1_get_queue_priority(unsigned short seq,int is_ccs)894f1535dc8Sdjm dtls1_get_queue_priority(unsigned short seq, int is_ccs)
895f1535dc8Sdjm {
896574f5b78Sguenther 	/*
897574f5b78Sguenther 	 * The index of the retransmission queue actually is the message
898574f5b78Sguenther 	 * sequence number, since the queue only contains messages of a
899574f5b78Sguenther 	 * single handshake. However, the ChangeCipherSpec has no message
900574f5b78Sguenther 	 * sequence number and so using only the sequence will result in
901574f5b78Sguenther 	 * the CCS and Finished having the same index. To prevent this, the
902574f5b78Sguenther 	 * sequence number is multiplied by 2. In case of a CCS 1 is
903574f5b78Sguenther 	 * subtracted.  This does not only differ CSS and Finished, it also
904574f5b78Sguenther 	 * maintains the order of the index (important for priority queues)
905574f5b78Sguenther 	 * and fits in the unsigned short variable.
906f1535dc8Sdjm 	 */
907f1535dc8Sdjm 	return seq * 2 - is_ccs;
908f1535dc8Sdjm }
9095650a0e1Sdjm 
910f1535dc8Sdjm int
dtls1_retransmit_buffered_messages(SSL * s)9115650a0e1Sdjm dtls1_retransmit_buffered_messages(SSL *s)
9125650a0e1Sdjm {
9135650a0e1Sdjm 	pqueue sent = s->d1->sent_messages;
9145650a0e1Sdjm 	piterator iter;
9155650a0e1Sdjm 	pitem *item;
9165650a0e1Sdjm 	hm_fragment *frag;
9175650a0e1Sdjm 	int found = 0;
9185650a0e1Sdjm 
9195650a0e1Sdjm 	iter = pqueue_iterator(sent);
9205650a0e1Sdjm 
921f63b7f2bSjsing 	for (item = pqueue_next(&iter); item != NULL;
922f63b7f2bSjsing 	    item = pqueue_next(&iter)) {
9235650a0e1Sdjm 		frag = (hm_fragment *)item->data;
924f1535dc8Sdjm 		if (dtls1_retransmit_message(s,
9254a47b859Sjsing 		    (unsigned short)dtls1_get_queue_priority(
9264a47b859Sjsing 		    frag->msg_header.seq, frag->msg_header.is_ccs), 0,
9274a47b859Sjsing 		    &found) <= 0 && found) {
92812a88955Sbeck #ifdef DEBUG
9295650a0e1Sdjm 			fprintf(stderr, "dtls1_retransmit_message() failed\n");
93012a88955Sbeck #endif
9315650a0e1Sdjm 			return -1;
9325650a0e1Sdjm 		}
9335650a0e1Sdjm 	}
9345650a0e1Sdjm 
9355650a0e1Sdjm 	return 1;
9365650a0e1Sdjm }
9375650a0e1Sdjm 
9385650a0e1Sdjm int
dtls1_buffer_message(SSL * s,int is_ccs)9395650a0e1Sdjm dtls1_buffer_message(SSL *s, int is_ccs)
9405650a0e1Sdjm {
9415650a0e1Sdjm 	pitem *item;
9425650a0e1Sdjm 	hm_fragment *frag;
943f1535dc8Sdjm 	unsigned char seq64be[8];
9445650a0e1Sdjm 
945*40ca958bSjmc 	/* Buffer the message in order to handle DTLS retransmissions. */
9460d55d512Sjsing 
947574f5b78Sguenther 	/*
948574f5b78Sguenther 	 * This function is called immediately after a message has
949574f5b78Sguenther 	 * been serialized
950574f5b78Sguenther 	 */
9516f7f653bSjsing 	OPENSSL_assert(s->init_off == 0);
9525650a0e1Sdjm 
9536f7f653bSjsing 	frag = dtls1_hm_fragment_new(s->init_num, 0);
9545071407dSjsing 	if (frag == NULL)
9555071407dSjsing 		return 0;
9565650a0e1Sdjm 
9576f7f653bSjsing 	memcpy(frag->fragment, s->init_buf->data, s->init_num);
9585650a0e1Sdjm 
959f19d9718Sjsing 	OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
960d25254fbSjsing 	    (is_ccs ? DTLS1_CCS_HEADER_LENGTH : DTLS1_HM_HEADER_LENGTH) ==
9616f7f653bSjsing 	    (unsigned int)s->init_num);
9625650a0e1Sdjm 
963f19d9718Sjsing 	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
964f19d9718Sjsing 	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
965f19d9718Sjsing 	frag->msg_header.type = s->d1->w_msg_hdr.type;
9665650a0e1Sdjm 	frag->msg_header.frag_off = 0;
967f19d9718Sjsing 	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
9685650a0e1Sdjm 	frag->msg_header.is_ccs = is_ccs;
9695650a0e1Sdjm 
970f1535dc8Sdjm 	/* save current state*/
971f1535dc8Sdjm 	frag->msg_header.saved_retransmit_state.session = s->session;
9722f4e7cfaSjsing 	frag->msg_header.saved_retransmit_state.epoch =
9736f7f653bSjsing 	    tls12_record_layer_write_epoch(s->rl);
9745650a0e1Sdjm 
975f1535dc8Sdjm 	memset(seq64be, 0, sizeof(seq64be));
976f63b7f2bSjsing 	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(
977f63b7f2bSjsing 	    frag->msg_header.seq, frag->msg_header.is_ccs) >> 8);
978f63b7f2bSjsing 	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(
979f63b7f2bSjsing 	    frag->msg_header.seq, frag->msg_header.is_ccs));
980f1535dc8Sdjm 
981f1535dc8Sdjm 	item = pitem_new(seq64be, frag);
9824a47b859Sjsing 	if (item == NULL) {
9835650a0e1Sdjm 		dtls1_hm_fragment_free(frag);
9845650a0e1Sdjm 		return 0;
9855650a0e1Sdjm 	}
9865650a0e1Sdjm 
9875650a0e1Sdjm 	pqueue_insert(s->d1->sent_messages, item);
9885650a0e1Sdjm 	return 1;
9895650a0e1Sdjm }
9905650a0e1Sdjm 
9915650a0e1Sdjm int
dtls1_retransmit_message(SSL * s,unsigned short seq,unsigned long frag_off,int * found)9925650a0e1Sdjm dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
9935650a0e1Sdjm     int *found)
9945650a0e1Sdjm {
9955650a0e1Sdjm 	int ret;
9965650a0e1Sdjm 	/* XDTLS: for now assuming that read/writes are blocking */
9975650a0e1Sdjm 	pitem *item;
9985650a0e1Sdjm 	hm_fragment *frag;
9995650a0e1Sdjm 	unsigned long header_length;
1000f1535dc8Sdjm 	unsigned char seq64be[8];
1001f1535dc8Sdjm 	struct dtls1_retransmit_state saved_state;
10025650a0e1Sdjm 
10035650a0e1Sdjm 	/*
10046f7f653bSjsing 	  OPENSSL_assert(s->init_num == 0);
10056f7f653bSjsing 	  OPENSSL_assert(s->init_off == 0);
10065650a0e1Sdjm 	 */
10075650a0e1Sdjm 
10085650a0e1Sdjm 	/* XDTLS:  the requested message ought to be found, otherwise error */
1009f1535dc8Sdjm 	memset(seq64be, 0, sizeof(seq64be));
1010f1535dc8Sdjm 	seq64be[6] = (unsigned char)(seq >> 8);
1011f1535dc8Sdjm 	seq64be[7] = (unsigned char)seq;
10125650a0e1Sdjm 
1013f1535dc8Sdjm 	item = pqueue_find(s->d1->sent_messages, seq64be);
10144a47b859Sjsing 	if (item == NULL) {
101512a88955Sbeck #ifdef DEBUG
10166ba149ccSphessler 		fprintf(stderr, "retransmit:  message %d non-existent\n", seq);
101712a88955Sbeck #endif
10185650a0e1Sdjm 		*found = 0;
10195650a0e1Sdjm 		return 0;
10205650a0e1Sdjm 	}
10215650a0e1Sdjm 
10225650a0e1Sdjm 	*found = 1;
10235650a0e1Sdjm 	frag = (hm_fragment *)item->data;
10245650a0e1Sdjm 
10255650a0e1Sdjm 	if (frag->msg_header.is_ccs)
10265650a0e1Sdjm 		header_length = DTLS1_CCS_HEADER_LENGTH;
10275650a0e1Sdjm 	else
10285650a0e1Sdjm 		header_length = DTLS1_HM_HEADER_LENGTH;
10295650a0e1Sdjm 
10306f7f653bSjsing 	memcpy(s->init_buf->data, frag->fragment,
10315650a0e1Sdjm 	    frag->msg_header.msg_len + header_length);
10326f7f653bSjsing 	s->init_num = frag->msg_header.msg_len + header_length;
10335650a0e1Sdjm 
10345650a0e1Sdjm 	dtls1_set_message_header_int(s, frag->msg_header.type,
10355650a0e1Sdjm 	    frag->msg_header.msg_len, frag->msg_header.seq, 0,
10365650a0e1Sdjm 	    frag->msg_header.frag_len);
10375650a0e1Sdjm 
1038f1535dc8Sdjm 	/* save current state */
1039f1535dc8Sdjm 	saved_state.session = s->session;
10406f7f653bSjsing 	saved_state.epoch = tls12_record_layer_write_epoch(s->rl);
1041f1535dc8Sdjm 
1042f19d9718Sjsing 	s->d1->retransmitting = 1;
1043f1535dc8Sdjm 
1044f1535dc8Sdjm 	/* restore state in which the message was originally sent */
1045f1535dc8Sdjm 	s->session = frag->msg_header.saved_retransmit_state.session;
10466f7f653bSjsing 	if (!tls12_record_layer_use_write_epoch(s->rl,
10472f4e7cfaSjsing 	    frag->msg_header.saved_retransmit_state.epoch))
10488ae961d9Sjsing 		return 0;
1049f1535dc8Sdjm 
10505650a0e1Sdjm 	ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
10515650a0e1Sdjm 	    SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
1052f1535dc8Sdjm 
1053f1535dc8Sdjm 	/* restore current state */
1054f1535dc8Sdjm 	s->session = saved_state.session;
10556f7f653bSjsing 	if (!tls12_record_layer_use_write_epoch(s->rl,
10562f4e7cfaSjsing 	    saved_state.epoch))
10578ae961d9Sjsing 		return 0;
1058f1535dc8Sdjm 
1059f19d9718Sjsing 	s->d1->retransmitting = 0;
10605650a0e1Sdjm 
10615650a0e1Sdjm 	(void)BIO_flush(SSL_get_wbio(s));
10625650a0e1Sdjm 	return ret;
10635650a0e1Sdjm }
10645650a0e1Sdjm 
10655650a0e1Sdjm /* call this function when the buffered messages are no longer needed */
10665650a0e1Sdjm void
dtls1_clear_record_buffer(SSL * s)10675650a0e1Sdjm dtls1_clear_record_buffer(SSL *s)
10685650a0e1Sdjm {
10692935b8f4Sjsing 	hm_fragment *frag;
10705650a0e1Sdjm 	pitem *item;
10715650a0e1Sdjm 
10724a47b859Sjsing 	for(item = pqueue_pop(s->d1->sent_messages); item != NULL;
10734a47b859Sjsing 	    item = pqueue_pop(s->d1->sent_messages)) {
10742935b8f4Sjsing 		frag = item->data;
10752935b8f4Sjsing 		if (frag->msg_header.is_ccs)
10766f7f653bSjsing 			tls12_record_layer_write_epoch_done(s->rl,
10772935b8f4Sjsing 			    frag->msg_header.saved_retransmit_state.epoch);
10782935b8f4Sjsing 		dtls1_hm_fragment_free(frag);
10795650a0e1Sdjm 		pitem_free(item);
10805650a0e1Sdjm 	}
10815650a0e1Sdjm }
10825650a0e1Sdjm 
1083d08ef415Sjsing void
dtls1_set_message_header(SSL * s,unsigned char mt,unsigned long len,unsigned long frag_off,unsigned long frag_len)1084d08ef415Sjsing dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len,
1085d08ef415Sjsing     unsigned long frag_off, unsigned long frag_len)
10865650a0e1Sdjm {
10879a0dbe41Sdjm 	/* Don't change sequence numbers while listening */
1088f19d9718Sjsing 	if (frag_off == 0 && !s->d1->listen) {
1089f19d9718Sjsing 		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
1090f19d9718Sjsing 		s->d1->next_handshake_write_seq++;
10915650a0e1Sdjm 	}
10925650a0e1Sdjm 
1093f19d9718Sjsing 	dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
10945650a0e1Sdjm 	    frag_off, frag_len);
10955650a0e1Sdjm }
10965650a0e1Sdjm 
10975650a0e1Sdjm /* don't actually do the writing, wait till the MTU has been retrieved */
1098ab211f3dSjsing void
dtls1_set_message_header_int(SSL * s,unsigned char mt,unsigned long len,unsigned short seq_num,unsigned long frag_off,unsigned long frag_len)1099f63b7f2bSjsing dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len,
1100f63b7f2bSjsing     unsigned short seq_num, unsigned long frag_off, unsigned long frag_len)
11015650a0e1Sdjm {
1102f19d9718Sjsing 	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
11035650a0e1Sdjm 
11045650a0e1Sdjm 	msg_hdr->type = mt;
11055650a0e1Sdjm 	msg_hdr->msg_len = len;
11065650a0e1Sdjm 	msg_hdr->seq = seq_num;
11075650a0e1Sdjm 	msg_hdr->frag_off = frag_off;
11085650a0e1Sdjm 	msg_hdr->frag_len = frag_len;
11095650a0e1Sdjm }
11105650a0e1Sdjm 
11115650a0e1Sdjm static void
dtls1_fix_message_header(SSL * s,unsigned long frag_off,unsigned long frag_len)1112f63b7f2bSjsing dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len)
11135650a0e1Sdjm {
1114f19d9718Sjsing 	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
11155650a0e1Sdjm 
11165650a0e1Sdjm 	msg_hdr->frag_off = frag_off;
11175650a0e1Sdjm 	msg_hdr->frag_len = frag_len;
11185650a0e1Sdjm }
11195650a0e1Sdjm 
112033b95d8bSjsing static int
dtls1_write_message_header(const struct hm_header_st * msg_hdr,unsigned long frag_off,unsigned long frag_len,unsigned char * p)112133b95d8bSjsing dtls1_write_message_header(const struct hm_header_st *msg_hdr,
112233b95d8bSjsing     unsigned long frag_off, unsigned long frag_len, unsigned char *p)
11235650a0e1Sdjm {
112433b95d8bSjsing 	CBB cbb;
11255650a0e1Sdjm 
112633b95d8bSjsing 	/* We assume DTLS1_HM_HEADER_LENGTH bytes are available for now... */
112733b95d8bSjsing 	if (!CBB_init_fixed(&cbb, p, DTLS1_HM_HEADER_LENGTH))
112833b95d8bSjsing 		return 0;
112933b95d8bSjsing 	if (!CBB_add_u8(&cbb, msg_hdr->type))
113033b95d8bSjsing 		goto err;
113133b95d8bSjsing 	if (!CBB_add_u24(&cbb, msg_hdr->msg_len))
113233b95d8bSjsing 		goto err;
113333b95d8bSjsing 	if (!CBB_add_u16(&cbb, msg_hdr->seq))
113433b95d8bSjsing 		goto err;
113533b95d8bSjsing 	if (!CBB_add_u24(&cbb, frag_off))
113633b95d8bSjsing 		goto err;
113733b95d8bSjsing 	if (!CBB_add_u24(&cbb, frag_len))
113833b95d8bSjsing 		goto err;
113933b95d8bSjsing 	if (!CBB_finish(&cbb, NULL, NULL))
114033b95d8bSjsing 		goto err;
11415650a0e1Sdjm 
114233b95d8bSjsing 	return 1;
11435650a0e1Sdjm 
114433b95d8bSjsing  err:
114533b95d8bSjsing 	CBB_cleanup(&cbb);
114633b95d8bSjsing 	return 0;
11475650a0e1Sdjm }
11485650a0e1Sdjm 
1149bad7092fSdjm unsigned int
dtls1_min_mtu(void)11505650a0e1Sdjm dtls1_min_mtu(void)
11515650a0e1Sdjm {
11525650a0e1Sdjm 	return (g_probable_mtu[(sizeof(g_probable_mtu) /
11535650a0e1Sdjm 	    sizeof(g_probable_mtu[0])) - 1]);
11545650a0e1Sdjm }
11555650a0e1Sdjm 
11565650a0e1Sdjm static unsigned int
dtls1_guess_mtu(unsigned int curr_mtu)11575650a0e1Sdjm dtls1_guess_mtu(unsigned int curr_mtu)
11585650a0e1Sdjm {
1159f1535dc8Sdjm 	unsigned int i;
11605650a0e1Sdjm 
11615650a0e1Sdjm 	if (curr_mtu == 0)
11625650a0e1Sdjm 		return g_probable_mtu[0];
11635650a0e1Sdjm 
11645650a0e1Sdjm 	for (i = 0; i < sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0]); i++)
11655650a0e1Sdjm 		if (curr_mtu > g_probable_mtu[i])
11665650a0e1Sdjm 			return g_probable_mtu[i];
11675650a0e1Sdjm 
11685650a0e1Sdjm 	return curr_mtu;
11695650a0e1Sdjm }
11705650a0e1Sdjm 
11714fd32991Sdoug int
dtls1_get_message_header(CBS * header,struct hm_header_st * msg_hdr)1172ab5ddd1bSjsing dtls1_get_message_header(CBS *header, struct hm_header_st *msg_hdr)
1173f63b7f2bSjsing {
11744fd32991Sdoug 	uint32_t msg_len, frag_off, frag_len;
11754fd32991Sdoug 	uint16_t seq;
11764fd32991Sdoug 	uint8_t type;
11775650a0e1Sdjm 
11784fd32991Sdoug 	memset(msg_hdr, 0, sizeof(*msg_hdr));
11794fd32991Sdoug 
1180ab5ddd1bSjsing 	if (!CBS_get_u8(header, &type))
11814fd32991Sdoug 		return 0;
1182ab5ddd1bSjsing 	if (!CBS_get_u24(header, &msg_len))
11834fd32991Sdoug 		return 0;
1184ab5ddd1bSjsing 	if (!CBS_get_u16(header, &seq))
11854fd32991Sdoug 		return 0;
1186ab5ddd1bSjsing 	if (!CBS_get_u24(header, &frag_off))
11874fd32991Sdoug 		return 0;
1188ab5ddd1bSjsing 	if (!CBS_get_u24(header, &frag_len))
11894fd32991Sdoug 		return 0;
11904fd32991Sdoug 
11914fd32991Sdoug 	msg_hdr->type = type;
11924fd32991Sdoug 	msg_hdr->msg_len = msg_len;
11934fd32991Sdoug 	msg_hdr->seq = seq;
11944fd32991Sdoug 	msg_hdr->frag_off = frag_off;
11954fd32991Sdoug 	msg_hdr->frag_len = frag_len;
11964fd32991Sdoug 
11974fd32991Sdoug 	return 1;
11985650a0e1Sdjm }
1199