1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: d1_both.c,v 1.81 2022/02/05 14:54:10 jsing Exp $ */
2f5b1c8a1SJohn Marino /*
3f5b1c8a1SJohn Marino * DTLS implementation written by Nagendra Modadugu
4f5b1c8a1SJohn Marino * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5f5b1c8a1SJohn Marino */
6f5b1c8a1SJohn Marino /* ====================================================================
7f5b1c8a1SJohn Marino * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
8f5b1c8a1SJohn Marino *
9f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
10f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
11f5b1c8a1SJohn Marino * are met:
12f5b1c8a1SJohn Marino *
13f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright
14f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
15f5b1c8a1SJohn Marino *
16f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
17f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in
18f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the
19f5b1c8a1SJohn Marino * distribution.
20f5b1c8a1SJohn Marino *
21f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this
22f5b1c8a1SJohn Marino * software must display the following acknowledgment:
23f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
24f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25f5b1c8a1SJohn Marino *
26f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27f5b1c8a1SJohn Marino * endorse or promote products derived from this software without
28f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact
29f5b1c8a1SJohn Marino * openssl-core@openssl.org.
30f5b1c8a1SJohn Marino *
31f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL"
32f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written
33f5b1c8a1SJohn Marino * permission of the OpenSSL Project.
34f5b1c8a1SJohn Marino *
35f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following
36f5b1c8a1SJohn Marino * acknowledgment:
37f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
38f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39f5b1c8a1SJohn Marino *
40f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE.
52f5b1c8a1SJohn Marino * ====================================================================
53f5b1c8a1SJohn Marino *
54f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young
55f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim
56f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com).
57f5b1c8a1SJohn Marino *
58f5b1c8a1SJohn Marino */
59f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
60f5b1c8a1SJohn Marino * All rights reserved.
61f5b1c8a1SJohn Marino *
62f5b1c8a1SJohn Marino * This package is an SSL implementation written
63f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com).
64f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL.
65f5b1c8a1SJohn Marino *
66f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as
67f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions
68f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA,
69f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation
70f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms
71f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com).
72f5b1c8a1SJohn Marino *
73f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in
74f5b1c8a1SJohn Marino * the code are not to be removed.
75f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution
76f5b1c8a1SJohn Marino * as the author of the parts of the library used.
77f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or
78f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package.
79f5b1c8a1SJohn Marino *
80f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
81f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
82f5b1c8a1SJohn Marino * are met:
83f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright
84f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
85f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
86f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the
87f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution.
88f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software
89f5b1c8a1SJohn Marino * must display the following acknowledgement:
90f5b1c8a1SJohn Marino * "This product includes cryptographic software written by
91f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)"
92f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library
93f5b1c8a1SJohn Marino * being used are not cryptographic related :-).
94f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from
95f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement:
96f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
97f5b1c8a1SJohn Marino *
98f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
99f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
101f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
102f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
103f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
104f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
106f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
107f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
108f5b1c8a1SJohn Marino * SUCH DAMAGE.
109f5b1c8a1SJohn Marino *
110f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or
111f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be
112f5b1c8a1SJohn Marino * copied and put under another distribution licence
113f5b1c8a1SJohn Marino * [including the GNU Public Licence.]
114f5b1c8a1SJohn Marino */
115f5b1c8a1SJohn Marino
116f5b1c8a1SJohn Marino #include <limits.h>
117f5b1c8a1SJohn Marino #include <stdio.h>
118f5b1c8a1SJohn Marino #include <string.h>
119f5b1c8a1SJohn Marino
120f5b1c8a1SJohn Marino #include <openssl/buffer.h>
121f5b1c8a1SJohn Marino #include <openssl/evp.h>
122f5b1c8a1SJohn Marino #include <openssl/objects.h>
123f5b1c8a1SJohn Marino #include <openssl/x509.h>
124f5b1c8a1SJohn Marino
125f5b1c8a1SJohn Marino #include "bytestring.h"
126*de0e0e4dSAntonio Huete Jimenez #include "dtls_locl.h"
127*de0e0e4dSAntonio Huete Jimenez #include "pqueue.h"
128*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
129f5b1c8a1SJohn Marino
130f5b1c8a1SJohn Marino #define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
131f5b1c8a1SJohn Marino
132f5b1c8a1SJohn Marino #define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
133f5b1c8a1SJohn Marino if ((end) - (start) <= 8) { \
134f5b1c8a1SJohn Marino long ii; \
135f5b1c8a1SJohn Marino for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
136f5b1c8a1SJohn Marino } else { \
137f5b1c8a1SJohn Marino long ii; \
138f5b1c8a1SJohn Marino bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
139f5b1c8a1SJohn Marino for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
140f5b1c8a1SJohn Marino bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
141f5b1c8a1SJohn Marino } }
142f5b1c8a1SJohn Marino
143f5b1c8a1SJohn Marino #define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
144f5b1c8a1SJohn Marino long ii; \
145f5b1c8a1SJohn Marino OPENSSL_assert((msg_len) > 0); \
146f5b1c8a1SJohn Marino is_complete = 1; \
147f5b1c8a1SJohn Marino if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
148f5b1c8a1SJohn Marino if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
149f5b1c8a1SJohn Marino if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
150f5b1c8a1SJohn Marino
151*de0e0e4dSAntonio Huete Jimenez static const unsigned char bitmask_start_values[] = {
152f5b1c8a1SJohn Marino 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80
153f5b1c8a1SJohn Marino };
154*de0e0e4dSAntonio Huete Jimenez static const unsigned char bitmask_end_values[] = {
155f5b1c8a1SJohn Marino 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f
156f5b1c8a1SJohn Marino };
157f5b1c8a1SJohn Marino
158f5b1c8a1SJohn Marino /* XDTLS: figure out the right values */
159*de0e0e4dSAntonio Huete Jimenez static const unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
160f5b1c8a1SJohn Marino
161f5b1c8a1SJohn Marino static unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
162f5b1c8a1SJohn Marino static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
163f5b1c8a1SJohn Marino unsigned long frag_len);
16472c33676SMaxim Ag static int dtls1_write_message_header(const struct hm_header_st *msg_hdr,
16572c33676SMaxim Ag unsigned long frag_off, unsigned long frag_len, unsigned char *p);
166f5b1c8a1SJohn Marino static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max,
167f5b1c8a1SJohn Marino int *ok);
168f5b1c8a1SJohn Marino
1698edacedfSDaniel Fojt void dtls1_hm_fragment_free(hm_fragment *frag);
1708edacedfSDaniel Fojt
171f5b1c8a1SJohn Marino static hm_fragment *
dtls1_hm_fragment_new(unsigned long frag_len,int reassembly)172f5b1c8a1SJohn Marino dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
173f5b1c8a1SJohn Marino {
1748edacedfSDaniel Fojt hm_fragment *frag;
175f5b1c8a1SJohn Marino
1768edacedfSDaniel Fojt if ((frag = calloc(1, sizeof(*frag))) == NULL)
1778edacedfSDaniel Fojt goto err;
178f5b1c8a1SJohn Marino
1798edacedfSDaniel Fojt if (frag_len > 0) {
1808edacedfSDaniel Fojt if ((frag->fragment = calloc(1, frag_len)) == NULL)
1818edacedfSDaniel Fojt goto err;
182f5b1c8a1SJohn Marino }
183f5b1c8a1SJohn Marino
1848edacedfSDaniel Fojt /* Initialize reassembly bitmask if necessary. */
185f5b1c8a1SJohn Marino if (reassembly) {
1868edacedfSDaniel Fojt if ((frag->reassembly = calloc(1,
1878edacedfSDaniel Fojt RSMBLY_BITMASK_SIZE(frag_len))) == NULL)
1888edacedfSDaniel Fojt goto err;
189f5b1c8a1SJohn Marino }
190f5b1c8a1SJohn Marino
191f5b1c8a1SJohn Marino return frag;
1928edacedfSDaniel Fojt
1938edacedfSDaniel Fojt err:
1948edacedfSDaniel Fojt dtls1_hm_fragment_free(frag);
1958edacedfSDaniel Fojt return NULL;
196f5b1c8a1SJohn Marino }
197f5b1c8a1SJohn Marino
1988edacedfSDaniel Fojt void
dtls1_hm_fragment_free(hm_fragment * frag)199f5b1c8a1SJohn Marino dtls1_hm_fragment_free(hm_fragment *frag)
200f5b1c8a1SJohn Marino {
201f5b1c8a1SJohn Marino if (frag == NULL)
202f5b1c8a1SJohn Marino return;
203f5b1c8a1SJohn Marino
204f5b1c8a1SJohn Marino free(frag->fragment);
205f5b1c8a1SJohn Marino free(frag->reassembly);
206f5b1c8a1SJohn Marino free(frag);
207f5b1c8a1SJohn Marino }
208f5b1c8a1SJohn Marino
20972c33676SMaxim Ag /* send s->internal->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
210f5b1c8a1SJohn Marino int
dtls1_do_write(SSL * s,int type)211f5b1c8a1SJohn Marino dtls1_do_write(SSL *s, int type)
212f5b1c8a1SJohn Marino {
213f5b1c8a1SJohn Marino int ret;
214f5b1c8a1SJohn Marino int curr_mtu;
215*de0e0e4dSAntonio Huete Jimenez unsigned int len, frag_off;
216*de0e0e4dSAntonio Huete Jimenez size_t overhead;
217f5b1c8a1SJohn Marino
218f5b1c8a1SJohn Marino /* AHA! Figure out the MTU, and stick to the right size */
219*de0e0e4dSAntonio Huete Jimenez if (s->d1->mtu < dtls1_min_mtu() &&
220f5b1c8a1SJohn Marino !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
221*de0e0e4dSAntonio Huete Jimenez s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
222f5b1c8a1SJohn Marino BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
223f5b1c8a1SJohn Marino
224f5b1c8a1SJohn Marino /*
225f5b1c8a1SJohn Marino * I've seen the kernel return bogus numbers when it
226f5b1c8a1SJohn Marino * doesn't know the MTU (ie., the initial write), so just
227f5b1c8a1SJohn Marino * make sure we have a reasonable number
228f5b1c8a1SJohn Marino */
229*de0e0e4dSAntonio Huete Jimenez if (s->d1->mtu < dtls1_min_mtu()) {
230*de0e0e4dSAntonio Huete Jimenez s->d1->mtu = 0;
231*de0e0e4dSAntonio Huete Jimenez s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
232f5b1c8a1SJohn Marino BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
233*de0e0e4dSAntonio Huete Jimenez s->d1->mtu, NULL);
234f5b1c8a1SJohn Marino }
235f5b1c8a1SJohn Marino }
236f5b1c8a1SJohn Marino
237*de0e0e4dSAntonio Huete Jimenez OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu());
238f5b1c8a1SJohn Marino /* should have something reasonable now */
239f5b1c8a1SJohn Marino
24072c33676SMaxim Ag if (s->internal->init_off == 0 && type == SSL3_RT_HANDSHAKE)
24172c33676SMaxim Ag OPENSSL_assert(s->internal->init_num ==
242*de0e0e4dSAntonio Huete Jimenez (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
243f5b1c8a1SJohn Marino
244*de0e0e4dSAntonio Huete Jimenez if (!tls12_record_layer_write_overhead(s->internal->rl, &overhead))
245*de0e0e4dSAntonio Huete Jimenez return -1;
246f5b1c8a1SJohn Marino
247f5b1c8a1SJohn Marino frag_off = 0;
24872c33676SMaxim Ag while (s->internal->init_num) {
249*de0e0e4dSAntonio Huete Jimenez curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -
250*de0e0e4dSAntonio Huete Jimenez DTLS1_RT_HEADER_LENGTH - overhead;
251f5b1c8a1SJohn Marino
252f5b1c8a1SJohn Marino if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
253f5b1c8a1SJohn Marino /* grr.. we could get an error if MTU picked was wrong */
254f5b1c8a1SJohn Marino ret = BIO_flush(SSL_get_wbio(s));
255f5b1c8a1SJohn Marino if (ret <= 0)
256f5b1c8a1SJohn Marino return ret;
257*de0e0e4dSAntonio Huete Jimenez curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH -
258*de0e0e4dSAntonio Huete Jimenez overhead;
259f5b1c8a1SJohn Marino }
260f5b1c8a1SJohn Marino
26172c33676SMaxim Ag if (s->internal->init_num > curr_mtu)
262f5b1c8a1SJohn Marino len = curr_mtu;
263f5b1c8a1SJohn Marino else
26472c33676SMaxim Ag len = s->internal->init_num;
265f5b1c8a1SJohn Marino
266f5b1c8a1SJohn Marino /* XDTLS: this function is too long. split out the CCS part */
267f5b1c8a1SJohn Marino if (type == SSL3_RT_HANDSHAKE) {
26872c33676SMaxim Ag if (s->internal->init_off != 0) {
26972c33676SMaxim Ag OPENSSL_assert(s->internal->init_off > DTLS1_HM_HEADER_LENGTH);
27072c33676SMaxim Ag s->internal->init_off -= DTLS1_HM_HEADER_LENGTH;
27172c33676SMaxim Ag s->internal->init_num += DTLS1_HM_HEADER_LENGTH;
272f5b1c8a1SJohn Marino
27372c33676SMaxim Ag if (s->internal->init_num > curr_mtu)
274f5b1c8a1SJohn Marino len = curr_mtu;
275f5b1c8a1SJohn Marino else
27672c33676SMaxim Ag len = s->internal->init_num;
277f5b1c8a1SJohn Marino }
278f5b1c8a1SJohn Marino
279f5b1c8a1SJohn Marino dtls1_fix_message_header(s, frag_off,
280f5b1c8a1SJohn Marino len - DTLS1_HM_HEADER_LENGTH);
281f5b1c8a1SJohn Marino
282*de0e0e4dSAntonio Huete Jimenez if (!dtls1_write_message_header(&s->d1->w_msg_hdr,
283*de0e0e4dSAntonio Huete Jimenez s->d1->w_msg_hdr.frag_off, s->d1->w_msg_hdr.frag_len,
28472c33676SMaxim Ag (unsigned char *)&s->internal->init_buf->data[s->internal->init_off]))
28572c33676SMaxim Ag return -1;
286f5b1c8a1SJohn Marino
287f5b1c8a1SJohn Marino OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH);
288f5b1c8a1SJohn Marino }
289f5b1c8a1SJohn Marino
290f5b1c8a1SJohn Marino ret = dtls1_write_bytes(s, type,
29172c33676SMaxim Ag &s->internal->init_buf->data[s->internal->init_off], len);
292f5b1c8a1SJohn Marino if (ret < 0) {
293f5b1c8a1SJohn Marino /*
294f5b1c8a1SJohn Marino * Might need to update MTU here, but we don't know
295f5b1c8a1SJohn Marino * which previous packet caused the failure -- so
296f5b1c8a1SJohn Marino * can't really retransmit anything. continue as
297f5b1c8a1SJohn Marino * if everything is fine and wait for an alert to
298f5b1c8a1SJohn Marino * handle the retransmit
299f5b1c8a1SJohn Marino */
300f5b1c8a1SJohn Marino if (BIO_ctrl(SSL_get_wbio(s),
301f5b1c8a1SJohn Marino BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0)
302*de0e0e4dSAntonio Huete Jimenez s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
303f5b1c8a1SJohn Marino BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
304f5b1c8a1SJohn Marino else
305f5b1c8a1SJohn Marino return (-1);
306f5b1c8a1SJohn Marino } else {
307f5b1c8a1SJohn Marino
308f5b1c8a1SJohn Marino /*
309f5b1c8a1SJohn Marino * Bad if this assert fails, only part of the
310f5b1c8a1SJohn Marino * handshake message got sent. but why would
311f5b1c8a1SJohn Marino * this happen?
312f5b1c8a1SJohn Marino */
313f5b1c8a1SJohn Marino OPENSSL_assert(len == (unsigned int)ret);
314f5b1c8a1SJohn Marino
315f5b1c8a1SJohn Marino if (type == SSL3_RT_HANDSHAKE &&
316*de0e0e4dSAntonio Huete Jimenez !s->d1->retransmitting) {
317f5b1c8a1SJohn Marino /*
318f5b1c8a1SJohn Marino * Should not be done for 'Hello Request's,
319f5b1c8a1SJohn Marino * but in that case we'll ignore the result
320f5b1c8a1SJohn Marino * anyway
321f5b1c8a1SJohn Marino */
32272c33676SMaxim Ag unsigned char *p = (unsigned char *)&s->internal->init_buf->data[s->internal->init_off];
323*de0e0e4dSAntonio Huete Jimenez const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
324f5b1c8a1SJohn Marino int xlen;
325f5b1c8a1SJohn Marino
326f5b1c8a1SJohn Marino if (frag_off == 0) {
327f5b1c8a1SJohn Marino /*
328f5b1c8a1SJohn Marino * Reconstruct message header is if it
329f5b1c8a1SJohn Marino * is being sent in single fragment
330f5b1c8a1SJohn Marino */
33172c33676SMaxim Ag if (!dtls1_write_message_header(msg_hdr,
33272c33676SMaxim Ag 0, msg_hdr->msg_len, p))
33372c33676SMaxim Ag return (-1);
334f5b1c8a1SJohn Marino xlen = ret;
335f5b1c8a1SJohn Marino } else {
336f5b1c8a1SJohn Marino p += DTLS1_HM_HEADER_LENGTH;
337f5b1c8a1SJohn Marino xlen = ret - DTLS1_HM_HEADER_LENGTH;
338f5b1c8a1SJohn Marino }
339f5b1c8a1SJohn Marino
34072c33676SMaxim Ag tls1_transcript_record(s, p, xlen);
341f5b1c8a1SJohn Marino }
342f5b1c8a1SJohn Marino
34372c33676SMaxim Ag if (ret == s->internal->init_num) {
34472c33676SMaxim Ag if (s->internal->msg_callback)
34572c33676SMaxim Ag s->internal->msg_callback(1, s->version, type,
34672c33676SMaxim Ag s->internal->init_buf->data,
34772c33676SMaxim Ag (size_t)(s->internal->init_off + s->internal->init_num),
34872c33676SMaxim Ag s, s->internal->msg_callback_arg);
349f5b1c8a1SJohn Marino
35072c33676SMaxim Ag s->internal->init_off = 0;
351f5b1c8a1SJohn Marino /* done writing this message */
35272c33676SMaxim Ag s->internal->init_num = 0;
353f5b1c8a1SJohn Marino
354f5b1c8a1SJohn Marino return (1);
355f5b1c8a1SJohn Marino }
35672c33676SMaxim Ag s->internal->init_off += ret;
35772c33676SMaxim Ag s->internal->init_num -= ret;
358f5b1c8a1SJohn Marino frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
359f5b1c8a1SJohn Marino }
360f5b1c8a1SJohn Marino }
361f5b1c8a1SJohn Marino return (0);
362f5b1c8a1SJohn Marino }
363f5b1c8a1SJohn Marino
364f5b1c8a1SJohn Marino
365f5b1c8a1SJohn Marino /*
366f5b1c8a1SJohn Marino * Obtain handshake message of message type 'mt' (any if mt == -1),
367f5b1c8a1SJohn Marino * maximum acceptable body length 'max'.
368f5b1c8a1SJohn Marino * Read an entire handshake message. Handshake messages arrive in
369f5b1c8a1SJohn Marino * fragments.
370f5b1c8a1SJohn Marino */
371*de0e0e4dSAntonio Huete Jimenez int
dtls1_get_message(SSL * s,int st1,int stn,int mt,long max)372*de0e0e4dSAntonio Huete Jimenez dtls1_get_message(SSL *s, int st1, int stn, int mt, long max)
373f5b1c8a1SJohn Marino {
374f5b1c8a1SJohn Marino struct hm_header_st *msg_hdr;
375f5b1c8a1SJohn Marino unsigned char *p;
376f5b1c8a1SJohn Marino unsigned long msg_len;
377*de0e0e4dSAntonio Huete Jimenez int i, al, ok;
378f5b1c8a1SJohn Marino
379f5b1c8a1SJohn Marino /*
38072c33676SMaxim Ag * s3->internal->tmp is used to store messages that are unexpected, caused
381f5b1c8a1SJohn Marino * by the absence of an optional handshake message
382f5b1c8a1SJohn Marino */
383*de0e0e4dSAntonio Huete Jimenez if (s->s3->hs.tls12.reuse_message) {
384*de0e0e4dSAntonio Huete Jimenez s->s3->hs.tls12.reuse_message = 0;
385*de0e0e4dSAntonio Huete Jimenez if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) {
386f5b1c8a1SJohn Marino al = SSL_AD_UNEXPECTED_MESSAGE;
38772c33676SMaxim Ag SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
388*de0e0e4dSAntonio Huete Jimenez goto fatal_err;
389f5b1c8a1SJohn Marino }
39072c33676SMaxim Ag s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH;
391*de0e0e4dSAntonio Huete Jimenez s->internal->init_num = (int)s->s3->hs.tls12.message_size;
392*de0e0e4dSAntonio Huete Jimenez return 1;
393f5b1c8a1SJohn Marino }
394f5b1c8a1SJohn Marino
395*de0e0e4dSAntonio Huete Jimenez msg_hdr = &s->d1->r_msg_hdr;
3968edacedfSDaniel Fojt memset(msg_hdr, 0, sizeof(struct hm_header_st));
397f5b1c8a1SJohn Marino
398f5b1c8a1SJohn Marino again:
399*de0e0e4dSAntonio Huete Jimenez i = dtls1_get_message_fragment(s, st1, stn, max, &ok);
400f5b1c8a1SJohn Marino if (i == DTLS1_HM_BAD_FRAGMENT ||
401f5b1c8a1SJohn Marino i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */
402f5b1c8a1SJohn Marino goto again;
403*de0e0e4dSAntonio Huete Jimenez else if (i <= 0 && !ok)
404f5b1c8a1SJohn Marino return i;
405f5b1c8a1SJohn Marino
40672c33676SMaxim Ag p = (unsigned char *)s->internal->init_buf->data;
407f5b1c8a1SJohn Marino msg_len = msg_hdr->msg_len;
408f5b1c8a1SJohn Marino
409f5b1c8a1SJohn Marino /* reconstruct message header */
41072c33676SMaxim Ag if (!dtls1_write_message_header(msg_hdr, 0, msg_len, p))
41172c33676SMaxim Ag return -1;
412f5b1c8a1SJohn Marino
413f5b1c8a1SJohn Marino msg_len += DTLS1_HM_HEADER_LENGTH;
414f5b1c8a1SJohn Marino
41572c33676SMaxim Ag tls1_transcript_record(s, p, msg_len);
41672c33676SMaxim Ag if (s->internal->msg_callback)
41772c33676SMaxim Ag s->internal->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len,
41872c33676SMaxim Ag s, s->internal->msg_callback_arg);
419f5b1c8a1SJohn Marino
4208edacedfSDaniel Fojt memset(msg_hdr, 0, sizeof(struct hm_header_st));
421f5b1c8a1SJohn Marino
422f5b1c8a1SJohn Marino /* Don't change sequence numbers while listening */
423*de0e0e4dSAntonio Huete Jimenez if (!s->d1->listen)
424*de0e0e4dSAntonio Huete Jimenez s->d1->handshake_read_seq++;
425f5b1c8a1SJohn Marino
42672c33676SMaxim Ag s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH;
427*de0e0e4dSAntonio Huete Jimenez return 1;
428f5b1c8a1SJohn Marino
429*de0e0e4dSAntonio Huete Jimenez fatal_err:
430f5b1c8a1SJohn Marino ssl3_send_alert(s, SSL3_AL_FATAL, al);
431f5b1c8a1SJohn Marino return -1;
432f5b1c8a1SJohn Marino }
433f5b1c8a1SJohn Marino
434f5b1c8a1SJohn Marino static int
dtls1_preprocess_fragment(SSL * s,struct hm_header_st * msg_hdr,int max)435f5b1c8a1SJohn Marino dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max)
436f5b1c8a1SJohn Marino {
437f5b1c8a1SJohn Marino size_t frag_off, frag_len, msg_len;
438f5b1c8a1SJohn Marino
439f5b1c8a1SJohn Marino msg_len = msg_hdr->msg_len;
440f5b1c8a1SJohn Marino frag_off = msg_hdr->frag_off;
441f5b1c8a1SJohn Marino frag_len = msg_hdr->frag_len;
442f5b1c8a1SJohn Marino
443f5b1c8a1SJohn Marino /* sanity checking */
444f5b1c8a1SJohn Marino if ((frag_off + frag_len) > msg_len) {
44572c33676SMaxim Ag SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
446f5b1c8a1SJohn Marino return SSL_AD_ILLEGAL_PARAMETER;
447f5b1c8a1SJohn Marino }
448f5b1c8a1SJohn Marino
449f5b1c8a1SJohn Marino if ((frag_off + frag_len) > (unsigned long)max) {
45072c33676SMaxim Ag SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
451f5b1c8a1SJohn Marino return SSL_AD_ILLEGAL_PARAMETER;
452f5b1c8a1SJohn Marino }
453f5b1c8a1SJohn Marino
454*de0e0e4dSAntonio Huete Jimenez if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
455f5b1c8a1SJohn Marino {
456f5b1c8a1SJohn Marino /*
457f5b1c8a1SJohn Marino * msg_len is limited to 2^24, but is effectively checked
458f5b1c8a1SJohn Marino * against max above
459f5b1c8a1SJohn Marino */
46072c33676SMaxim Ag if (!BUF_MEM_grow_clean(s->internal->init_buf,
461f5b1c8a1SJohn Marino msg_len + DTLS1_HM_HEADER_LENGTH)) {
46272c33676SMaxim Ag SSLerror(s, ERR_R_BUF_LIB);
463f5b1c8a1SJohn Marino return SSL_AD_INTERNAL_ERROR;
464f5b1c8a1SJohn Marino }
465f5b1c8a1SJohn Marino
466*de0e0e4dSAntonio Huete Jimenez s->s3->hs.tls12.message_size = msg_len;
467*de0e0e4dSAntonio Huete Jimenez s->d1->r_msg_hdr.msg_len = msg_len;
468*de0e0e4dSAntonio Huete Jimenez s->s3->hs.tls12.message_type = msg_hdr->type;
469*de0e0e4dSAntonio Huete Jimenez s->d1->r_msg_hdr.type = msg_hdr->type;
470*de0e0e4dSAntonio Huete Jimenez s->d1->r_msg_hdr.seq = msg_hdr->seq;
471*de0e0e4dSAntonio Huete Jimenez } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
472f5b1c8a1SJohn Marino /*
473f5b1c8a1SJohn Marino * They must be playing with us! BTW, failure to enforce
474f5b1c8a1SJohn Marino * upper limit would open possibility for buffer overrun.
475f5b1c8a1SJohn Marino */
47672c33676SMaxim Ag SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE);
477f5b1c8a1SJohn Marino return SSL_AD_ILLEGAL_PARAMETER;
478f5b1c8a1SJohn Marino }
479f5b1c8a1SJohn Marino
480f5b1c8a1SJohn Marino return 0; /* no error */
481f5b1c8a1SJohn Marino }
482f5b1c8a1SJohn Marino
483f5b1c8a1SJohn Marino static int
dtls1_retrieve_buffered_fragment(SSL * s,long max,int * ok)484f5b1c8a1SJohn Marino dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
485f5b1c8a1SJohn Marino {
486f5b1c8a1SJohn Marino /*
487f5b1c8a1SJohn Marino * (0) check whether the desired fragment is available
488f5b1c8a1SJohn Marino * if so:
48972c33676SMaxim Ag * (1) copy over the fragment to s->internal->init_buf->data[]
49072c33676SMaxim Ag * (2) update s->internal->init_num
491f5b1c8a1SJohn Marino */
492f5b1c8a1SJohn Marino pitem *item;
493f5b1c8a1SJohn Marino hm_fragment *frag;
494f5b1c8a1SJohn Marino int al;
495f5b1c8a1SJohn Marino
496f5b1c8a1SJohn Marino *ok = 0;
497*de0e0e4dSAntonio Huete Jimenez item = pqueue_peek(s->d1->buffered_messages);
498f5b1c8a1SJohn Marino if (item == NULL)
499f5b1c8a1SJohn Marino return 0;
500f5b1c8a1SJohn Marino
501f5b1c8a1SJohn Marino frag = (hm_fragment *)item->data;
502f5b1c8a1SJohn Marino
503f5b1c8a1SJohn Marino /* Don't return if reassembly still in progress */
504f5b1c8a1SJohn Marino if (frag->reassembly != NULL)
505f5b1c8a1SJohn Marino return 0;
506f5b1c8a1SJohn Marino
507*de0e0e4dSAntonio Huete Jimenez if (s->d1->handshake_read_seq == frag->msg_header.seq) {
508f5b1c8a1SJohn Marino unsigned long frag_len = frag->msg_header.frag_len;
509*de0e0e4dSAntonio Huete Jimenez pqueue_pop(s->d1->buffered_messages);
510f5b1c8a1SJohn Marino
511f5b1c8a1SJohn Marino al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
512f5b1c8a1SJohn Marino
513f5b1c8a1SJohn Marino if (al == 0) /* no alert */
514f5b1c8a1SJohn Marino {
51572c33676SMaxim Ag unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH;
516f5b1c8a1SJohn Marino memcpy(&p[frag->msg_header.frag_off],
517f5b1c8a1SJohn Marino frag->fragment, frag->msg_header.frag_len);
518f5b1c8a1SJohn Marino }
519f5b1c8a1SJohn Marino
520f5b1c8a1SJohn Marino dtls1_hm_fragment_free(frag);
521f5b1c8a1SJohn Marino pitem_free(item);
522f5b1c8a1SJohn Marino
523f5b1c8a1SJohn Marino if (al == 0) {
524f5b1c8a1SJohn Marino *ok = 1;
525f5b1c8a1SJohn Marino return frag_len;
526f5b1c8a1SJohn Marino }
527f5b1c8a1SJohn Marino
528f5b1c8a1SJohn Marino ssl3_send_alert(s, SSL3_AL_FATAL, al);
52972c33676SMaxim Ag s->internal->init_num = 0;
530f5b1c8a1SJohn Marino *ok = 0;
531f5b1c8a1SJohn Marino return -1;
532f5b1c8a1SJohn Marino } else
533f5b1c8a1SJohn Marino return 0;
534f5b1c8a1SJohn Marino }
535f5b1c8a1SJohn Marino
536f5b1c8a1SJohn Marino /*
537f5b1c8a1SJohn Marino * dtls1_max_handshake_message_len returns the maximum number of bytes
538f5b1c8a1SJohn Marino * permitted in a DTLS handshake message for |s|. The minimum is 16KB,
539f5b1c8a1SJohn Marino * but may be greater if the maximum certificate list size requires it.
540f5b1c8a1SJohn Marino */
541f5b1c8a1SJohn Marino static unsigned long
dtls1_max_handshake_message_len(const SSL * s)542f5b1c8a1SJohn Marino dtls1_max_handshake_message_len(const SSL *s)
543f5b1c8a1SJohn Marino {
544f5b1c8a1SJohn Marino unsigned long max_len;
545f5b1c8a1SJohn Marino
546f5b1c8a1SJohn Marino max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
54772c33676SMaxim Ag if (max_len < (unsigned long)s->internal->max_cert_list)
54872c33676SMaxim Ag return s->internal->max_cert_list;
549f5b1c8a1SJohn Marino return max_len;
550f5b1c8a1SJohn Marino }
551f5b1c8a1SJohn Marino
552f5b1c8a1SJohn Marino static int
dtls1_reassemble_fragment(SSL * s,struct hm_header_st * msg_hdr,int * ok)553f5b1c8a1SJohn Marino dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
554f5b1c8a1SJohn Marino {
555f5b1c8a1SJohn Marino hm_fragment *frag = NULL;
556f5b1c8a1SJohn Marino pitem *item = NULL;
557f5b1c8a1SJohn Marino int i = -1, is_complete;
558f5b1c8a1SJohn Marino unsigned char seq64be[8];
559f5b1c8a1SJohn Marino unsigned long frag_len = msg_hdr->frag_len;
560f5b1c8a1SJohn Marino
561f5b1c8a1SJohn Marino if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
562f5b1c8a1SJohn Marino msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
563f5b1c8a1SJohn Marino goto err;
564f5b1c8a1SJohn Marino
565f5b1c8a1SJohn Marino if (frag_len == 0) {
566f5b1c8a1SJohn Marino i = DTLS1_HM_FRAGMENT_RETRY;
567f5b1c8a1SJohn Marino goto err;
568f5b1c8a1SJohn Marino }
569f5b1c8a1SJohn Marino
570f5b1c8a1SJohn Marino /* Try to find item in queue */
571f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
572f5b1c8a1SJohn Marino seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
573f5b1c8a1SJohn Marino seq64be[7] = (unsigned char)msg_hdr->seq;
574*de0e0e4dSAntonio Huete Jimenez item = pqueue_find(s->d1->buffered_messages, seq64be);
575f5b1c8a1SJohn Marino
576f5b1c8a1SJohn Marino if (item == NULL) {
577f5b1c8a1SJohn Marino frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
578f5b1c8a1SJohn Marino if (frag == NULL)
579f5b1c8a1SJohn Marino goto err;
580f5b1c8a1SJohn Marino memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
581f5b1c8a1SJohn Marino frag->msg_header.frag_len = frag->msg_header.msg_len;
582f5b1c8a1SJohn Marino frag->msg_header.frag_off = 0;
583f5b1c8a1SJohn Marino } else {
584f5b1c8a1SJohn Marino frag = (hm_fragment*)item->data;
585f5b1c8a1SJohn Marino if (frag->msg_header.msg_len != msg_hdr->msg_len) {
586f5b1c8a1SJohn Marino item = NULL;
587f5b1c8a1SJohn Marino frag = NULL;
588f5b1c8a1SJohn Marino goto err;
589f5b1c8a1SJohn Marino }
590f5b1c8a1SJohn Marino }
591f5b1c8a1SJohn Marino
592f5b1c8a1SJohn Marino /*
593f5b1c8a1SJohn Marino * If message is already reassembled, this must be a
594f5b1c8a1SJohn Marino * retransmit and can be dropped.
595f5b1c8a1SJohn Marino */
596f5b1c8a1SJohn Marino if (frag->reassembly == NULL) {
597f5b1c8a1SJohn Marino unsigned char devnull [256];
598f5b1c8a1SJohn Marino
599f5b1c8a1SJohn Marino while (frag_len) {
600*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
601f5b1c8a1SJohn Marino devnull, frag_len > sizeof(devnull) ?
602f5b1c8a1SJohn Marino sizeof(devnull) : frag_len, 0);
603f5b1c8a1SJohn Marino if (i <= 0)
604f5b1c8a1SJohn Marino goto err;
605f5b1c8a1SJohn Marino frag_len -= i;
606f5b1c8a1SJohn Marino }
607f5b1c8a1SJohn Marino i = DTLS1_HM_FRAGMENT_RETRY;
608f5b1c8a1SJohn Marino goto err;
609f5b1c8a1SJohn Marino }
610f5b1c8a1SJohn Marino
611f5b1c8a1SJohn Marino /* read the body of the fragment (header has already been read */
612*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
613f5b1c8a1SJohn Marino frag->fragment + msg_hdr->frag_off, frag_len, 0);
614f5b1c8a1SJohn Marino if (i <= 0 || (unsigned long)i != frag_len)
615f5b1c8a1SJohn Marino goto err;
616f5b1c8a1SJohn Marino
617f5b1c8a1SJohn Marino RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
618f5b1c8a1SJohn Marino (long)(msg_hdr->frag_off + frag_len));
619f5b1c8a1SJohn Marino
620f5b1c8a1SJohn Marino RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
621f5b1c8a1SJohn Marino is_complete);
622f5b1c8a1SJohn Marino
623f5b1c8a1SJohn Marino if (is_complete) {
624f5b1c8a1SJohn Marino free(frag->reassembly);
625f5b1c8a1SJohn Marino frag->reassembly = NULL;
626f5b1c8a1SJohn Marino }
627f5b1c8a1SJohn Marino
628f5b1c8a1SJohn Marino if (item == NULL) {
629f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
630f5b1c8a1SJohn Marino seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
631f5b1c8a1SJohn Marino seq64be[7] = (unsigned char)(msg_hdr->seq);
632f5b1c8a1SJohn Marino
633f5b1c8a1SJohn Marino item = pitem_new(seq64be, frag);
634f5b1c8a1SJohn Marino if (item == NULL) {
635f5b1c8a1SJohn Marino i = -1;
636f5b1c8a1SJohn Marino goto err;
637f5b1c8a1SJohn Marino }
638f5b1c8a1SJohn Marino
639*de0e0e4dSAntonio Huete Jimenez pqueue_insert(s->d1->buffered_messages, item);
640f5b1c8a1SJohn Marino }
641f5b1c8a1SJohn Marino
642f5b1c8a1SJohn Marino return DTLS1_HM_FRAGMENT_RETRY;
643f5b1c8a1SJohn Marino
644f5b1c8a1SJohn Marino err:
645f5b1c8a1SJohn Marino if (item == NULL && frag != NULL)
646f5b1c8a1SJohn Marino dtls1_hm_fragment_free(frag);
647f5b1c8a1SJohn Marino *ok = 0;
648f5b1c8a1SJohn Marino return i;
649f5b1c8a1SJohn Marino }
650f5b1c8a1SJohn Marino
651f5b1c8a1SJohn Marino
652f5b1c8a1SJohn Marino static int
dtls1_process_out_of_seq_message(SSL * s,struct hm_header_st * msg_hdr,int * ok)653f5b1c8a1SJohn Marino dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
654f5b1c8a1SJohn Marino {
655f5b1c8a1SJohn Marino int i = -1;
656f5b1c8a1SJohn Marino hm_fragment *frag = NULL;
657f5b1c8a1SJohn Marino pitem *item = NULL;
658f5b1c8a1SJohn Marino unsigned char seq64be[8];
659f5b1c8a1SJohn Marino unsigned long frag_len = msg_hdr->frag_len;
660f5b1c8a1SJohn Marino
661f5b1c8a1SJohn Marino if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
662f5b1c8a1SJohn Marino goto err;
663f5b1c8a1SJohn Marino
664f5b1c8a1SJohn Marino /* Try to find item in queue, to prevent duplicate entries */
665f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
666f5b1c8a1SJohn Marino seq64be[6] = (unsigned char) (msg_hdr->seq >> 8);
667f5b1c8a1SJohn Marino seq64be[7] = (unsigned char) msg_hdr->seq;
668*de0e0e4dSAntonio Huete Jimenez item = pqueue_find(s->d1->buffered_messages, seq64be);
669f5b1c8a1SJohn Marino
670f5b1c8a1SJohn Marino /*
671f5b1c8a1SJohn Marino * If we already have an entry and this one is a fragment,
672f5b1c8a1SJohn Marino * don't discard it and rather try to reassemble it.
673f5b1c8a1SJohn Marino */
674f5b1c8a1SJohn Marino if (item != NULL && frag_len < msg_hdr->msg_len)
675f5b1c8a1SJohn Marino item = NULL;
676f5b1c8a1SJohn Marino
677f5b1c8a1SJohn Marino /*
678f5b1c8a1SJohn Marino * Discard the message if sequence number was already there, is
679f5b1c8a1SJohn Marino * too far in the future, already in the queue or if we received
680f5b1c8a1SJohn Marino * a FINISHED before the SERVER_HELLO, which then must be a stale
681f5b1c8a1SJohn Marino * retransmit.
682f5b1c8a1SJohn Marino */
683*de0e0e4dSAntonio Huete Jimenez if (msg_hdr->seq <= s->d1->handshake_read_seq ||
684*de0e0e4dSAntonio Huete Jimenez msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
685*de0e0e4dSAntonio Huete Jimenez (s->d1->handshake_read_seq == 0 &&
686f5b1c8a1SJohn Marino msg_hdr->type == SSL3_MT_FINISHED)) {
687f5b1c8a1SJohn Marino unsigned char devnull [256];
688f5b1c8a1SJohn Marino
689f5b1c8a1SJohn Marino while (frag_len) {
690*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
691f5b1c8a1SJohn Marino devnull, frag_len > sizeof(devnull) ?
692f5b1c8a1SJohn Marino sizeof(devnull) : frag_len, 0);
693f5b1c8a1SJohn Marino if (i <= 0)
694f5b1c8a1SJohn Marino goto err;
695f5b1c8a1SJohn Marino frag_len -= i;
696f5b1c8a1SJohn Marino }
697f5b1c8a1SJohn Marino } else {
698f5b1c8a1SJohn Marino if (frag_len < msg_hdr->msg_len)
699f5b1c8a1SJohn Marino return dtls1_reassemble_fragment(s, msg_hdr, ok);
700f5b1c8a1SJohn Marino
701f5b1c8a1SJohn Marino if (frag_len > dtls1_max_handshake_message_len(s))
702f5b1c8a1SJohn Marino goto err;
703f5b1c8a1SJohn Marino
704f5b1c8a1SJohn Marino frag = dtls1_hm_fragment_new(frag_len, 0);
705f5b1c8a1SJohn Marino if (frag == NULL)
706f5b1c8a1SJohn Marino goto err;
707f5b1c8a1SJohn Marino
708f5b1c8a1SJohn Marino memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
709f5b1c8a1SJohn Marino
710f5b1c8a1SJohn Marino if (frag_len) {
711f5b1c8a1SJohn Marino /* read the body of the fragment (header has already been read */
712*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
713f5b1c8a1SJohn Marino frag->fragment, frag_len, 0);
714f5b1c8a1SJohn Marino if (i <= 0 || (unsigned long)i != frag_len)
715f5b1c8a1SJohn Marino goto err;
716f5b1c8a1SJohn Marino }
717f5b1c8a1SJohn Marino
718f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
719f5b1c8a1SJohn Marino seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
720f5b1c8a1SJohn Marino seq64be[7] = (unsigned char)(msg_hdr->seq);
721f5b1c8a1SJohn Marino
722f5b1c8a1SJohn Marino item = pitem_new(seq64be, frag);
723f5b1c8a1SJohn Marino if (item == NULL)
724f5b1c8a1SJohn Marino goto err;
725f5b1c8a1SJohn Marino
726*de0e0e4dSAntonio Huete Jimenez pqueue_insert(s->d1->buffered_messages, item);
727f5b1c8a1SJohn Marino }
728f5b1c8a1SJohn Marino
729f5b1c8a1SJohn Marino return DTLS1_HM_FRAGMENT_RETRY;
730f5b1c8a1SJohn Marino
731f5b1c8a1SJohn Marino err:
732f5b1c8a1SJohn Marino if (item == NULL && frag != NULL)
733f5b1c8a1SJohn Marino dtls1_hm_fragment_free(frag);
734f5b1c8a1SJohn Marino *ok = 0;
735f5b1c8a1SJohn Marino return i;
736f5b1c8a1SJohn Marino }
737f5b1c8a1SJohn Marino
738f5b1c8a1SJohn Marino
739f5b1c8a1SJohn Marino static long
dtls1_get_message_fragment(SSL * s,int st1,int stn,long max,int * ok)740f5b1c8a1SJohn Marino dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
741f5b1c8a1SJohn Marino {
742f5b1c8a1SJohn Marino unsigned char wire[DTLS1_HM_HEADER_LENGTH];
743f5b1c8a1SJohn Marino unsigned long len, frag_off, frag_len;
744f5b1c8a1SJohn Marino struct hm_header_st msg_hdr;
745*de0e0e4dSAntonio Huete Jimenez int i, al;
746*de0e0e4dSAntonio Huete Jimenez CBS cbs;
747f5b1c8a1SJohn Marino
748f5b1c8a1SJohn Marino again:
749f5b1c8a1SJohn Marino /* see if we have the required fragment already */
750f5b1c8a1SJohn Marino if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) {
751f5b1c8a1SJohn Marino if (*ok)
75272c33676SMaxim Ag s->internal->init_num = frag_len;
753f5b1c8a1SJohn Marino return frag_len;
754f5b1c8a1SJohn Marino }
755f5b1c8a1SJohn Marino
756f5b1c8a1SJohn Marino /* read handshake message header */
757*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire,
758f5b1c8a1SJohn Marino DTLS1_HM_HEADER_LENGTH, 0);
759*de0e0e4dSAntonio Huete Jimenez if (i <= 0) {
760*de0e0e4dSAntonio Huete Jimenez /* nbio, or an error */
76172c33676SMaxim Ag s->internal->rwstate = SSL_READING;
762f5b1c8a1SJohn Marino *ok = 0;
763f5b1c8a1SJohn Marino return i;
764f5b1c8a1SJohn Marino }
765*de0e0e4dSAntonio Huete Jimenez
766*de0e0e4dSAntonio Huete Jimenez CBS_init(&cbs, wire, i);
767*de0e0e4dSAntonio Huete Jimenez if (!dtls1_get_message_header(&cbs, &msg_hdr)) {
768*de0e0e4dSAntonio Huete Jimenez /* Handshake fails if message header is incomplete. */
769f5b1c8a1SJohn Marino al = SSL_AD_UNEXPECTED_MESSAGE;
77072c33676SMaxim Ag SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
771*de0e0e4dSAntonio Huete Jimenez goto fatal_err;
772f5b1c8a1SJohn Marino }
773f5b1c8a1SJohn Marino
774f5b1c8a1SJohn Marino /*
775f5b1c8a1SJohn Marino * if this is a future (or stale) message it gets buffered
776f5b1c8a1SJohn Marino * (or dropped)--no further processing at this time
777f5b1c8a1SJohn Marino * While listening, we accept seq 1 (ClientHello with cookie)
778f5b1c8a1SJohn Marino * although we're still expecting seq 0 (ClientHello)
779f5b1c8a1SJohn Marino */
780*de0e0e4dSAntonio Huete Jimenez if (msg_hdr.seq != s->d1->handshake_read_seq &&
781*de0e0e4dSAntonio Huete Jimenez !(s->d1->listen && msg_hdr.seq == 1))
782f5b1c8a1SJohn Marino return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
783f5b1c8a1SJohn Marino
784f5b1c8a1SJohn Marino len = msg_hdr.msg_len;
785f5b1c8a1SJohn Marino frag_off = msg_hdr.frag_off;
786f5b1c8a1SJohn Marino frag_len = msg_hdr.frag_len;
787f5b1c8a1SJohn Marino
788f5b1c8a1SJohn Marino if (frag_len && frag_len < len)
789f5b1c8a1SJohn Marino return dtls1_reassemble_fragment(s, &msg_hdr, ok);
790f5b1c8a1SJohn Marino
791*de0e0e4dSAntonio Huete Jimenez if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
792f5b1c8a1SJohn Marino wire[0] == SSL3_MT_HELLO_REQUEST) {
793f5b1c8a1SJohn Marino /*
794f5b1c8a1SJohn Marino * The server may always send 'Hello Request' messages --
795f5b1c8a1SJohn Marino * we are doing a handshake anyway now, so ignore them
796f5b1c8a1SJohn Marino * if their format is correct. Does not count for
797f5b1c8a1SJohn Marino * 'Finished' MAC.
798f5b1c8a1SJohn Marino */
799f5b1c8a1SJohn Marino if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
80072c33676SMaxim Ag if (s->internal->msg_callback)
80172c33676SMaxim Ag s->internal->msg_callback(0, s->version,
802f5b1c8a1SJohn Marino SSL3_RT_HANDSHAKE, wire,
803f5b1c8a1SJohn Marino DTLS1_HM_HEADER_LENGTH, s,
80472c33676SMaxim Ag s->internal->msg_callback_arg);
805f5b1c8a1SJohn Marino
80672c33676SMaxim Ag s->internal->init_num = 0;
807f5b1c8a1SJohn Marino goto again;
808f5b1c8a1SJohn Marino }
809f5b1c8a1SJohn Marino else /* Incorrectly formated Hello request */
810f5b1c8a1SJohn Marino {
811f5b1c8a1SJohn Marino al = SSL_AD_UNEXPECTED_MESSAGE;
81272c33676SMaxim Ag SSLerror(s, SSL_R_UNEXPECTED_MESSAGE);
813*de0e0e4dSAntonio Huete Jimenez goto fatal_err;
814f5b1c8a1SJohn Marino }
815f5b1c8a1SJohn Marino }
816f5b1c8a1SJohn Marino
817f5b1c8a1SJohn Marino if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
818*de0e0e4dSAntonio Huete Jimenez goto fatal_err;
819f5b1c8a1SJohn Marino
820f5b1c8a1SJohn Marino /* XDTLS: ressurect this when restart is in place */
821*de0e0e4dSAntonio Huete Jimenez s->s3->hs.state = stn;
822f5b1c8a1SJohn Marino
823f5b1c8a1SJohn Marino if (frag_len > 0) {
82472c33676SMaxim Ag unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH;
825f5b1c8a1SJohn Marino
826*de0e0e4dSAntonio Huete Jimenez i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
827f5b1c8a1SJohn Marino &p[frag_off], frag_len, 0);
828f5b1c8a1SJohn Marino /* XDTLS: fix this--message fragments cannot span multiple packets */
829f5b1c8a1SJohn Marino if (i <= 0) {
83072c33676SMaxim Ag s->internal->rwstate = SSL_READING;
831f5b1c8a1SJohn Marino *ok = 0;
832f5b1c8a1SJohn Marino return i;
833f5b1c8a1SJohn Marino }
834f5b1c8a1SJohn Marino } else
835f5b1c8a1SJohn Marino i = 0;
836f5b1c8a1SJohn Marino
837f5b1c8a1SJohn Marino /*
838f5b1c8a1SJohn Marino * XDTLS: an incorrectly formatted fragment should cause the
839f5b1c8a1SJohn Marino * handshake to fail
840f5b1c8a1SJohn Marino */
841f5b1c8a1SJohn Marino if (i != (int)frag_len) {
842*de0e0e4dSAntonio Huete Jimenez al = SSL_AD_ILLEGAL_PARAMETER;
843*de0e0e4dSAntonio Huete Jimenez SSLerror(s, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER);
844*de0e0e4dSAntonio Huete Jimenez goto fatal_err;
845f5b1c8a1SJohn Marino }
846f5b1c8a1SJohn Marino
847f5b1c8a1SJohn Marino /*
84872c33676SMaxim Ag * Note that s->internal->init_num is *not* used as current offset in
84972c33676SMaxim Ag * s->internal->init_buf->data, but as a counter summing up fragments'
850f5b1c8a1SJohn Marino * lengths: as soon as they sum up to handshake packet
851f5b1c8a1SJohn Marino * length, we assume we have got all the fragments.
852f5b1c8a1SJohn Marino */
85372c33676SMaxim Ag s->internal->init_num = frag_len;
854*de0e0e4dSAntonio Huete Jimenez *ok = 1;
855f5b1c8a1SJohn Marino return frag_len;
856f5b1c8a1SJohn Marino
857*de0e0e4dSAntonio Huete Jimenez fatal_err:
858f5b1c8a1SJohn Marino ssl3_send_alert(s, SSL3_AL_FATAL, al);
85972c33676SMaxim Ag s->internal->init_num = 0;
860f5b1c8a1SJohn Marino
861f5b1c8a1SJohn Marino *ok = 0;
862f5b1c8a1SJohn Marino return (-1);
863f5b1c8a1SJohn Marino }
864f5b1c8a1SJohn Marino
865f5b1c8a1SJohn Marino int
dtls1_read_failed(SSL * s,int code)866f5b1c8a1SJohn Marino dtls1_read_failed(SSL *s, int code)
867f5b1c8a1SJohn Marino {
868f5b1c8a1SJohn Marino if (code > 0) {
869f5b1c8a1SJohn Marino #ifdef DEBUG
870f5b1c8a1SJohn Marino fprintf(stderr, "invalid state reached %s:%d",
871f5b1c8a1SJohn Marino __FILE__, __LINE__);
872f5b1c8a1SJohn Marino #endif
873f5b1c8a1SJohn Marino return 1;
874f5b1c8a1SJohn Marino }
875f5b1c8a1SJohn Marino
876f5b1c8a1SJohn Marino if (!dtls1_is_timer_expired(s)) {
877f5b1c8a1SJohn Marino /*
878f5b1c8a1SJohn Marino * not a timeout, none of our business, let higher layers
879f5b1c8a1SJohn Marino * handle this. in fact it's probably an error
880f5b1c8a1SJohn Marino */
881f5b1c8a1SJohn Marino return code;
882f5b1c8a1SJohn Marino }
883f5b1c8a1SJohn Marino
884f5b1c8a1SJohn Marino if (!SSL_in_init(s)) /* done, no need to send a retransmit */
885f5b1c8a1SJohn Marino {
886f5b1c8a1SJohn Marino BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
887f5b1c8a1SJohn Marino return code;
888f5b1c8a1SJohn Marino }
889f5b1c8a1SJohn Marino
890f5b1c8a1SJohn Marino return dtls1_handle_timeout(s);
891f5b1c8a1SJohn Marino }
892f5b1c8a1SJohn Marino
893f5b1c8a1SJohn Marino int
dtls1_get_queue_priority(unsigned short seq,int is_ccs)894f5b1c8a1SJohn Marino dtls1_get_queue_priority(unsigned short seq, int is_ccs)
895f5b1c8a1SJohn Marino {
896f5b1c8a1SJohn Marino /*
897f5b1c8a1SJohn Marino * The index of the retransmission queue actually is the message
898f5b1c8a1SJohn Marino * sequence number, since the queue only contains messages of a
899f5b1c8a1SJohn Marino * single handshake. However, the ChangeCipherSpec has no message
900f5b1c8a1SJohn Marino * sequence number and so using only the sequence will result in
901f5b1c8a1SJohn Marino * the CCS and Finished having the same index. To prevent this, the
902f5b1c8a1SJohn Marino * sequence number is multiplied by 2. In case of a CCS 1 is
903f5b1c8a1SJohn Marino * subtracted. This does not only differ CSS and Finished, it also
904f5b1c8a1SJohn Marino * maintains the order of the index (important for priority queues)
905f5b1c8a1SJohn Marino * and fits in the unsigned short variable.
906f5b1c8a1SJohn Marino */
907f5b1c8a1SJohn Marino return seq * 2 - is_ccs;
908f5b1c8a1SJohn Marino }
909f5b1c8a1SJohn Marino
910f5b1c8a1SJohn Marino int
dtls1_retransmit_buffered_messages(SSL * s)911f5b1c8a1SJohn Marino dtls1_retransmit_buffered_messages(SSL *s)
912f5b1c8a1SJohn Marino {
913f5b1c8a1SJohn Marino pqueue sent = s->d1->sent_messages;
914f5b1c8a1SJohn Marino piterator iter;
915f5b1c8a1SJohn Marino pitem *item;
916f5b1c8a1SJohn Marino hm_fragment *frag;
917f5b1c8a1SJohn Marino int found = 0;
918f5b1c8a1SJohn Marino
919f5b1c8a1SJohn Marino iter = pqueue_iterator(sent);
920f5b1c8a1SJohn Marino
921f5b1c8a1SJohn Marino for (item = pqueue_next(&iter); item != NULL;
922f5b1c8a1SJohn Marino item = pqueue_next(&iter)) {
923f5b1c8a1SJohn Marino frag = (hm_fragment *)item->data;
924f5b1c8a1SJohn Marino if (dtls1_retransmit_message(s,
925f5b1c8a1SJohn Marino (unsigned short)dtls1_get_queue_priority(
926f5b1c8a1SJohn Marino frag->msg_header.seq, frag->msg_header.is_ccs), 0,
927f5b1c8a1SJohn Marino &found) <= 0 && found) {
928f5b1c8a1SJohn Marino #ifdef DEBUG
929f5b1c8a1SJohn Marino fprintf(stderr, "dtls1_retransmit_message() failed\n");
930f5b1c8a1SJohn Marino #endif
931f5b1c8a1SJohn Marino return -1;
932f5b1c8a1SJohn Marino }
933f5b1c8a1SJohn Marino }
934f5b1c8a1SJohn Marino
935f5b1c8a1SJohn Marino return 1;
936f5b1c8a1SJohn Marino }
937f5b1c8a1SJohn Marino
938f5b1c8a1SJohn Marino int
dtls1_buffer_message(SSL * s,int is_ccs)939f5b1c8a1SJohn Marino dtls1_buffer_message(SSL *s, int is_ccs)
940f5b1c8a1SJohn Marino {
941f5b1c8a1SJohn Marino pitem *item;
942f5b1c8a1SJohn Marino hm_fragment *frag;
943f5b1c8a1SJohn Marino unsigned char seq64be[8];
944f5b1c8a1SJohn Marino
945f5b1c8a1SJohn Marino /* Buffer the messsage in order to handle DTLS retransmissions. */
946f5b1c8a1SJohn Marino
947f5b1c8a1SJohn Marino /*
948f5b1c8a1SJohn Marino * This function is called immediately after a message has
949f5b1c8a1SJohn Marino * been serialized
950f5b1c8a1SJohn Marino */
95172c33676SMaxim Ag OPENSSL_assert(s->internal->init_off == 0);
952f5b1c8a1SJohn Marino
95372c33676SMaxim Ag frag = dtls1_hm_fragment_new(s->internal->init_num, 0);
954f5b1c8a1SJohn Marino if (frag == NULL)
955f5b1c8a1SJohn Marino return 0;
956f5b1c8a1SJohn Marino
95772c33676SMaxim Ag memcpy(frag->fragment, s->internal->init_buf->data, s->internal->init_num);
958f5b1c8a1SJohn Marino
959*de0e0e4dSAntonio Huete Jimenez OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
960*de0e0e4dSAntonio Huete Jimenez (is_ccs ? DTLS1_CCS_HEADER_LENGTH : DTLS1_HM_HEADER_LENGTH) ==
961*de0e0e4dSAntonio Huete Jimenez (unsigned int)s->internal->init_num);
962f5b1c8a1SJohn Marino
963*de0e0e4dSAntonio Huete Jimenez frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
964*de0e0e4dSAntonio Huete Jimenez frag->msg_header.seq = s->d1->w_msg_hdr.seq;
965*de0e0e4dSAntonio Huete Jimenez frag->msg_header.type = s->d1->w_msg_hdr.type;
966f5b1c8a1SJohn Marino frag->msg_header.frag_off = 0;
967*de0e0e4dSAntonio Huete Jimenez frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
968f5b1c8a1SJohn Marino frag->msg_header.is_ccs = is_ccs;
969f5b1c8a1SJohn Marino
970f5b1c8a1SJohn Marino /* save current state*/
971f5b1c8a1SJohn Marino frag->msg_header.saved_retransmit_state.session = s->session;
972*de0e0e4dSAntonio Huete Jimenez frag->msg_header.saved_retransmit_state.epoch =
973*de0e0e4dSAntonio Huete Jimenez tls12_record_layer_write_epoch(s->internal->rl);
974f5b1c8a1SJohn Marino
975f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
976f5b1c8a1SJohn Marino seq64be[6] = (unsigned char)(dtls1_get_queue_priority(
977f5b1c8a1SJohn Marino frag->msg_header.seq, frag->msg_header.is_ccs) >> 8);
978f5b1c8a1SJohn Marino seq64be[7] = (unsigned char)(dtls1_get_queue_priority(
979f5b1c8a1SJohn Marino frag->msg_header.seq, frag->msg_header.is_ccs));
980f5b1c8a1SJohn Marino
981f5b1c8a1SJohn Marino item = pitem_new(seq64be, frag);
982f5b1c8a1SJohn Marino if (item == NULL) {
983f5b1c8a1SJohn Marino dtls1_hm_fragment_free(frag);
984f5b1c8a1SJohn Marino return 0;
985f5b1c8a1SJohn Marino }
986f5b1c8a1SJohn Marino
987f5b1c8a1SJohn Marino pqueue_insert(s->d1->sent_messages, item);
988f5b1c8a1SJohn Marino return 1;
989f5b1c8a1SJohn Marino }
990f5b1c8a1SJohn Marino
991f5b1c8a1SJohn Marino int
dtls1_retransmit_message(SSL * s,unsigned short seq,unsigned long frag_off,int * found)992f5b1c8a1SJohn Marino dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
993f5b1c8a1SJohn Marino int *found)
994f5b1c8a1SJohn Marino {
995f5b1c8a1SJohn Marino int ret;
996f5b1c8a1SJohn Marino /* XDTLS: for now assuming that read/writes are blocking */
997f5b1c8a1SJohn Marino pitem *item;
998f5b1c8a1SJohn Marino hm_fragment *frag;
999f5b1c8a1SJohn Marino unsigned long header_length;
1000f5b1c8a1SJohn Marino unsigned char seq64be[8];
1001f5b1c8a1SJohn Marino struct dtls1_retransmit_state saved_state;
1002f5b1c8a1SJohn Marino
1003f5b1c8a1SJohn Marino /*
100472c33676SMaxim Ag OPENSSL_assert(s->internal->init_num == 0);
100572c33676SMaxim Ag OPENSSL_assert(s->internal->init_off == 0);
1006f5b1c8a1SJohn Marino */
1007f5b1c8a1SJohn Marino
1008f5b1c8a1SJohn Marino /* XDTLS: the requested message ought to be found, otherwise error */
1009f5b1c8a1SJohn Marino memset(seq64be, 0, sizeof(seq64be));
1010f5b1c8a1SJohn Marino seq64be[6] = (unsigned char)(seq >> 8);
1011f5b1c8a1SJohn Marino seq64be[7] = (unsigned char)seq;
1012f5b1c8a1SJohn Marino
1013f5b1c8a1SJohn Marino item = pqueue_find(s->d1->sent_messages, seq64be);
1014f5b1c8a1SJohn Marino if (item == NULL) {
1015f5b1c8a1SJohn Marino #ifdef DEBUG
101672c33676SMaxim Ag fprintf(stderr, "retransmit: message %d non-existent\n", seq);
1017f5b1c8a1SJohn Marino #endif
1018f5b1c8a1SJohn Marino *found = 0;
1019f5b1c8a1SJohn Marino return 0;
1020f5b1c8a1SJohn Marino }
1021f5b1c8a1SJohn Marino
1022f5b1c8a1SJohn Marino *found = 1;
1023f5b1c8a1SJohn Marino frag = (hm_fragment *)item->data;
1024f5b1c8a1SJohn Marino
1025f5b1c8a1SJohn Marino if (frag->msg_header.is_ccs)
1026f5b1c8a1SJohn Marino header_length = DTLS1_CCS_HEADER_LENGTH;
1027f5b1c8a1SJohn Marino else
1028f5b1c8a1SJohn Marino header_length = DTLS1_HM_HEADER_LENGTH;
1029f5b1c8a1SJohn Marino
103072c33676SMaxim Ag memcpy(s->internal->init_buf->data, frag->fragment,
1031f5b1c8a1SJohn Marino frag->msg_header.msg_len + header_length);
103272c33676SMaxim Ag s->internal->init_num = frag->msg_header.msg_len + header_length;
1033f5b1c8a1SJohn Marino
1034f5b1c8a1SJohn Marino dtls1_set_message_header_int(s, frag->msg_header.type,
1035f5b1c8a1SJohn Marino frag->msg_header.msg_len, frag->msg_header.seq, 0,
1036f5b1c8a1SJohn Marino frag->msg_header.frag_len);
1037f5b1c8a1SJohn Marino
1038f5b1c8a1SJohn Marino /* save current state */
1039f5b1c8a1SJohn Marino saved_state.session = s->session;
1040*de0e0e4dSAntonio Huete Jimenez saved_state.epoch = tls12_record_layer_write_epoch(s->internal->rl);
1041f5b1c8a1SJohn Marino
1042*de0e0e4dSAntonio Huete Jimenez s->d1->retransmitting = 1;
1043f5b1c8a1SJohn Marino
1044f5b1c8a1SJohn Marino /* restore state in which the message was originally sent */
1045f5b1c8a1SJohn Marino s->session = frag->msg_header.saved_retransmit_state.session;
1046*de0e0e4dSAntonio Huete Jimenez if (!tls12_record_layer_use_write_epoch(s->internal->rl,
1047*de0e0e4dSAntonio Huete Jimenez frag->msg_header.saved_retransmit_state.epoch))
10482eb7d3b8SDaniel Fojt return 0;
1049f5b1c8a1SJohn Marino
1050f5b1c8a1SJohn Marino ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
1051f5b1c8a1SJohn Marino SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
1052f5b1c8a1SJohn Marino
1053f5b1c8a1SJohn Marino /* restore current state */
1054f5b1c8a1SJohn Marino s->session = saved_state.session;
1055*de0e0e4dSAntonio Huete Jimenez if (!tls12_record_layer_use_write_epoch(s->internal->rl,
1056*de0e0e4dSAntonio Huete Jimenez saved_state.epoch))
10572eb7d3b8SDaniel Fojt return 0;
1058f5b1c8a1SJohn Marino
1059*de0e0e4dSAntonio Huete Jimenez s->d1->retransmitting = 0;
1060f5b1c8a1SJohn Marino
1061f5b1c8a1SJohn Marino (void)BIO_flush(SSL_get_wbio(s));
1062f5b1c8a1SJohn Marino return ret;
1063f5b1c8a1SJohn Marino }
1064f5b1c8a1SJohn Marino
1065f5b1c8a1SJohn Marino /* call this function when the buffered messages are no longer needed */
1066f5b1c8a1SJohn Marino void
dtls1_clear_record_buffer(SSL * s)1067f5b1c8a1SJohn Marino dtls1_clear_record_buffer(SSL *s)
1068f5b1c8a1SJohn Marino {
1069*de0e0e4dSAntonio Huete Jimenez hm_fragment *frag;
1070f5b1c8a1SJohn Marino pitem *item;
1071f5b1c8a1SJohn Marino
1072f5b1c8a1SJohn Marino for(item = pqueue_pop(s->d1->sent_messages); item != NULL;
1073f5b1c8a1SJohn Marino item = pqueue_pop(s->d1->sent_messages)) {
1074*de0e0e4dSAntonio Huete Jimenez frag = item->data;
1075*de0e0e4dSAntonio Huete Jimenez if (frag->msg_header.is_ccs)
1076*de0e0e4dSAntonio Huete Jimenez tls12_record_layer_write_epoch_done(s->internal->rl,
1077*de0e0e4dSAntonio Huete Jimenez frag->msg_header.saved_retransmit_state.epoch);
1078*de0e0e4dSAntonio Huete Jimenez dtls1_hm_fragment_free(frag);
1079f5b1c8a1SJohn Marino pitem_free(item);
1080f5b1c8a1SJohn Marino }
1081f5b1c8a1SJohn Marino }
1082f5b1c8a1SJohn Marino
108372c33676SMaxim Ag void
dtls1_set_message_header(SSL * s,unsigned char mt,unsigned long len,unsigned long frag_off,unsigned long frag_len)108472c33676SMaxim Ag dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len,
108572c33676SMaxim Ag unsigned long frag_off, unsigned long frag_len)
1086f5b1c8a1SJohn Marino {
1087f5b1c8a1SJohn Marino /* Don't change sequence numbers while listening */
1088*de0e0e4dSAntonio Huete Jimenez if (frag_off == 0 && !s->d1->listen) {
1089*de0e0e4dSAntonio Huete Jimenez s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
1090*de0e0e4dSAntonio Huete Jimenez s->d1->next_handshake_write_seq++;
1091f5b1c8a1SJohn Marino }
1092f5b1c8a1SJohn Marino
1093*de0e0e4dSAntonio Huete Jimenez dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
1094f5b1c8a1SJohn Marino frag_off, frag_len);
1095f5b1c8a1SJohn Marino }
1096f5b1c8a1SJohn Marino
1097f5b1c8a1SJohn Marino /* don't actually do the writing, wait till the MTU has been retrieved */
109872c33676SMaxim Ag void
dtls1_set_message_header_int(SSL * s,unsigned char mt,unsigned long len,unsigned short seq_num,unsigned long frag_off,unsigned long frag_len)1099f5b1c8a1SJohn Marino dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len,
1100f5b1c8a1SJohn Marino unsigned short seq_num, unsigned long frag_off, unsigned long frag_len)
1101f5b1c8a1SJohn Marino {
1102*de0e0e4dSAntonio Huete Jimenez struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
1103f5b1c8a1SJohn Marino
1104f5b1c8a1SJohn Marino msg_hdr->type = mt;
1105f5b1c8a1SJohn Marino msg_hdr->msg_len = len;
1106f5b1c8a1SJohn Marino msg_hdr->seq = seq_num;
1107f5b1c8a1SJohn Marino msg_hdr->frag_off = frag_off;
1108f5b1c8a1SJohn Marino msg_hdr->frag_len = frag_len;
1109f5b1c8a1SJohn Marino }
1110f5b1c8a1SJohn Marino
1111f5b1c8a1SJohn Marino static void
dtls1_fix_message_header(SSL * s,unsigned long frag_off,unsigned long frag_len)1112f5b1c8a1SJohn Marino dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len)
1113f5b1c8a1SJohn Marino {
1114*de0e0e4dSAntonio Huete Jimenez struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
1115f5b1c8a1SJohn Marino
1116f5b1c8a1SJohn Marino msg_hdr->frag_off = frag_off;
1117f5b1c8a1SJohn Marino msg_hdr->frag_len = frag_len;
1118f5b1c8a1SJohn Marino }
1119f5b1c8a1SJohn Marino
112072c33676SMaxim Ag static int
dtls1_write_message_header(const struct hm_header_st * msg_hdr,unsigned long frag_off,unsigned long frag_len,unsigned char * p)112172c33676SMaxim Ag dtls1_write_message_header(const struct hm_header_st *msg_hdr,
112272c33676SMaxim Ag unsigned long frag_off, unsigned long frag_len, unsigned char *p)
1123f5b1c8a1SJohn Marino {
112472c33676SMaxim Ag CBB cbb;
1125f5b1c8a1SJohn Marino
112672c33676SMaxim Ag /* We assume DTLS1_HM_HEADER_LENGTH bytes are available for now... */
112772c33676SMaxim Ag if (!CBB_init_fixed(&cbb, p, DTLS1_HM_HEADER_LENGTH))
112872c33676SMaxim Ag return 0;
112972c33676SMaxim Ag if (!CBB_add_u8(&cbb, msg_hdr->type))
113072c33676SMaxim Ag goto err;
113172c33676SMaxim Ag if (!CBB_add_u24(&cbb, msg_hdr->msg_len))
113272c33676SMaxim Ag goto err;
113372c33676SMaxim Ag if (!CBB_add_u16(&cbb, msg_hdr->seq))
113472c33676SMaxim Ag goto err;
113572c33676SMaxim Ag if (!CBB_add_u24(&cbb, frag_off))
113672c33676SMaxim Ag goto err;
113772c33676SMaxim Ag if (!CBB_add_u24(&cbb, frag_len))
113872c33676SMaxim Ag goto err;
113972c33676SMaxim Ag if (!CBB_finish(&cbb, NULL, NULL))
114072c33676SMaxim Ag goto err;
1141f5b1c8a1SJohn Marino
114272c33676SMaxim Ag return 1;
1143f5b1c8a1SJohn Marino
114472c33676SMaxim Ag err:
114572c33676SMaxim Ag CBB_cleanup(&cbb);
114672c33676SMaxim Ag return 0;
1147f5b1c8a1SJohn Marino }
1148f5b1c8a1SJohn Marino
1149f5b1c8a1SJohn Marino unsigned int
dtls1_min_mtu(void)1150f5b1c8a1SJohn Marino dtls1_min_mtu(void)
1151f5b1c8a1SJohn Marino {
1152f5b1c8a1SJohn Marino return (g_probable_mtu[(sizeof(g_probable_mtu) /
1153f5b1c8a1SJohn Marino sizeof(g_probable_mtu[0])) - 1]);
1154f5b1c8a1SJohn Marino }
1155f5b1c8a1SJohn Marino
1156f5b1c8a1SJohn Marino static unsigned int
dtls1_guess_mtu(unsigned int curr_mtu)1157f5b1c8a1SJohn Marino dtls1_guess_mtu(unsigned int curr_mtu)
1158f5b1c8a1SJohn Marino {
1159f5b1c8a1SJohn Marino unsigned int i;
1160f5b1c8a1SJohn Marino
1161f5b1c8a1SJohn Marino if (curr_mtu == 0)
1162f5b1c8a1SJohn Marino return g_probable_mtu[0];
1163f5b1c8a1SJohn Marino
1164f5b1c8a1SJohn Marino for (i = 0; i < sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0]); i++)
1165f5b1c8a1SJohn Marino if (curr_mtu > g_probable_mtu[i])
1166f5b1c8a1SJohn Marino return g_probable_mtu[i];
1167f5b1c8a1SJohn Marino
1168f5b1c8a1SJohn Marino return curr_mtu;
1169f5b1c8a1SJohn Marino }
1170f5b1c8a1SJohn Marino
1171f5b1c8a1SJohn Marino int
dtls1_get_message_header(CBS * header,struct hm_header_st * msg_hdr)1172*de0e0e4dSAntonio Huete Jimenez dtls1_get_message_header(CBS *header, struct hm_header_st *msg_hdr)
1173f5b1c8a1SJohn Marino {
1174f5b1c8a1SJohn Marino uint32_t msg_len, frag_off, frag_len;
1175f5b1c8a1SJohn Marino uint16_t seq;
1176f5b1c8a1SJohn Marino uint8_t type;
1177f5b1c8a1SJohn Marino
1178f5b1c8a1SJohn Marino memset(msg_hdr, 0, sizeof(*msg_hdr));
1179f5b1c8a1SJohn Marino
1180*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_u8(header, &type))
1181f5b1c8a1SJohn Marino return 0;
1182*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_u24(header, &msg_len))
1183f5b1c8a1SJohn Marino return 0;
1184*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_u16(header, &seq))
1185f5b1c8a1SJohn Marino return 0;
1186*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_u24(header, &frag_off))
1187f5b1c8a1SJohn Marino return 0;
1188*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_u24(header, &frag_len))
1189f5b1c8a1SJohn Marino return 0;
1190f5b1c8a1SJohn Marino
1191f5b1c8a1SJohn Marino msg_hdr->type = type;
1192f5b1c8a1SJohn Marino msg_hdr->msg_len = msg_len;
1193f5b1c8a1SJohn Marino msg_hdr->seq = seq;
1194f5b1c8a1SJohn Marino msg_hdr->frag_off = frag_off;
1195f5b1c8a1SJohn Marino msg_hdr->frag_len = frag_len;
1196f5b1c8a1SJohn Marino
1197f5b1c8a1SJohn Marino return 1;
1198f5b1c8a1SJohn Marino }
1199