195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/*
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DTLS implementation written by Nagendra Modadugu
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ====================================================================
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the documentation and/or other materials provided with the
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    distribution.
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    software must display the following acknowledgment:
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    endorse or promote products derived from this software without
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    prior written permission. For written permission, please contact
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    openssl-core@openssl.org.
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL"
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    nor may "OpenSSL" appear in their names without prior written
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    permission of the OpenSSL Project.
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    acknowledgment:
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ====================================================================
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com).
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com).
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL.
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to.  The following conditions
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA,
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed.
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used.
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package.
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    must display the following acknowledgement:
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes cryptographic software written by
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *     Eric Young (eay@cryptsoft.com)"
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    The word 'cryptographic' can be left out if the rouines from the library
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    being used are not cryptographic related :-).
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the apps directory (application code) you must include an acknowledgement:
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE.
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] */
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <assert.h>
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <limits.h>
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <stdio.h>
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <string.h>
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/buf.h>
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h>
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/evp.h>
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/obj.h>
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/rand.h>
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/x509.h>
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "ssl_locl.h"
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((end) - (start) <= 8) { \
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				long ii; \
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			} else { \
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				long ii; \
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			} }
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			long ii; \
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			assert((msg_len) > 0); \
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			is_complete = 1; \
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			long ii; \
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			printf("\n"); }
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
158cff6472442de2e65f95fa04893b12b1412118f60David Benjaminstatic const uint8_t bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
159cff6472442de2e65f95fa04893b12b1412118f60David Benjaminstatic const uint8_t bitmask_end_values[]   = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* XDTLS:  figure out the right values */
162cff6472442de2e65f95fa04893b12b1412118f60David Benjaminstatic const unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long frag_len);
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic unsigned char *dtls1_write_message_header(SSL *s,
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *p);
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void dtls1_set_message_header_int(SSL *s, unsigned char mt,
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long len, unsigned short seq_num, unsigned long frag_off,
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long frag_len);
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic long dtls1_get_message_fragment(SSL *s, int stn,
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long max, int *ok);
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic hm_fragment *
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag = NULL;
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *buf = NULL;
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *bitmask = NULL;
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( frag == NULL)
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return NULL;
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag_len)
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf = (unsigned char *)OPENSSL_malloc(frag_len);
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( buf == NULL)
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_free(frag);
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return NULL;
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* zero length fragment gets zero frag->fragment */
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->fragment = buf;
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Initialize reassembly bitmask if necessary */
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (reassembly)
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (bitmask == NULL)
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (buf != NULL) OPENSSL_free(buf);
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_free(frag);
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return NULL;
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->reassembly = bitmask;
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return frag;
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_hm_fragment_free(hm_fragment *frag)
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->msg_header.is_ccs)
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		EVP_CIPHER_CTX_free(frag->msg_header.saved_retransmit_state.enc_write_ctx);
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		EVP_MD_CTX_destroy(frag->msg_header.saved_retransmit_state.write_hash);
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->fragment) OPENSSL_free(frag->fragment);
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->reassembly) OPENSSL_free(frag->reassembly);
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_free(frag);
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint dtls1_do_write(SSL *s, int type)
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int curr_mtu;
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned int len, frag_off, mac_size, blocksize;
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* AHA!  Figure out the MTU, and stick to the right size */
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->mtu =
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* I've seen the kernel return bogus numbers when it doesn't know
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * (initial write), so just make sure we have a reasonable number */
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (s->d1->mtu < dtls1_min_mtu())
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->d1->mtu = 0;
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->d1->mtu, NULL);
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	mtu = s->d1->mtu;
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	fprintf(stderr, "using MTU = %d\n", mtu);
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s));
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( curr_mtu > 0)
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		mtu = curr_mtu;
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ret;
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = BIO_flush(SSL_get_wbio(s));
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( ret <= 0)
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return ret;
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	assert(s->d1->mtu >= dtls1_min_mtu());  /* should have something reasonable now */
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( s->init_off == 0  && type == SSL3_RT_HANDSHAKE)
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		assert(s->init_num ==
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->write_hash)
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (s->enc_write_ctx && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE)
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			mac_size = 0;
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			mac_size = EVP_MD_CTX_size(s->write_hash);
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		mac_size = 0;
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->enc_write_ctx &&
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		(EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		blocksize = 0;
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag_off = 0;
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	while( s->init_num)
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			DTLS1_RT_HEADER_LENGTH - mac_size - blocksize;
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* grr.. we could get an error if MTU picked was wrong */
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = BIO_flush(SSL_get_wbio(s));
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ( ret <= 0)
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return ret;
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH -
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				mac_size - blocksize;
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( s->init_num > curr_mtu)
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len = curr_mtu;
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len = s->init_num;
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* XDTLS: this function is too long.  split out the CCS part */
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( type == SSL3_RT_HANDSHAKE)
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ( s->init_off != 0)
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->init_off -= DTLS1_HM_HEADER_LENGTH;
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->init_num += DTLS1_HM_HEADER_LENGTH;
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				if ( s->init_num > curr_mtu)
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					len = curr_mtu;
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				else
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					len = s->init_num;
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			dtls1_fix_message_header(s, frag_off,
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				len - DTLS1_HM_HEADER_LENGTH);
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			assert(len >= DTLS1_HM_HEADER_LENGTH);
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len);
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ret < 0)
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* might need to update MTU here, but we don't know
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * which previous packet caused the failure -- so can't
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * really retransmit anything.  continue as if everything
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * is fine and wait for an alert to handle the
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * retransmit
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ( BIO_ctrl(SSL_get_wbio(s),
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 )
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return(-1);
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* bad if this assert fails, only part of the handshake
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * message got sent.  but why would this happen? */
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			assert(len == (unsigned int)ret);
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				/* should not be done for 'Hello Request's, but in that case
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				 * we'll ignore the result anyway */
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				int xlen;
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
376cc23df53da503b6095d4c8d0dd5207e90ebf4580David Benjamin				if (frag_off == 0)
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					{
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					/* reconstruct message header is if it
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					 * is being sent in single fragment */
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					*p++ = msg_hdr->type;
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					l2n3(msg_hdr->msg_len,p);
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					s2n (msg_hdr->seq,p);
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					l2n3(0,p);
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					l2n3(msg_hdr->msg_len,p);
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					p  -= DTLS1_HM_HEADER_LENGTH;
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					xlen = ret;
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					}
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				else
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					{
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					p  += DTLS1_HM_HEADER_LENGTH;
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					xlen = ret - DTLS1_HM_HEADER_LENGTH;
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					}
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ssl3_finish_mac(s, p, xlen);
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (ret == s->init_num)
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				if (s->msg_callback)
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					s->msg_callback(1, s->version, type, s->init_buf->data,
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						(size_t)(s->init_off + s->init_num), s,
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						s->msg_callback_arg);
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->init_off = 0;  /* done writing this message */
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->init_num = 0;
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return(1);
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->init_off+=ret;
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->init_num-=ret;
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return(0);
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Obtain handshake message of message type 'mt' (any if mt == -1),
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * maximum acceptable body length 'max'.
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Read an entire handshake message.  Handshake messages arrive in
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * fragments.
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
423590cbe970c75973f38aeba4b7146dc0b84b66348David Benjaminlong dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok)
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i, al;
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct hm_header_st *msg_hdr;
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *p;
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long msg_len;
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* s3->tmp is used to store messages that are unexpected, caused
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * by the absence of an optional handshake message */
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->s3->tmp.reuse_message)
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
434590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin		/* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
435590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin		 * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
436590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin		 * would have to have been applied to the previous call. */
437590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin		assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->s3->tmp.reuse_message=0;
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			al=SSL_AD_UNEXPECTED_MESSAGE;
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(SSL, dtls1_get_message, SSL_R_UNEXPECTED_MESSAGE);
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto f_err;
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*ok=1;
44651b1f7427b6e153675ae4bcb75f3f5a6b44648f4David Benjamin		s->init_msg = (uint8_t*)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->init_num = (int)s->s3->tmp.message_size;
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return s->init_num;
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr = &s->d1->r_msg_hdr;
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
45395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyagain:
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	i = dtls1_get_message_fragment(s, stn, max, ok);
45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( i == DTLS1_HM_BAD_FRAGMENT ||
45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto again;
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if ( i <= 0 && !*ok)
46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i;
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = (unsigned char *)s->init_buf->data;
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_len = msg_hdr->msg_len;
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* reconstruct message header */
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*(p++) = msg_hdr->type;
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(msg_len,p);
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s2n (msg_hdr->seq,p);
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(0,p);
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(msg_len,p);
471cc23df53da503b6095d4c8d0dd5207e90ebf4580David Benjamin	p       -= DTLS1_HM_HEADER_LENGTH;
472cc23df53da503b6095d4c8d0dd5207e90ebf4580David Benjamin	msg_len += DTLS1_HM_HEADER_LENGTH;
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
474590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin	s->init_msg = (uint8_t*)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
475590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin
476590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin	if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE)
477590cbe970c75973f38aeba4b7146dc0b84b66348David Benjamin		ssl3_hash_current_message(s);
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->msg_callback)
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			p, msg_len,
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s, s->msg_callback_arg);
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Don't change sequence numbers while listening */
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!s->d1->listen)
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->handshake_read_seq++;
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return s->init_num;
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyf_err:
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ssl3_send_alert(s,SSL3_AL_FATAL,al);
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok = 0;
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return -1;
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t frag_off,frag_len,msg_len;
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_len  = msg_hdr->msg_len;
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag_off = msg_hdr->frag_off;
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag_len = msg_hdr->frag_len;
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* sanity checking */
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( (frag_off+frag_len) > msg_len)
50895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment, SSL_R_EXCESSIVE_MESSAGE_SIZE);
51095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return SSL_AD_ILLEGAL_PARAMETER;
51195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
51295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( (frag_off+frag_len) > (unsigned long)max)
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment, SSL_R_EXCESSIVE_MESSAGE_SIZE);
51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return SSL_AD_ILLEGAL_PARAMETER;
51795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
52195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* msg_len is limited to 2^24, but is effectively checked
52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * against max above */
52395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH))
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment, ERR_R_BUF_LIB);
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return SSL_AD_INTERNAL_ERROR;
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->s3->tmp.message_size  = msg_len;
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->r_msg_hdr.msg_len = msg_len;
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->s3->tmp.message_type  = msg_hdr->type;
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->r_msg_hdr.type    = msg_hdr->type;
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->r_msg_hdr.seq     = msg_hdr->seq;
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (msg_len != s->d1->r_msg_hdr.msg_len)
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* They must be playing with us! BTW, failure to enforce
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * upper limit would open possibility for buffer overrun. */
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment, SSL_R_EXCESSIVE_MESSAGE_SIZE);
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return SSL_AD_ILLEGAL_PARAMETER;
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0; /* no error */
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* (0) check whether the desired fragment is available
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * if so:
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * (1) copy over the fragment to s->init_buf->data[]
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * (2) update s->init_num
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item;
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag;
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int al;
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok = 0;
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pqueue_peek(s->d1->buffered_messages);
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( item == NULL)
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag = (hm_fragment *)item->data;
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Don't return if reassembly still in progress */
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->reassembly != NULL)
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( s->d1->handshake_read_seq == frag->msg_header.seq)
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned long frag_len = frag->msg_header.frag_len;
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pqueue_pop(s->d1->buffered_messages);
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (al==0) /* no alert */
57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			memcpy(&p[frag->msg_header.frag_off],
58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				frag->fragment,frag->msg_header.frag_len);
58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
58395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		dtls1_hm_fragment_free(frag);
58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pitem_free(item);
58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (al==0)
58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*ok = 1;
59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return frag_len;
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ssl3_send_alert(s,SSL3_AL_FATAL,al);
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->init_num = 0;
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*ok = 0;
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return -1;
59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6022306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell/* dtls1_max_handshake_message_len returns the maximum number of bytes
6032306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
6042306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell * be greater if the maximum certificate list size requires it. */
6052306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswellstatic unsigned long dtls1_max_handshake_message_len(const SSL *s)
6062306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	{
6072306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
6082306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	if (max_len < (unsigned long)s->max_cert_list)
6092306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell		return s->max_cert_list;
6102306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	return max_len;
6112306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	}
61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int
614abae631fb9af14c60834c58769ef57979ff35eeeAdam Langleydtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
61595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
61695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag = NULL;
61795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item = NULL;
61895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i = -1, is_complete;
61995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char seq64be[8];
6202306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	unsigned long frag_len = msg_hdr->frag_len;
62195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6222306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
6232306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell	    msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
62495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto err;
62595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
626e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley	if (frag_len == 0)
627e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		return DTLS1_HM_FRAGMENT_RETRY;
628e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley
62995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Try to find item in queue */
63095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(seq64be,0,sizeof(seq64be));
63195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
63295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[7] = (unsigned char) msg_hdr->seq;
63395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pqueue_find(s->d1->buffered_messages, seq64be);
63495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
63595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (item == NULL)
63695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
63795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
63895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( frag == NULL)
63995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
64095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
64195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->msg_header.frag_len = frag->msg_header.msg_len;
64295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->msg_header.frag_off = 0;
64395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
64495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
645bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley		{
64695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag = (hm_fragment*) item->data;
647bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley		if (frag->msg_header.msg_len != msg_hdr->msg_len)
648bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley			{
649bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley			item = NULL;
650bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley			frag = NULL;
651bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley			goto err;
652bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley			}
653bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley		}
654bed2214b3ee623f0b817fddb1042f9b0d8735243Adam Langley
65595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If message is already reassembled, this must be a
6563873f6f33d3faa5ff5cd34d4b094978862da2f6dMatt Caswell	 * retransmit and can be dropped. In this case item != NULL and so frag
6573873f6f33d3faa5ff5cd34d4b094978862da2f6dMatt Caswell	 * does not need to be freed. */
65895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->reassembly == NULL)
65995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
66095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned char devnull [256];
66195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6623873f6f33d3faa5ff5cd34d4b094978862da2f6dMatt Caswell		assert(item != NULL);
66395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		while (frag_len)
66495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
66595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
66695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				devnull,
66795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
66895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (i<=0) goto err;
66995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			frag_len -= i;
67095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
67195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return DTLS1_HM_FRAGMENT_RETRY;
67295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
67395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
67495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* read the body of the fragment (header has already been read */
67595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
67695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->fragment + msg_hdr->frag_off,frag_len,0);
677e24f686e31e40013f7222e745facd9f18e56f4deMatt Caswell	if ((unsigned long)i!=frag_len)
678e24f686e31e40013f7222e745facd9f18e56f4deMatt Caswell		i=-1;
679e24f686e31e40013f7222e745facd9f18e56f4deMatt Caswell	if (i<=0)
68095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto err;
68195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
68295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
68395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	                    (long)(msg_hdr->frag_off + frag_len));
68495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
68595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
68695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	                           is_complete);
68795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
68895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (is_complete)
68995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
69095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_free(frag->reassembly);
69195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->reassembly = NULL;
69295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
69395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
69495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (item == NULL)
69595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
69695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		item = pitem_new(seq64be, frag);
69795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (item == NULL)
69895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
69995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			i = -1;
700f10a63b050f353aea217cbc5da6c26b51d0bc2c0Adam Langley			goto err;
70195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
70295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
703e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		item = pqueue_insert(s->d1->buffered_messages, item);
704e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		/* pqueue_insert fails iff a duplicate item is inserted.
705e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * However, |item| cannot be a duplicate. If it were,
706e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * |pqueue_find|, above, would have returned it and control
707e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * would never have reached this branch. */
708e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		assert(item != NULL);
70995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
71095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
71195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return DTLS1_HM_FRAGMENT_RETRY;
71295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
71395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr:
714d06afe40ab84e3a99b90302399092ec4691a4fc1Adam Langley	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
71595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok = 0;
71695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return i;
71795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
71895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
71995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int
721abae631fb9af14c60834c58769ef57979ff35eeeAdam Langleydtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
72295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{
72395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i=-1;
72495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag = NULL;
72595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item = NULL;
72695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char seq64be[8];
72795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long frag_len = msg_hdr->frag_len;
72895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
73095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto err;
73195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Try to find item in queue, to prevent duplicate entries */
73395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(seq64be,0,sizeof(seq64be));
73495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
73595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[7] = (unsigned char) msg_hdr->seq;
73695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pqueue_find(s->d1->buffered_messages, seq64be);
73795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If we already have an entry and this one is a fragment,
73995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * don't discard it and rather try to reassemble it.
74095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
741abae631fb9af14c60834c58769ef57979ff35eeeAdam Langley	if (item != NULL && frag_len != msg_hdr->msg_len)
74295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		item = NULL;
74395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
74495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Discard the message if sequence number was already there, is
74595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * too far in the future, already in the queue or if we received
74695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * a FINISHED before the SERVER_HELLO, which then must be a stale
74795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * retransmit.
74895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
74995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
75095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
75195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		(s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
75295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
75395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned char devnull [256];
75495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
75595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		while (frag_len)
75695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
75795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
75895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				devnull,
75995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
76095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (i<=0) goto err;
76195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			frag_len -= i;
76295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
76395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
76495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
76595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
766abae631fb9af14c60834c58769ef57979ff35eeeAdam Langley		if (frag_len != msg_hdr->msg_len)
76795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return dtls1_reassemble_fragment(s, msg_hdr, ok);
76895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7692306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell		if (frag_len > dtls1_max_handshake_message_len(s))
7702306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell			goto err;
7712306fe5ff5611ea98f95405dc429bda0f29bcac1Matt Caswell
77295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag = dtls1_hm_fragment_new(frag_len, 0);
77395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( frag == NULL)
77495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
77595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
77695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
77795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
77895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (frag_len)
77995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
78095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* read the body of the fragment (header has already been read */
78195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
78295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				frag->fragment,frag_len,0);
7838506609ca38110eeda86d40416de7ebf3e6f9035Adam Langley			if ((unsigned long)i!=frag_len)
7848506609ca38110eeda86d40416de7ebf3e6f9035Adam Langley				i = -1;
7858506609ca38110eeda86d40416de7ebf3e6f9035Adam Langley			if (i<=0)
78695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
78795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
78895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
78995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		item = pitem_new(seq64be, frag);
79095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( item == NULL)
79195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
79295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
793e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		item = pqueue_insert(s->d1->buffered_messages, item);
794e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		/* pqueue_insert fails iff a duplicate item is inserted.
795e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * However, |item| cannot be a duplicate. If it were,
796e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * |pqueue_find|, above, would have returned it. Then, either
797e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
798e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * to NULL and it will have been processed with
799e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * |dtls1_reassemble_fragment|, above, or the record will have
800e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		 * been discarded. */
801e951ff4fc3fe9582561f7f25ad793ab7e23da785Adam Langley		assert(item != NULL);
80295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
80395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
80495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return DTLS1_HM_FRAGMENT_RETRY;
80595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
80695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr:
807d06afe40ab84e3a99b90302399092ec4691a4fc1Adam Langley	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
80895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok = 0;
80995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return i;
81095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
81195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
81295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
81395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic long
81495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_get_message_fragment(SSL *s, int stn, long max, int *ok)
81595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
81695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
81795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long len, frag_off, frag_len;
81895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i,al;
81995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct hm_header_st msg_hdr;
82095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
821895780572b7895784ed7088248ecb2ed5dd0c97aAdam Langley	redo:
82295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* see if we have the required fragment already */
82395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
82495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
82595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (*ok)	s->init_num = frag_len;
82695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return frag_len;
82795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
82895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
82995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* read handshake message header */
83095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
83195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		DTLS1_HM_HEADER_LENGTH, 0);
83295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i <= 0) 	/* nbio, or an error */
83395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
83495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->rwstate=SSL_READING;
83595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*ok = 0;
83695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i;
83795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
83895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Handshake fails if message header is incomplete */
83995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i != DTLS1_HM_HEADER_LENGTH)
84095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
84195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		al=SSL_AD_UNEXPECTED_MESSAGE;
84295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment, SSL_R_UNEXPECTED_MESSAGE);
84395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto f_err;
84495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
84595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
84695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* parse the message fragment header */
84795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	dtls1_get_message_header(wire, &msg_hdr);
84895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
84995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/*
85095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * if this is a future (or stale) message it gets buffered
85195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * (or dropped)--no further processing at this time
85295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * While listening, we accept seq 1 (ClientHello with cookie)
85395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * although we're still expecting seq 0 (ClientHello)
85495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
85595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1))
85695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
85795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
85895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	len = msg_hdr.msg_len;
85995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag_off = msg_hdr.frag_off;
86095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag_len = msg_hdr.frag_len;
86195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
86295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag_len && frag_len < len)
86395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return dtls1_reassemble_fragment(s, &msg_hdr, ok);
86495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
86595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
86695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		wire[0] == SSL3_MT_HELLO_REQUEST)
86795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
86895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* The server may always send 'Hello Request' messages --
86995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * we are doing a handshake anyway now, so ignore them
87095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * if their format is correct. Does not count for
87195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * 'Finished' MAC. */
87295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
87395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
87495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (s->msg_callback)
87595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
87695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					wire, DTLS1_HM_HEADER_LENGTH, s,
87795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					s->msg_callback_arg);
87895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->init_num = 0;
880895780572b7895784ed7088248ecb2ed5dd0c97aAdam Langley			goto redo;
88195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
88295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else /* Incorrectly formated Hello request */
88395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
88495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			al=SSL_AD_UNEXPECTED_MESSAGE;
88595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment, SSL_R_UNEXPECTED_MESSAGE);
88695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto f_err;
88795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
88895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
88995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
89095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
89195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto f_err;
89295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
89395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* XDTLS:  ressurect this when restart is in place */
89495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->state=stn;
89595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
89695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( frag_len > 0)
89795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
89895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
89995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
90095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
90195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			&p[frag_off],frag_len,0);
90295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* XDTLS:  fix this--message fragments cannot span multiple packets */
90395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (i <= 0)
90495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
90595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->rwstate=SSL_READING;
90695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*ok = 0;
90795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return i;
90895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
90995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
91095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
91195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = 0;
91295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
91395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* XDTLS:  an incorrectly formatted fragment should cause the
91495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * handshake to fail */
91595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i != (int)frag_len)
91695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
91795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		al=SSL3_AD_ILLEGAL_PARAMETER;
91895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment, SSL3_AD_ILLEGAL_PARAMETER);
91995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto f_err;
92095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
92195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
92295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok = 1;
92395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
92495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Note that s->init_num is *not* used as current offset in
92595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * s->init_buf->data, but as a counter summing up fragments'
92695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * lengths: as soon as they sum up to handshake packet
92795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * length, we assume we have got all the fragments. */
92895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->init_num = frag_len;
92995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return frag_len;
93095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
93195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyf_err:
93295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ssl3_send_alert(s,SSL3_AL_FATAL,al);
93395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->init_num = 0;
93495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
93595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ok=0;
93695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return(-1);
93795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
93895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
93995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* for these 2 messages, we need to
94095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->enc_read_ctx			re-init
94195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->s3->read_sequence		zero
94295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->s3->read_mac_secret		re-init
94395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->session->read_sym_enc		assign
94495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->session->read_compression	assign
94595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ssl->session->read_hash		assign
94695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
94795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint dtls1_send_change_cipher_spec(SSL *s, int a, int b)
94895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
94995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *p;
95095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
95195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (s->state == a)
95295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
95395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p=(unsigned char *)s->init_buf->data;
95495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*p++=SSL3_MT_CCS;
95595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
95695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->init_num=DTLS1_CCS_HEADER_LENGTH;
95795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
95895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->init_off=0;
95995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
96095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
96195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			s->d1->handshake_write_seq, 0, 0);
96295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
96395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* buffer the message to handle re-xmits */
96495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		dtls1_buffer_message(s, 1);
96595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
96695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->state=b;
96795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
96895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
96995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* SSL3_ST_CW_CHANGE_B */
97095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
97195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
97295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
97395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint dtls1_read_failed(SSL *s, int code)
97495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
97595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( code > 0)
97695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
97795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
97895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
97995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
98095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
98195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!dtls1_is_timer_expired(s))
98295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
98395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* not a timeout, none of our business,
98495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		   let higher layers handle this.  in fact it's probably an error */
98595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return code;
98695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
98795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
98895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!SSL_in_init(s))  /* done, no need to send a retransmit */
98995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
99095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
99195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return code;
99295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
99395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
99495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0 /* for now, each alert contains only one record number */
99595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pqueue_peek(state->rcvd_records);
99695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( item )
99795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
99895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* send an alert immediately for all the missing records */
99995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
100095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
100195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
100295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
100395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0  /* no more alert sending, just retransmit the last set of messages */
100495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
100595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ssl3_send_alert(s,SSL3_AL_WARNING,
100695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
100795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
100895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
100995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return dtls1_handle_timeout(s);
101095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
101195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
101295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint
101395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_get_queue_priority(unsigned short seq, int is_ccs)
101495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
101595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* The index of the retransmission queue actually is the message sequence number,
101695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * since the queue only contains messages of a single handshake. However, the
101795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * ChangeCipherSpec has no message sequence number and so using only the sequence
101895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * will result in the CCS and Finished having the same index. To prevent this,
101995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted.
102095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * This does not only differ CSS and Finished, it also maintains the order of the
102195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * index (important for priority queues) and fits in the unsigned short variable.
102295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
102395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return seq * 2 - is_ccs;
102495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
102595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
102695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint
102795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_retransmit_buffered_messages(SSL *s)
102895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
102995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pqueue sent = s->d1->sent_messages;
103095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	piterator iter;
103195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item;
103295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag;
103395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int found = 0;
103495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
103595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	iter = pqueue_iterator(sent);
103695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
103795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
103895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
103995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag = (hm_fragment *)item->data;
104095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ( dtls1_retransmit_message(s,
104195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				(unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs),
104295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				0, &found) <= 0 && found)
104395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
104495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			fprintf(stderr, "dtls1_retransmit_message() failed\n");
104595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
104695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
104795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
104895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
104995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
105095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
105195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
105295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint
105395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_buffer_message(SSL *s, int is_ccs)
105495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
105595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item;
105695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag;
105795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char seq64be[8];
105895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
105995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* this function is called immediately after a message has
106095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * been serialized */
106195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	assert(s->init_off == 0);
106295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
106395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag = dtls1_hm_fragment_new(s->init_num, 0);
1064e044fe4bc773061589d40bf56011843570fd63aaAdam Langley	if (!frag)
1065e044fe4bc773061589d40bf56011843570fd63aaAdam Langley		return 0;
106695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
106795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memcpy(frag->fragment, s->init_buf->data, s->init_num);
106895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
106995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( is_ccs)
107095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
107195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		assert(s->d1->w_msg_hdr.msg_len +
107295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			       DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
107395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
107495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
107595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
107695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		assert(s->d1->w_msg_hdr.msg_len +
107795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
107895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
107995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
108095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
108195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
108295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.type = s->d1->w_msg_hdr.type;
108395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.frag_off = 0;
108495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
108595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.is_ccs = is_ccs;
108695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
108795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* save current state*/
108895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
108995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
109095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.saved_retransmit_state.session = s->session;
109195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
109295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
109395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(seq64be,0,sizeof(seq64be));
109495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
109595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley														  frag->msg_header.is_ccs)>>8);
109695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
109795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley														  frag->msg_header.is_ccs));
109895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
109995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pitem_new(seq64be, frag);
110095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( item == NULL)
110195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
110295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		dtls1_hm_fragment_free(frag);
110395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
110495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
110595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
110695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
110795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
110895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
110995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
111095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
111195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
111295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pqueue_insert(s->d1->sent_messages, item);
111395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
111495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
111595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
111695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint
111795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
111895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int *found)
111995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
112095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
112195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* XDTLS: for now assuming that read/writes are blocking */
112295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item;
112395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	hm_fragment *frag ;
112495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned long header_length;
112595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char seq64be[8];
112695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct dtls1_retransmit_state saved_state;
112795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char save_write_sequence[8];
112895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
112995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/*
113095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	  assert(s->init_num == 0);
113195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	  assert(s->init_off == 0);
113295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
113395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
113495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* XDTLS:  the requested message ought to be found, otherwise error */
113595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(seq64be,0,sizeof(seq64be));
113695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[6] = (unsigned char)(seq>>8);
113795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	seq64be[7] = (unsigned char)seq;
113895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
113995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	item = pqueue_find(s->d1->sent_messages, seq64be);
114095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( item == NULL)
114195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
114295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
114395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*found = 0;
114495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
114595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
114695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
114795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*found = 1;
114895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	frag = (hm_fragment *)item->data;
114995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
115095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( frag->msg_header.is_ccs)
115195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		header_length = DTLS1_CCS_HEADER_LENGTH;
115295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
115395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		header_length = DTLS1_HM_HEADER_LENGTH;
115495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
115595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memcpy(s->init_buf->data, frag->fragment,
115695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->msg_header.msg_len + header_length);
115795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->init_num = frag->msg_header.msg_len + header_length;
115895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
115995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	dtls1_set_message_header_int(s, frag->msg_header.type,
116095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->msg_header.msg_len, frag->msg_header.seq, 0,
116195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag->msg_header.frag_len);
116295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
116395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* save current state */
116495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	saved_state.enc_write_ctx = s->enc_write_ctx;
116595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	saved_state.write_hash = s->write_hash;
116695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	saved_state.session = s->session;
116795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	saved_state.epoch = s->d1->w_epoch;
116895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
116995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->d1->retransmitting = 1;
117095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
117195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* restore state in which the message was originally sent */
117295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
117395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
117495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->session = frag->msg_header.saved_retransmit_state.session;
117595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
117695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
117795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
117895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
117995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
118095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
118195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
118295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
118395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
118495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
118595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
118695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* restore current state */
118795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->enc_write_ctx = saved_state.enc_write_ctx;
118895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->write_hash = saved_state.write_hash;
118995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->session = saved_state.session;
119095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->d1->w_epoch = saved_state.epoch;
119195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
119295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
119395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
119495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
119595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
119695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
119795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
119895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s->d1->retransmitting = 0;
119995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
120095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	(void)BIO_flush(SSL_get_wbio(s));
120195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ret;
120295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
120395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
120495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* call this function when the buffered messages are no longer needed */
120595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid
120695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_clear_record_buffer(SSL *s)
120795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
120895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pitem *item;
120995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
121095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for(item = pqueue_pop(s->d1->sent_messages);
121195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		item != NULL; item = pqueue_pop(s->d1->sent_messages))
121295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
121395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		dtls1_hm_fragment_free((hm_fragment *)item->data);
121495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pitem_free(item);
121595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
121695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
121795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
121895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
121995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned char *
122095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
122195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			unsigned long len, unsigned long frag_off, unsigned long frag_len)
122295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
122395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Don't change sequence numbers while listening */
122495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (frag_off == 0 && !s->d1->listen)
122595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
122695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
122795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		s->d1->next_handshake_write_seq++;
122895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
122995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
123095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
123195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		frag_off, frag_len);
123295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
123395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return p += DTLS1_HM_HEADER_LENGTH;
123495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
123595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
123695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
123795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* don't actually do the writing, wait till the MTU has been retrieved */
123895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void
123995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_set_message_header_int(SSL *s, unsigned char mt,
124095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			    unsigned long len, unsigned short seq_num, unsigned long frag_off,
124195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			    unsigned long frag_len)
124295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
124395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
124495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
124595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->type = mt;
124695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->msg_len = len;
124795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->seq = seq_num;
124895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->frag_off = frag_off;
124995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->frag_len = frag_len;
125095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
125195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
125295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void
125395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_fix_message_header(SSL *s, unsigned long frag_off,
125495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			unsigned long frag_len)
125595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
125695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
125795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
125895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->frag_off = frag_off;
125995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->frag_len = frag_len;
126095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
126195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
126295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic unsigned char *
126395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_write_message_header(SSL *s, unsigned char *p)
126495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
126595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
126695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
126795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*p++ = msg_hdr->type;
126895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(msg_hdr->msg_len, p);
126995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
127095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	s2n(msg_hdr->seq, p);
127195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(msg_hdr->frag_off, p);
127295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	l2n3(msg_hdr->frag_len, p);
127395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
127495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return p;
127595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
127695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
127795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned int
127895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_min_mtu(void)
127995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
128095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return (g_probable_mtu[(sizeof(g_probable_mtu) /
128195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		sizeof(g_probable_mtu[0])) - 1]);
128295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
128395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
128495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic unsigned int
128595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_guess_mtu(unsigned int curr_mtu)
128695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
128795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned int i;
128895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
128995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ( curr_mtu == 0 )
129095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return g_probable_mtu[0] ;
129195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++)
129395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ( curr_mtu > g_probable_mtu[i])
129495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return g_probable_mtu[i];
129595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return curr_mtu;
129795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
129895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid
130095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
130195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
130295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
130395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	msg_hdr->type = *(data++);
130495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	n2l3(data, msg_hdr->msg_len);
130595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
130695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	n2s(data, msg_hdr->seq);
130795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	n2l3(data, msg_hdr->frag_off);
130895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	n2l3(data, msg_hdr->frag_len);
130995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
131095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
131195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid
131295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleydtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
131395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
131495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
131595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
131695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ccs_hdr->type = *(data++);
131795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
131895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
131995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint dtls1_shutdown(SSL *s)
132095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
132195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
132295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = ssl3_shutdown(s);
132395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ret;
132495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
1325