1160814Ssimon/* ssl/d1_both.c */
2296341Sdelphij/*
3160814Ssimon * DTLS implementation written by Nagendra Modadugu
4296341Sdelphij * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5160814Ssimon */
6160814Ssimon/* ====================================================================
7160814Ssimon * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
8160814Ssimon *
9160814Ssimon * Redistribution and use in source and binary forms, with or without
10160814Ssimon * modification, are permitted provided that the following conditions
11160814Ssimon * are met:
12160814Ssimon *
13160814Ssimon * 1. Redistributions of source code must retain the above copyright
14296341Sdelphij *    notice, this list of conditions and the following disclaimer.
15160814Ssimon *
16160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
17160814Ssimon *    notice, this list of conditions and the following disclaimer in
18160814Ssimon *    the documentation and/or other materials provided with the
19160814Ssimon *    distribution.
20160814Ssimon *
21160814Ssimon * 3. All advertising materials mentioning features or use of this
22160814Ssimon *    software must display the following acknowledgment:
23160814Ssimon *    "This product includes software developed by the OpenSSL Project
24160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25160814Ssimon *
26160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27160814Ssimon *    endorse or promote products derived from this software without
28160814Ssimon *    prior written permission. For written permission, please contact
29160814Ssimon *    openssl-core@openssl.org.
30160814Ssimon *
31160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
32160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
33160814Ssimon *    permission of the OpenSSL Project.
34160814Ssimon *
35160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
36160814Ssimon *    acknowledgment:
37160814Ssimon *    "This product includes software developed by the OpenSSL Project
38160814Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39160814Ssimon *
40160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
52160814Ssimon * ====================================================================
53160814Ssimon *
54160814Ssimon * This product includes cryptographic software written by Eric Young
55160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
56160814Ssimon * Hudson (tjh@cryptsoft.com).
57160814Ssimon *
58160814Ssimon */
59160814Ssimon/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
60160814Ssimon * All rights reserved.
61160814Ssimon *
62160814Ssimon * This package is an SSL implementation written
63160814Ssimon * by Eric Young (eay@cryptsoft.com).
64160814Ssimon * The implementation was written so as to conform with Netscapes SSL.
65296341Sdelphij *
66160814Ssimon * This library is free for commercial and non-commercial use as long as
67160814Ssimon * the following conditions are aheared to.  The following conditions
68160814Ssimon * apply to all code found in this distribution, be it the RC4, RSA,
69160814Ssimon * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
70160814Ssimon * included with this distribution is covered by the same copyright terms
71160814Ssimon * except that the holder is Tim Hudson (tjh@cryptsoft.com).
72296341Sdelphij *
73160814Ssimon * Copyright remains Eric Young's, and as such any Copyright notices in
74160814Ssimon * the code are not to be removed.
75160814Ssimon * If this package is used in a product, Eric Young should be given attribution
76160814Ssimon * as the author of the parts of the library used.
77160814Ssimon * This can be in the form of a textual message at program startup or
78160814Ssimon * in documentation (online or textual) provided with the package.
79296341Sdelphij *
80160814Ssimon * Redistribution and use in source and binary forms, with or without
81160814Ssimon * modification, are permitted provided that the following conditions
82160814Ssimon * are met:
83160814Ssimon * 1. Redistributions of source code must retain the copyright
84160814Ssimon *    notice, this list of conditions and the following disclaimer.
85160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
86160814Ssimon *    notice, this list of conditions and the following disclaimer in the
87160814Ssimon *    documentation and/or other materials provided with the distribution.
88160814Ssimon * 3. All advertising materials mentioning features or use of this software
89160814Ssimon *    must display the following acknowledgement:
90160814Ssimon *    "This product includes cryptographic software written by
91160814Ssimon *     Eric Young (eay@cryptsoft.com)"
92160814Ssimon *    The word 'cryptographic' can be left out if the rouines from the library
93160814Ssimon *    being used are not cryptographic related :-).
94296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
95160814Ssimon *    the apps directory (application code) you must include an acknowledgement:
96160814Ssimon *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
97296341Sdelphij *
98160814Ssimon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
99160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
101160814Ssimon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
102160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
103160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
104160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
106160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
107160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
108160814Ssimon * SUCH DAMAGE.
109296341Sdelphij *
110160814Ssimon * The licence and distribution terms for any publically available version or
111160814Ssimon * derivative of this code cannot be changed.  i.e. this code cannot simply be
112160814Ssimon * copied and put under another distribution licence
113160814Ssimon * [including the GNU Public Licence.]
114160814Ssimon */
115160814Ssimon
116160814Ssimon#include <limits.h>
117160814Ssimon#include <string.h>
118160814Ssimon#include <stdio.h>
119160814Ssimon#include "ssl_locl.h"
120160814Ssimon#include <openssl/buffer.h>
121160814Ssimon#include <openssl/rand.h>
122160814Ssimon#include <openssl/objects.h>
123160814Ssimon#include <openssl/evp.h>
124160814Ssimon#include <openssl/x509.h>
125160814Ssimon
126215697Ssimon#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
127160814Ssimon
128215697Ssimon#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
129296341Sdelphij                        if ((end) - (start) <= 8) { \
130296341Sdelphij                                long ii; \
131296341Sdelphij                                for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
132296341Sdelphij                        } else { \
133296341Sdelphij                                long ii; \
134296341Sdelphij                                bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
135296341Sdelphij                                for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
136296341Sdelphij                                bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
137296341Sdelphij                        } }
138215697Ssimon
139215697Ssimon#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
140296341Sdelphij                        long ii; \
141296341Sdelphij                        OPENSSL_assert((msg_len) > 0); \
142296341Sdelphij                        is_complete = 1; \
143296341Sdelphij                        if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
144296341Sdelphij                        if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
145296341Sdelphij                                if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
146215697Ssimon
147215697Ssimon#if 0
148296341Sdelphij# define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
149296341Sdelphij                        long ii; \
150296341Sdelphij                        printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
151296341Sdelphij                        printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
152296341Sdelphij                        printf("\n"); }
153215697Ssimon#endif
154215697Ssimon
155296341Sdelphijstatic unsigned char bitmask_start_values[] =
156296341Sdelphij    { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
157296341Sdelphijstatic unsigned char bitmask_end_values[] =
158296341Sdelphij    { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
159215697Ssimon
160160814Ssimon/* XDTLS:  figure out the right values */
161296341Sdelphijstatic const unsigned int g_probable_mtu[] = { 1500, 512, 256 };
162160814Ssimon
163296341Sdelphijstatic void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
164296341Sdelphij                                     unsigned long frag_len);
165296341Sdelphijstatic unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
166160814Ssimonstatic void dtls1_set_message_header_int(SSL *s, unsigned char mt,
167296341Sdelphij                                         unsigned long len,
168296341Sdelphij                                         unsigned short seq_num,
169296341Sdelphij                                         unsigned long frag_off,
170296341Sdelphij                                         unsigned long frag_len);
171296341Sdelphijstatic long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max,
172296341Sdelphij                                       int *ok);
173160814Ssimon
174296341Sdelphijstatic hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
175296341Sdelphij                                          int reassembly)
176296341Sdelphij{
177296341Sdelphij    hm_fragment *frag = NULL;
178296341Sdelphij    unsigned char *buf = NULL;
179296341Sdelphij    unsigned char *bitmask = NULL;
180160814Ssimon
181296341Sdelphij    frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
182296341Sdelphij    if (frag == NULL)
183296341Sdelphij        return NULL;
184160814Ssimon
185296341Sdelphij    if (frag_len) {
186296341Sdelphij        buf = (unsigned char *)OPENSSL_malloc(frag_len);
187296341Sdelphij        if (buf == NULL) {
188296341Sdelphij            OPENSSL_free(frag);
189296341Sdelphij            return NULL;
190296341Sdelphij        }
191296341Sdelphij    }
192160814Ssimon
193296341Sdelphij    /* zero length fragment gets zero frag->fragment */
194296341Sdelphij    frag->fragment = buf;
195160814Ssimon
196296341Sdelphij    /* Initialize reassembly bitmask if necessary */
197296341Sdelphij    if (reassembly) {
198296341Sdelphij        bitmask =
199296341Sdelphij            (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
200296341Sdelphij        if (bitmask == NULL) {
201296341Sdelphij            if (buf != NULL)
202296341Sdelphij                OPENSSL_free(buf);
203296341Sdelphij            OPENSSL_free(frag);
204296341Sdelphij            return NULL;
205296341Sdelphij        }
206296341Sdelphij        memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
207296341Sdelphij    }
208215697Ssimon
209296341Sdelphij    frag->reassembly = bitmask;
210215697Ssimon
211296341Sdelphij    return frag;
212296341Sdelphij}
213172767Ssimon
214279264Sdelphijvoid dtls1_hm_fragment_free(hm_fragment *frag)
215296341Sdelphij{
216260404Sdelphij
217296341Sdelphij    if (frag->msg_header.is_ccs) {
218296341Sdelphij        EVP_CIPHER_CTX_free(frag->msg_header.
219296341Sdelphij                            saved_retransmit_state.enc_write_ctx);
220296341Sdelphij        EVP_MD_CTX_destroy(frag->msg_header.
221296341Sdelphij                           saved_retransmit_state.write_hash);
222296341Sdelphij    }
223296341Sdelphij    if (frag->fragment)
224296341Sdelphij        OPENSSL_free(frag->fragment);
225296341Sdelphij    if (frag->reassembly)
226296341Sdelphij        OPENSSL_free(frag->reassembly);
227296341Sdelphij    OPENSSL_free(frag);
228296341Sdelphij}
229160814Ssimon
230279264Sdelphijstatic int dtls1_query_mtu(SSL *s)
231279264Sdelphij{
232296341Sdelphij    if (s->d1->link_mtu) {
233296341Sdelphij        s->d1->mtu =
234296341Sdelphij            s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
235296341Sdelphij        s->d1->link_mtu = 0;
236296341Sdelphij    }
237160814Ssimon
238296341Sdelphij    /* AHA!  Figure out the MTU, and stick to the right size */
239296341Sdelphij    if (s->d1->mtu < dtls1_min_mtu(s)) {
240296341Sdelphij        if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
241296341Sdelphij            s->d1->mtu =
242296341Sdelphij                BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
243160814Ssimon
244296341Sdelphij            /*
245296341Sdelphij             * I've seen the kernel return bogus numbers when it doesn't know
246296341Sdelphij             * (initial write), so just make sure we have a reasonable number
247296341Sdelphij             */
248296341Sdelphij            if (s->d1->mtu < dtls1_min_mtu(s)) {
249296341Sdelphij                /* Set to min mtu */
250296341Sdelphij                s->d1->mtu = dtls1_min_mtu(s);
251296341Sdelphij                BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
252296341Sdelphij                         s->d1->mtu, NULL);
253296341Sdelphij            }
254296341Sdelphij        } else
255296341Sdelphij            return 0;
256296341Sdelphij    }
257296341Sdelphij    return 1;
258279264Sdelphij}
259160814Ssimon
260296341Sdelphij/*
261296341Sdelphij * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
262296341Sdelphij * SSL3_RT_CHANGE_CIPHER_SPEC)
263296341Sdelphij */
264279264Sdelphijint dtls1_do_write(SSL *s, int type)
265296341Sdelphij{
266296341Sdelphij    int ret;
267296341Sdelphij    unsigned int curr_mtu;
268296341Sdelphij    int retry = 1;
269296341Sdelphij    unsigned int len, frag_off, mac_size, blocksize, used_len;
270160814Ssimon
271296341Sdelphij    if (!dtls1_query_mtu(s))
272296341Sdelphij        return -1;
273160814Ssimon
274296341Sdelphij    OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something
275296341Sdelphij                                                     * reasonable now */
276160814Ssimon
277296341Sdelphij    if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
278296341Sdelphij        OPENSSL_assert(s->init_num ==
279296341Sdelphij                       (int)s->d1->w_msg_hdr.msg_len +
280296341Sdelphij                       DTLS1_HM_HEADER_LENGTH);
281160814Ssimon
282296341Sdelphij    if (s->write_hash)
283296341Sdelphij        mac_size = EVP_MD_CTX_size(s->write_hash);
284296341Sdelphij    else
285296341Sdelphij        mac_size = 0;
286205128Ssimon
287296341Sdelphij    if (s->enc_write_ctx &&
288296341Sdelphij        (EVP_CIPHER_mode(s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE))
289296341Sdelphij        blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
290296341Sdelphij    else
291296341Sdelphij        blocksize = 0;
292205128Ssimon
293296341Sdelphij    frag_off = 0;
294296341Sdelphij    /* s->init_num shouldn't ever be < 0...but just in case */
295296341Sdelphij    while (s->init_num > 0) {
296296341Sdelphij        used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
297296341Sdelphij            + mac_size + blocksize;
298296341Sdelphij        if (s->d1->mtu > used_len)
299296341Sdelphij            curr_mtu = s->d1->mtu - used_len;
300296341Sdelphij        else
301296341Sdelphij            curr_mtu = 0;
302160814Ssimon
303296341Sdelphij        if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
304296341Sdelphij            /*
305296341Sdelphij             * grr.. we could get an error if MTU picked was wrong
306296341Sdelphij             */
307296341Sdelphij            ret = BIO_flush(SSL_get_wbio(s));
308296341Sdelphij            if (ret <= 0)
309296341Sdelphij                return ret;
310296341Sdelphij            used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
311296341Sdelphij            if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
312296341Sdelphij                curr_mtu = s->d1->mtu - used_len;
313296341Sdelphij            } else {
314296341Sdelphij                /* Shouldn't happen */
315296341Sdelphij                return -1;
316296341Sdelphij            }
317296341Sdelphij        }
318160814Ssimon
319296341Sdelphij        /*
320296341Sdelphij         * We just checked that s->init_num > 0 so this cast should be safe
321296341Sdelphij         */
322296341Sdelphij        if (((unsigned int)s->init_num) > curr_mtu)
323296341Sdelphij            len = curr_mtu;
324296341Sdelphij        else
325296341Sdelphij            len = s->init_num;
326160814Ssimon
327296341Sdelphij        /* Shouldn't ever happen */
328296341Sdelphij        if (len > INT_MAX)
329296341Sdelphij            len = INT_MAX;
330160814Ssimon
331296341Sdelphij        /*
332296341Sdelphij         * XDTLS: this function is too long.  split out the CCS part
333296341Sdelphij         */
334296341Sdelphij        if (type == SSL3_RT_HANDSHAKE) {
335296341Sdelphij            if (s->init_off != 0) {
336296341Sdelphij                OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
337296341Sdelphij                s->init_off -= DTLS1_HM_HEADER_LENGTH;
338296341Sdelphij                s->init_num += DTLS1_HM_HEADER_LENGTH;
339160814Ssimon
340296341Sdelphij                /*
341296341Sdelphij                 * We just checked that s->init_num > 0 so this cast should
342296341Sdelphij                 * be safe
343296341Sdelphij                 */
344296341Sdelphij                if (((unsigned int)s->init_num) > curr_mtu)
345296341Sdelphij                    len = curr_mtu;
346296341Sdelphij                else
347296341Sdelphij                    len = s->init_num;
348296341Sdelphij            }
349172767Ssimon
350296341Sdelphij            /* Shouldn't ever happen */
351296341Sdelphij            if (len > INT_MAX)
352296341Sdelphij                len = INT_MAX;
353279264Sdelphij
354296341Sdelphij            if (len < DTLS1_HM_HEADER_LENGTH) {
355296341Sdelphij                /*
356296341Sdelphij                 * len is so small that we really can't do anything sensible
357296341Sdelphij                 * so fail
358296341Sdelphij                 */
359296341Sdelphij                return -1;
360296341Sdelphij            }
361296341Sdelphij            dtls1_fix_message_header(s, frag_off,
362296341Sdelphij                                     len - DTLS1_HM_HEADER_LENGTH);
363160814Ssimon
364296341Sdelphij            dtls1_write_message_header(s,
365296341Sdelphij                                       (unsigned char *)&s->init_buf->
366296341Sdelphij                                       data[s->init_off]);
367296341Sdelphij        }
368160814Ssimon
369296341Sdelphij        ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off],
370296341Sdelphij                                len);
371296341Sdelphij        if (ret < 0) {
372296341Sdelphij            /*
373296341Sdelphij             * might need to update MTU here, but we don't know which
374296341Sdelphij             * previous packet caused the failure -- so can't really
375296341Sdelphij             * retransmit anything.  continue as if everything is fine and
376296341Sdelphij             * wait for an alert to handle the retransmit
377296341Sdelphij             */
378296341Sdelphij            if (retry && BIO_ctrl(SSL_get_wbio(s),
379296341Sdelphij                                  BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
380296341Sdelphij                if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
381296341Sdelphij                    if (!dtls1_query_mtu(s))
382296341Sdelphij                        return -1;
383296341Sdelphij                    /* Have one more go */
384296341Sdelphij                    retry = 0;
385296341Sdelphij                } else
386296341Sdelphij                    return -1;
387296341Sdelphij            } else {
388296341Sdelphij                return (-1);
389296341Sdelphij            }
390296341Sdelphij        } else {
391172767Ssimon
392296341Sdelphij            /*
393296341Sdelphij             * bad if this assert fails, only part of the handshake message
394296341Sdelphij             * got sent.  but why would this happen?
395296341Sdelphij             */
396296341Sdelphij            OPENSSL_assert(len == (unsigned int)ret);
397172767Ssimon
398296341Sdelphij            if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
399296341Sdelphij                /*
400296341Sdelphij                 * should not be done for 'Hello Request's, but in that case
401296341Sdelphij                 * we'll ignore the result anyway
402296341Sdelphij                 */
403296341Sdelphij                unsigned char *p =
404296341Sdelphij                    (unsigned char *)&s->init_buf->data[s->init_off];
405296341Sdelphij                const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
406296341Sdelphij                int xlen;
407172767Ssimon
408296341Sdelphij                if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
409296341Sdelphij                    /*
410296341Sdelphij                     * reconstruct message header is if it is being sent in
411296341Sdelphij                     * single fragment
412296341Sdelphij                     */
413296341Sdelphij                    *p++ = msg_hdr->type;
414296341Sdelphij                    l2n3(msg_hdr->msg_len, p);
415296341Sdelphij                    s2n(msg_hdr->seq, p);
416296341Sdelphij                    l2n3(0, p);
417296341Sdelphij                    l2n3(msg_hdr->msg_len, p);
418296341Sdelphij                    p -= DTLS1_HM_HEADER_LENGTH;
419296341Sdelphij                    xlen = ret;
420296341Sdelphij                } else {
421296341Sdelphij                    p += DTLS1_HM_HEADER_LENGTH;
422296341Sdelphij                    xlen = ret - DTLS1_HM_HEADER_LENGTH;
423296341Sdelphij                }
424172767Ssimon
425296341Sdelphij                ssl3_finish_mac(s, p, xlen);
426296341Sdelphij            }
427172767Ssimon
428296341Sdelphij            if (ret == s->init_num) {
429296341Sdelphij                if (s->msg_callback)
430296341Sdelphij                    s->msg_callback(1, s->version, type, s->init_buf->data,
431296341Sdelphij                                    (size_t)(s->init_off + s->init_num), s,
432296341Sdelphij                                    s->msg_callback_arg);
433160814Ssimon
434296341Sdelphij                s->init_off = 0; /* done writing this message */
435296341Sdelphij                s->init_num = 0;
436172767Ssimon
437296341Sdelphij                return (1);
438296341Sdelphij            }
439296341Sdelphij            s->init_off += ret;
440296341Sdelphij            s->init_num -= ret;
441296341Sdelphij            frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
442296341Sdelphij        }
443296341Sdelphij    }
444296341Sdelphij    return (0);
445296341Sdelphij}
446160814Ssimon
447296341Sdelphij/*
448296341Sdelphij * Obtain handshake message of message type 'mt' (any if mt == -1), maximum
449296341Sdelphij * acceptable body length 'max'. Read an entire handshake message.  Handshake
450296341Sdelphij * messages arrive in fragments.
451160814Ssimon */
452160814Ssimonlong dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
453296341Sdelphij{
454296341Sdelphij    int i, al;
455296341Sdelphij    struct hm_header_st *msg_hdr;
456296341Sdelphij    unsigned char *p;
457296341Sdelphij    unsigned long msg_len;
458160814Ssimon
459296341Sdelphij    /*
460296341Sdelphij     * s3->tmp is used to store messages that are unexpected, caused by the
461296341Sdelphij     * absence of an optional handshake message
462296341Sdelphij     */
463296341Sdelphij    if (s->s3->tmp.reuse_message) {
464296341Sdelphij        s->s3->tmp.reuse_message = 0;
465296341Sdelphij        if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
466296341Sdelphij            al = SSL_AD_UNEXPECTED_MESSAGE;
467296341Sdelphij            SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
468296341Sdelphij            goto f_err;
469296341Sdelphij        }
470296341Sdelphij        *ok = 1;
471296341Sdelphij        s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
472296341Sdelphij        s->init_num = (int)s->s3->tmp.message_size;
473296341Sdelphij        return s->init_num;
474296341Sdelphij    }
475172767Ssimon
476296341Sdelphij    msg_hdr = &s->d1->r_msg_hdr;
477296341Sdelphij    memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
478160814Ssimon
479296341Sdelphij again:
480296341Sdelphij    i = dtls1_get_message_fragment(s, st1, stn, max, ok);
481296341Sdelphij    if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) {
482296341Sdelphij        /* bad fragment received */
483296341Sdelphij        goto again;
484296341Sdelphij    } else if (i <= 0 && !*ok) {
485296341Sdelphij        return i;
486296341Sdelphij    }
487160814Ssimon
488284295Sdelphij    if (mt >= 0 && s->s3->tmp.message_type != mt) {
489284295Sdelphij        al = SSL_AD_UNEXPECTED_MESSAGE;
490284295Sdelphij        SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
491284295Sdelphij        goto f_err;
492284295Sdelphij    }
493284295Sdelphij
494296341Sdelphij    p = (unsigned char *)s->init_buf->data;
495296341Sdelphij    msg_len = msg_hdr->msg_len;
496160814Ssimon
497296341Sdelphij    /* reconstruct message header */
498296341Sdelphij    *(p++) = msg_hdr->type;
499296341Sdelphij    l2n3(msg_len, p);
500296341Sdelphij    s2n(msg_hdr->seq, p);
501296341Sdelphij    l2n3(0, p);
502296341Sdelphij    l2n3(msg_len, p);
503296341Sdelphij    if (s->version != DTLS1_BAD_VER) {
504296341Sdelphij        p -= DTLS1_HM_HEADER_LENGTH;
505296341Sdelphij        msg_len += DTLS1_HM_HEADER_LENGTH;
506296341Sdelphij    }
507172767Ssimon
508296341Sdelphij    ssl3_finish_mac(s, p, msg_len);
509296341Sdelphij    if (s->msg_callback)
510296341Sdelphij        s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
511296341Sdelphij                        p, msg_len, s, s->msg_callback_arg);
512172767Ssimon
513296341Sdelphij    memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
514172767Ssimon
515296341Sdelphij    /* Don't change sequence numbers while listening */
516296341Sdelphij    if (!s->d1->listen)
517296341Sdelphij        s->d1->handshake_read_seq++;
518160814Ssimon
519296341Sdelphij    s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
520296341Sdelphij    return s->init_num;
521160814Ssimon
522296341Sdelphij f_err:
523296341Sdelphij    ssl3_send_alert(s, SSL3_AL_FATAL, al);
524296341Sdelphij    *ok = 0;
525296341Sdelphij    return -1;
526296341Sdelphij}
527160814Ssimon
528296341Sdelphijstatic int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr,
529296341Sdelphij                                     int max)
530296341Sdelphij{
531296341Sdelphij    size_t frag_off, frag_len, msg_len;
532160814Ssimon
533296341Sdelphij    msg_len = msg_hdr->msg_len;
534296341Sdelphij    frag_off = msg_hdr->frag_off;
535296341Sdelphij    frag_len = msg_hdr->frag_len;
536160814Ssimon
537296341Sdelphij    /* sanity checking */
538296341Sdelphij    if ((frag_off + frag_len) > msg_len) {
539296341Sdelphij        SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
540296341Sdelphij        return SSL_AD_ILLEGAL_PARAMETER;
541296341Sdelphij    }
542160814Ssimon
543296341Sdelphij    if ((frag_off + frag_len) > (unsigned long)max) {
544296341Sdelphij        SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
545296341Sdelphij        return SSL_AD_ILLEGAL_PARAMETER;
546296341Sdelphij    }
547160814Ssimon
548296341Sdelphij    if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
549296341Sdelphij        /*
550296341Sdelphij         * msg_len is limited to 2^24, but is effectively checked against max
551296341Sdelphij         * above
552296341Sdelphij         */
553296341Sdelphij        if (!BUF_MEM_grow_clean
554296341Sdelphij            (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
555296341Sdelphij            SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
556296341Sdelphij            return SSL_AD_INTERNAL_ERROR;
557296341Sdelphij        }
558160814Ssimon
559296341Sdelphij        s->s3->tmp.message_size = msg_len;
560296341Sdelphij        s->d1->r_msg_hdr.msg_len = msg_len;
561296341Sdelphij        s->s3->tmp.message_type = msg_hdr->type;
562296341Sdelphij        s->d1->r_msg_hdr.type = msg_hdr->type;
563296341Sdelphij        s->d1->r_msg_hdr.seq = msg_hdr->seq;
564296341Sdelphij    } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
565296341Sdelphij        /*
566296341Sdelphij         * They must be playing with us! BTW, failure to enforce upper limit
567296341Sdelphij         * would open possibility for buffer overrun.
568296341Sdelphij         */
569296341Sdelphij        SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
570296341Sdelphij        return SSL_AD_ILLEGAL_PARAMETER;
571296341Sdelphij    }
572160814Ssimon
573296341Sdelphij    return 0;                   /* no error */
574296341Sdelphij}
575160814Ssimon
576296341Sdelphijstatic int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
577296341Sdelphij{
578296341Sdelphij    /*-
579296341Sdelphij     * (0) check whether the desired fragment is available
580296341Sdelphij     * if so:
581296341Sdelphij     * (1) copy over the fragment to s->init_buf->data[]
582296341Sdelphij     * (2) update s->init_num
583296341Sdelphij     */
584296341Sdelphij    pitem *item;
585296341Sdelphij    hm_fragment *frag;
586296341Sdelphij    int al;
587160814Ssimon
588296341Sdelphij    *ok = 0;
589306230Sdelphij    do {
590306230Sdelphij        item = pqueue_peek(s->d1->buffered_messages);
591306230Sdelphij        if (item == NULL)
592306230Sdelphij            return 0;
593172767Ssimon
594306230Sdelphij        frag = (hm_fragment *)item->data;
595160814Ssimon
596306230Sdelphij        if (frag->msg_header.seq < s->d1->handshake_read_seq) {
597306230Sdelphij            /* This is a stale message that has been buffered so clear it */
598306230Sdelphij            pqueue_pop(s->d1->buffered_messages);
599306230Sdelphij            dtls1_hm_fragment_free(frag);
600306230Sdelphij            pitem_free(item);
601306230Sdelphij            item = NULL;
602306230Sdelphij            frag = NULL;
603306230Sdelphij        }
604306230Sdelphij    } while (item == NULL);
605306230Sdelphij
606306230Sdelphij
607296341Sdelphij    /* Don't return if reassembly still in progress */
608296341Sdelphij    if (frag->reassembly != NULL)
609296341Sdelphij        return 0;
610160814Ssimon
611296341Sdelphij    if (s->d1->handshake_read_seq == frag->msg_header.seq) {
612296341Sdelphij        unsigned long frag_len = frag->msg_header.frag_len;
613296341Sdelphij        pqueue_pop(s->d1->buffered_messages);
614160814Ssimon
615296341Sdelphij        al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
616160814Ssimon
617296341Sdelphij        if (al == 0) {          /* no alert */
618296341Sdelphij            unsigned char *p =
619296341Sdelphij                (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
620296341Sdelphij            memcpy(&p[frag->msg_header.frag_off], frag->fragment,
621296341Sdelphij                   frag->msg_header.frag_len);
622296341Sdelphij        }
623160814Ssimon
624296341Sdelphij        dtls1_hm_fragment_free(frag);
625296341Sdelphij        pitem_free(item);
626160814Ssimon
627296341Sdelphij        if (al == 0) {
628296341Sdelphij            *ok = 1;
629296341Sdelphij            return frag_len;
630296341Sdelphij        }
631160814Ssimon
632296341Sdelphij        ssl3_send_alert(s, SSL3_AL_FATAL, al);
633296341Sdelphij        s->init_num = 0;
634296341Sdelphij        *ok = 0;
635296341Sdelphij        return -1;
636296341Sdelphij    } else
637296341Sdelphij        return 0;
638296341Sdelphij}
639160814Ssimon
640296341Sdelphij/*
641296341Sdelphij * dtls1_max_handshake_message_len returns the maximum number of bytes
642296341Sdelphij * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
643296341Sdelphij * may be greater if the maximum certificate list size requires it.
644296341Sdelphij */
645269686Sjkimstatic unsigned long dtls1_max_handshake_message_len(const SSL *s)
646296341Sdelphij{
647296341Sdelphij    unsigned long max_len =
648296341Sdelphij        DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
649296341Sdelphij    if (max_len < (unsigned long)s->max_cert_list)
650296341Sdelphij        return s->max_cert_list;
651296341Sdelphij    return max_len;
652296341Sdelphij}
653160814Ssimon
654172767Ssimonstatic int
655296341Sdelphijdtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
656296341Sdelphij{
657296341Sdelphij    hm_fragment *frag = NULL;
658296341Sdelphij    pitem *item = NULL;
659296341Sdelphij    int i = -1, is_complete;
660296341Sdelphij    unsigned char seq64be[8];
661296341Sdelphij    unsigned long frag_len = msg_hdr->frag_len;
662215697Ssimon
663296341Sdelphij    if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
664296341Sdelphij        msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
665296341Sdelphij        goto err;
666215697Ssimon
667296341Sdelphij    if (frag_len == 0)
668296341Sdelphij        return DTLS1_HM_FRAGMENT_RETRY;
669215697Ssimon
670296341Sdelphij    /* Try to find item in queue */
671296341Sdelphij    memset(seq64be, 0, sizeof(seq64be));
672296341Sdelphij    seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
673296341Sdelphij    seq64be[7] = (unsigned char)msg_hdr->seq;
674296341Sdelphij    item = pqueue_find(s->d1->buffered_messages, seq64be);
675215697Ssimon
676296341Sdelphij    if (item == NULL) {
677296341Sdelphij        frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
678296341Sdelphij        if (frag == NULL)
679296341Sdelphij            goto err;
680296341Sdelphij        memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
681296341Sdelphij        frag->msg_header.frag_len = frag->msg_header.msg_len;
682296341Sdelphij        frag->msg_header.frag_off = 0;
683296341Sdelphij    } else {
684296341Sdelphij        frag = (hm_fragment *)item->data;
685296341Sdelphij        if (frag->msg_header.msg_len != msg_hdr->msg_len) {
686296341Sdelphij            item = NULL;
687296341Sdelphij            frag = NULL;
688296341Sdelphij            goto err;
689296341Sdelphij        }
690296341Sdelphij    }
691215697Ssimon
692296341Sdelphij    /*
693296341Sdelphij     * If message is already reassembled, this must be a retransmit and can
694296341Sdelphij     * be dropped. In this case item != NULL and so frag does not need to be
695296341Sdelphij     * freed.
696296341Sdelphij     */
697296341Sdelphij    if (frag->reassembly == NULL) {
698296341Sdelphij        unsigned char devnull[256];
699267103Sdelphij
700296341Sdelphij        while (frag_len) {
701296341Sdelphij            i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
702296341Sdelphij                                          devnull,
703296341Sdelphij                                          frag_len >
704296341Sdelphij                                          sizeof(devnull) ? sizeof(devnull) :
705296341Sdelphij                                          frag_len, 0);
706296341Sdelphij            if (i <= 0)
707296341Sdelphij                goto err;
708296341Sdelphij            frag_len -= i;
709296341Sdelphij        }
710296341Sdelphij        return DTLS1_HM_FRAGMENT_RETRY;
711296341Sdelphij    }
712215697Ssimon
713296341Sdelphij    /* read the body of the fragment (header has already been read */
714296341Sdelphij    i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
715296341Sdelphij                                  frag->fragment + msg_hdr->frag_off,
716296341Sdelphij                                  frag_len, 0);
717296341Sdelphij    if ((unsigned long)i != frag_len)
718296341Sdelphij        i = -1;
719296341Sdelphij    if (i <= 0)
720296341Sdelphij        goto err;
721215697Ssimon
722296341Sdelphij    RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
723296341Sdelphij                        (long)(msg_hdr->frag_off + frag_len));
724215697Ssimon
725296341Sdelphij    RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
726296341Sdelphij                               is_complete);
727215697Ssimon
728296341Sdelphij    if (is_complete) {
729296341Sdelphij        OPENSSL_free(frag->reassembly);
730296341Sdelphij        frag->reassembly = NULL;
731296341Sdelphij    }
732215697Ssimon
733296341Sdelphij    if (item == NULL) {
734296341Sdelphij        item = pitem_new(seq64be, frag);
735296341Sdelphij        if (item == NULL) {
736296341Sdelphij            i = -1;
737296341Sdelphij            goto err;
738296341Sdelphij        }
739215697Ssimon
740296341Sdelphij        item = pqueue_insert(s->d1->buffered_messages, item);
741296341Sdelphij        /*
742296341Sdelphij         * pqueue_insert fails iff a duplicate item is inserted. However,
743296341Sdelphij         * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
744296341Sdelphij         * would have returned it and control would never have reached this
745296341Sdelphij         * branch.
746296341Sdelphij         */
747296341Sdelphij        OPENSSL_assert(item != NULL);
748296341Sdelphij    }
749215697Ssimon
750296341Sdelphij    return DTLS1_HM_FRAGMENT_RETRY;
751215697Ssimon
752296341Sdelphij err:
753296341Sdelphij    if (frag != NULL && item == NULL)
754296341Sdelphij        dtls1_hm_fragment_free(frag);
755296341Sdelphij    *ok = 0;
756296341Sdelphij    return i;
757296341Sdelphij}
758215697Ssimon
759215697Ssimonstatic int
760296341Sdelphijdtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
761296341Sdelphij                                 int *ok)
762172767Ssimon{
763296341Sdelphij    int i = -1;
764296341Sdelphij    hm_fragment *frag = NULL;
765296341Sdelphij    pitem *item = NULL;
766296341Sdelphij    unsigned char seq64be[8];
767296341Sdelphij    unsigned long frag_len = msg_hdr->frag_len;
768160814Ssimon
769296341Sdelphij    if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
770296341Sdelphij        goto err;
771160814Ssimon
772296341Sdelphij    /* Try to find item in queue, to prevent duplicate entries */
773296341Sdelphij    memset(seq64be, 0, sizeof(seq64be));
774296341Sdelphij    seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
775296341Sdelphij    seq64be[7] = (unsigned char)msg_hdr->seq;
776296341Sdelphij    item = pqueue_find(s->d1->buffered_messages, seq64be);
777215697Ssimon
778296341Sdelphij    /*
779296341Sdelphij     * If we already have an entry and this one is a fragment, don't discard
780296341Sdelphij     * it and rather try to reassemble it.
781296341Sdelphij     */
782296341Sdelphij    if (item != NULL && frag_len != msg_hdr->msg_len)
783296341Sdelphij        item = NULL;
784215697Ssimon
785296341Sdelphij    /*
786296341Sdelphij     * Discard the message if sequence number was already there, is too far
787296341Sdelphij     * in the future, already in the queue or if we received a FINISHED
788296341Sdelphij     * before the SERVER_HELLO, which then must be a stale retransmit.
789296341Sdelphij     */
790296341Sdelphij    if (msg_hdr->seq <= s->d1->handshake_read_seq ||
791296341Sdelphij        msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
792296341Sdelphij        (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
793296341Sdelphij    {
794296341Sdelphij        unsigned char devnull[256];
795160814Ssimon
796296341Sdelphij        while (frag_len) {
797296341Sdelphij            i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
798296341Sdelphij                                          devnull,
799296341Sdelphij                                          frag_len >
800296341Sdelphij                                          sizeof(devnull) ? sizeof(devnull) :
801296341Sdelphij                                          frag_len, 0);
802296341Sdelphij            if (i <= 0)
803296341Sdelphij                goto err;
804296341Sdelphij            frag_len -= i;
805296341Sdelphij        }
806296341Sdelphij    } else {
807296341Sdelphij        if (frag_len != msg_hdr->msg_len)
808296341Sdelphij            return dtls1_reassemble_fragment(s, msg_hdr, ok);
809160814Ssimon
810296341Sdelphij        if (frag_len > dtls1_max_handshake_message_len(s))
811296341Sdelphij            goto err;
812269686Sjkim
813296341Sdelphij        frag = dtls1_hm_fragment_new(frag_len, 0);
814296341Sdelphij        if (frag == NULL)
815296341Sdelphij            goto err;
816160814Ssimon
817296341Sdelphij        memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
818160814Ssimon
819296341Sdelphij        if (frag_len) {
820296341Sdelphij            /*
821296341Sdelphij             * read the body of the fragment (header has already been read
822296341Sdelphij             */
823296341Sdelphij            i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
824296341Sdelphij                                          frag->fragment, frag_len, 0);
825296341Sdelphij            if ((unsigned long)i != frag_len)
826296341Sdelphij                i = -1;
827296341Sdelphij            if (i <= 0)
828296341Sdelphij                goto err;
829296341Sdelphij        }
830160814Ssimon
831296341Sdelphij        item = pitem_new(seq64be, frag);
832296341Sdelphij        if (item == NULL)
833296341Sdelphij            goto err;
834172767Ssimon
835296341Sdelphij        item = pqueue_insert(s->d1->buffered_messages, item);
836296341Sdelphij        /*
837296341Sdelphij         * pqueue_insert fails iff a duplicate item is inserted. However,
838296341Sdelphij         * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
839296341Sdelphij         * would have returned it. Then, either |frag_len| !=
840296341Sdelphij         * |msg_hdr->msg_len| in which case |item| is set to NULL and it will
841296341Sdelphij         * have been processed with |dtls1_reassemble_fragment|, above, or
842296341Sdelphij         * the record will have been discarded.
843296341Sdelphij         */
844296341Sdelphij        OPENSSL_assert(item != NULL);
845296341Sdelphij    }
846196474Ssimon
847296341Sdelphij    return DTLS1_HM_FRAGMENT_RETRY;
848172767Ssimon
849296341Sdelphij err:
850296341Sdelphij    if (frag != NULL && item == NULL)
851296341Sdelphij        dtls1_hm_fragment_free(frag);
852296341Sdelphij    *ok = 0;
853296341Sdelphij    return i;
854296341Sdelphij}
855160814Ssimon
856160814Ssimonstatic long
857160814Ssimondtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
858296341Sdelphij{
859296341Sdelphij    unsigned char wire[DTLS1_HM_HEADER_LENGTH];
860296341Sdelphij    unsigned long len, frag_off, frag_len;
861296341Sdelphij    int i, al;
862296341Sdelphij    struct hm_header_st msg_hdr;
863160814Ssimon
864296341Sdelphij redo:
865296341Sdelphij    /* see if we have the required fragment already */
866296341Sdelphij    if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) {
867296341Sdelphij        if (*ok)
868296341Sdelphij            s->init_num = frag_len;
869296341Sdelphij        return frag_len;
870296341Sdelphij    }
871160814Ssimon
872296341Sdelphij    /* read handshake message header */
873296341Sdelphij    i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire,
874296341Sdelphij                                  DTLS1_HM_HEADER_LENGTH, 0);
875296341Sdelphij    if (i <= 0) {               /* nbio, or an error */
876296341Sdelphij        s->rwstate = SSL_READING;
877296341Sdelphij        *ok = 0;
878296341Sdelphij        return i;
879296341Sdelphij    }
880296341Sdelphij    /* Handshake fails if message header is incomplete */
881296341Sdelphij    if (i != DTLS1_HM_HEADER_LENGTH) {
882296341Sdelphij        al = SSL_AD_UNEXPECTED_MESSAGE;
883296341Sdelphij        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_UNEXPECTED_MESSAGE);
884296341Sdelphij        goto f_err;
885296341Sdelphij    }
886160814Ssimon
887296341Sdelphij    /* parse the message fragment header */
888296341Sdelphij    dtls1_get_message_header(wire, &msg_hdr);
889160814Ssimon
890284295Sdelphij    len = msg_hdr.msg_len;
891284295Sdelphij    frag_off = msg_hdr.frag_off;
892284295Sdelphij    frag_len = msg_hdr.frag_len;
893284295Sdelphij
894284295Sdelphij    /*
895284295Sdelphij     * We must have at least frag_len bytes left in the record to be read.
896284295Sdelphij     * Fragments must not span records.
897284295Sdelphij     */
898284295Sdelphij    if (frag_len > s->s3->rrec.length) {
899284295Sdelphij        al = SSL3_AD_ILLEGAL_PARAMETER;
900284295Sdelphij        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_LENGTH);
901284295Sdelphij        goto f_err;
902284295Sdelphij    }
903284295Sdelphij
904296341Sdelphij    /*
905296341Sdelphij     * if this is a future (or stale) message it gets buffered
906296341Sdelphij     * (or dropped)--no further processing at this time
907296341Sdelphij     * While listening, we accept seq 1 (ClientHello with cookie)
908296341Sdelphij     * although we're still expecting seq 0 (ClientHello)
909296341Sdelphij     */
910296341Sdelphij    if (msg_hdr.seq != s->d1->handshake_read_seq
911296341Sdelphij        && !(s->d1->listen && msg_hdr.seq == 1))
912296341Sdelphij        return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
913160814Ssimon
914296341Sdelphij    if (frag_len && frag_len < len)
915296341Sdelphij        return dtls1_reassemble_fragment(s, &msg_hdr, ok);
916215697Ssimon
917296341Sdelphij    if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
918296341Sdelphij        wire[0] == SSL3_MT_HELLO_REQUEST) {
919296341Sdelphij        /*
920296341Sdelphij         * The server may always send 'Hello Request' messages -- we are
921296341Sdelphij         * doing a handshake anyway now, so ignore them if their format is
922296341Sdelphij         * correct. Does not count for 'Finished' MAC.
923296341Sdelphij         */
924296341Sdelphij        if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
925296341Sdelphij            if (s->msg_callback)
926296341Sdelphij                s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
927296341Sdelphij                                wire, DTLS1_HM_HEADER_LENGTH, s,
928296341Sdelphij                                s->msg_callback_arg);
929160814Ssimon
930296341Sdelphij            s->init_num = 0;
931296341Sdelphij            goto redo;
932296341Sdelphij        } else {                /* Incorrectly formated Hello request */
933160814Ssimon
934296341Sdelphij            al = SSL_AD_UNEXPECTED_MESSAGE;
935296341Sdelphij            SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,
936296341Sdelphij                   SSL_R_UNEXPECTED_MESSAGE);
937296341Sdelphij            goto f_err;
938296341Sdelphij        }
939296341Sdelphij    }
940172767Ssimon
941296341Sdelphij    if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
942296341Sdelphij        goto f_err;
943160814Ssimon
944296341Sdelphij    if (frag_len > 0) {
945296341Sdelphij        unsigned char *p =
946296341Sdelphij            (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
947160814Ssimon
948296341Sdelphij        i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
949296341Sdelphij                                      &p[frag_off], frag_len, 0);
950296341Sdelphij
951296341Sdelphij        /*
952296341Sdelphij         * This shouldn't ever fail due to NBIO because we already checked
953296341Sdelphij         * that we have enough data in the record
954296341Sdelphij         */
955296341Sdelphij        if (i <= 0) {
956296341Sdelphij            s->rwstate = SSL_READING;
957296341Sdelphij            *ok = 0;
958296341Sdelphij            return i;
959296341Sdelphij        }
960296341Sdelphij    } else
961296341Sdelphij        i = 0;
962296341Sdelphij
963296341Sdelphij    /*
964296341Sdelphij     * XDTLS: an incorrectly formatted fragment should cause the handshake
965296341Sdelphij     * to fail
966296341Sdelphij     */
967296341Sdelphij    if (i != (int)frag_len) {
968296341Sdelphij        al = SSL3_AD_ILLEGAL_PARAMETER;
969296341Sdelphij        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL3_AD_ILLEGAL_PARAMETER);
970296341Sdelphij        goto f_err;
971296341Sdelphij    }
972296341Sdelphij
973296341Sdelphij    *ok = 1;
974284295Sdelphij    s->state = stn;
975160814Ssimon
976296341Sdelphij    /*
977296341Sdelphij     * Note that s->init_num is *not* used as current offset in
978296341Sdelphij     * s->init_buf->data, but as a counter summing up fragments' lengths: as
979296341Sdelphij     * soon as they sum up to handshake packet length, we assume we have got
980296341Sdelphij     * all the fragments.
981296341Sdelphij     */
982296341Sdelphij    s->init_num = frag_len;
983296341Sdelphij    return frag_len;
984160814Ssimon
985296341Sdelphij f_err:
986296341Sdelphij    ssl3_send_alert(s, SSL3_AL_FATAL, al);
987296341Sdelphij    s->init_num = 0;
988172767Ssimon
989296341Sdelphij    *ok = 0;
990296341Sdelphij    return (-1);
991296341Sdelphij}
992160814Ssimon
993160814Ssimonint dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen)
994296341Sdelphij{
995296341Sdelphij    unsigned char *p, *d;
996296341Sdelphij    int i;
997296341Sdelphij    unsigned long l;
998160814Ssimon
999296341Sdelphij    if (s->state == a) {
1000296341Sdelphij        d = (unsigned char *)s->init_buf->data;
1001296341Sdelphij        p = &(d[DTLS1_HM_HEADER_LENGTH]);
1002160814Ssimon
1003296341Sdelphij        i = s->method->ssl3_enc->final_finish_mac(s,
1004296341Sdelphij                                                  sender, slen,
1005296341Sdelphij                                                  s->s3->tmp.finish_md);
1006296341Sdelphij        s->s3->tmp.finish_md_len = i;
1007296341Sdelphij        memcpy(p, s->s3->tmp.finish_md, i);
1008296341Sdelphij        p += i;
1009296341Sdelphij        l = i;
1010160814Ssimon
1011296341Sdelphij        /*
1012296341Sdelphij         * Copy the finished so we can use it for renegotiation checks
1013296341Sdelphij         */
1014296341Sdelphij        if (s->type == SSL_ST_CONNECT) {
1015296341Sdelphij            OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
1016296341Sdelphij            memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
1017296341Sdelphij            s->s3->previous_client_finished_len = i;
1018296341Sdelphij        } else {
1019296341Sdelphij            OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
1020296341Sdelphij            memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
1021296341Sdelphij            s->s3->previous_server_finished_len = i;
1022296341Sdelphij        }
1023205128Ssimon
1024160814Ssimon#ifdef OPENSSL_SYS_WIN16
1025296341Sdelphij        /*
1026296341Sdelphij         * MSVC 1.5 does not clear the top bytes of the word unless I do
1027296341Sdelphij         * this.
1028296341Sdelphij         */
1029296341Sdelphij        l &= 0xffff;
1030160814Ssimon#endif
1031160814Ssimon
1032296341Sdelphij        d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l);
1033296341Sdelphij        s->init_num = (int)l + DTLS1_HM_HEADER_LENGTH;
1034296341Sdelphij        s->init_off = 0;
1035160814Ssimon
1036296341Sdelphij        /* buffer the message to handle re-xmits */
1037296341Sdelphij        dtls1_buffer_message(s, 0);
1038172767Ssimon
1039296341Sdelphij        s->state = b;
1040296341Sdelphij    }
1041160814Ssimon
1042296341Sdelphij    /* SSL3_ST_SEND_xxxxxx_HELLO_B */
1043296341Sdelphij    return (dtls1_do_write(s, SSL3_RT_HANDSHAKE));
1044296341Sdelphij}
1045160814Ssimon
1046296341Sdelphij/*-
1047296341Sdelphij * for these 2 messages, we need to
1048296341Sdelphij * ssl->enc_read_ctx                    re-init
1049296341Sdelphij * ssl->s3->read_sequence               zero
1050296341Sdelphij * ssl->s3->read_mac_secret             re-init
1051296341Sdelphij * ssl->session->read_sym_enc           assign
1052296341Sdelphij * ssl->session->read_compression       assign
1053296341Sdelphij * ssl->session->read_hash              assign
1054160814Ssimon */
1055160814Ssimonint dtls1_send_change_cipher_spec(SSL *s, int a, int b)
1056296341Sdelphij{
1057296341Sdelphij    unsigned char *p;
1058160814Ssimon
1059296341Sdelphij    if (s->state == a) {
1060296341Sdelphij        p = (unsigned char *)s->init_buf->data;
1061296341Sdelphij        *p++ = SSL3_MT_CCS;
1062296341Sdelphij        s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
1063296341Sdelphij        s->init_num = DTLS1_CCS_HEADER_LENGTH;
1064160814Ssimon
1065296341Sdelphij        if (s->version == DTLS1_BAD_VER) {
1066296341Sdelphij            s->d1->next_handshake_write_seq++;
1067296341Sdelphij            s2n(s->d1->handshake_write_seq, p);
1068296341Sdelphij            s->init_num += 2;
1069296341Sdelphij        }
1070172767Ssimon
1071296341Sdelphij        s->init_off = 0;
1072160814Ssimon
1073296341Sdelphij        dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
1074296341Sdelphij                                     s->d1->handshake_write_seq, 0, 0);
1075160814Ssimon
1076296341Sdelphij        /* buffer the message to handle re-xmits */
1077296341Sdelphij        dtls1_buffer_message(s, 1);
1078160814Ssimon
1079296341Sdelphij        s->state = b;
1080296341Sdelphij    }
1081160814Ssimon
1082296341Sdelphij    /* SSL3_ST_CW_CHANGE_B */
1083296341Sdelphij    return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC));
1084296341Sdelphij}
1085160814Ssimon
1086205128Ssimonstatic int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
1087296341Sdelphij{
1088296341Sdelphij    int n;
1089296341Sdelphij    unsigned char *p;
1090205128Ssimon
1091296341Sdelphij    n = i2d_X509(x, NULL);
1092296341Sdelphij    if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
1093296341Sdelphij        SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
1094296341Sdelphij        return 0;
1095296341Sdelphij    }
1096296341Sdelphij    p = (unsigned char *)&(buf->data[*l]);
1097296341Sdelphij    l2n3(n, p);
1098296341Sdelphij    i2d_X509(x, &p);
1099296341Sdelphij    *l += n + 3;
1100205128Ssimon
1101296341Sdelphij    return 1;
1102296341Sdelphij}
1103296341Sdelphij
1104160814Ssimonunsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
1105296341Sdelphij{
1106296341Sdelphij    unsigned char *p;
1107296341Sdelphij    int i;
1108296341Sdelphij    unsigned long l = 3 + DTLS1_HM_HEADER_LENGTH;
1109296341Sdelphij    BUF_MEM *buf;
1110160814Ssimon
1111296341Sdelphij    /* TLSv1 sends a chain with nothing in it, instead of an alert */
1112296341Sdelphij    buf = s->init_buf;
1113296341Sdelphij    if (!BUF_MEM_grow_clean(buf, 10)) {
1114296341Sdelphij        SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB);
1115296341Sdelphij        return (0);
1116296341Sdelphij    }
1117296341Sdelphij    if (x != NULL) {
1118296341Sdelphij        X509_STORE_CTX xs_ctx;
1119238405Sjkim
1120296341Sdelphij        if (!X509_STORE_CTX_init(&xs_ctx, s->ctx->cert_store, x, NULL)) {
1121296341Sdelphij            SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB);
1122296341Sdelphij            return (0);
1123296341Sdelphij        }
1124160814Ssimon
1125296341Sdelphij        X509_verify_cert(&xs_ctx);
1126296341Sdelphij        /* Don't leave errors in the queue */
1127296341Sdelphij        ERR_clear_error();
1128296341Sdelphij        for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
1129296341Sdelphij            x = sk_X509_value(xs_ctx.chain, i);
1130160814Ssimon
1131296341Sdelphij            if (!dtls1_add_cert_to_buf(buf, &l, x)) {
1132296341Sdelphij                X509_STORE_CTX_cleanup(&xs_ctx);
1133296341Sdelphij                return 0;
1134296341Sdelphij            }
1135296341Sdelphij        }
1136296341Sdelphij        X509_STORE_CTX_cleanup(&xs_ctx);
1137296341Sdelphij    }
1138296341Sdelphij    /* Thawte special :-) */
1139296341Sdelphij    for (i = 0; i < sk_X509_num(s->ctx->extra_certs); i++) {
1140296341Sdelphij        x = sk_X509_value(s->ctx->extra_certs, i);
1141296341Sdelphij        if (!dtls1_add_cert_to_buf(buf, &l, x))
1142296341Sdelphij            return 0;
1143296341Sdelphij    }
1144160814Ssimon
1145296341Sdelphij    l -= (3 + DTLS1_HM_HEADER_LENGTH);
1146160814Ssimon
1147296341Sdelphij    p = (unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
1148296341Sdelphij    l2n3(l, p);
1149296341Sdelphij    l += 3;
1150296341Sdelphij    p = (unsigned char *)&(buf->data[0]);
1151296341Sdelphij    p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);
1152160814Ssimon
1153296341Sdelphij    l += DTLS1_HM_HEADER_LENGTH;
1154296341Sdelphij    return (l);
1155296341Sdelphij}
1156296341Sdelphij
1157160814Ssimonint dtls1_read_failed(SSL *s, int code)
1158296341Sdelphij{
1159296341Sdelphij    if (code > 0) {
1160296341Sdelphij        fprintf(stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
1161296341Sdelphij        return 1;
1162296341Sdelphij    }
1163160814Ssimon
1164296341Sdelphij    if (!dtls1_is_timer_expired(s)) {
1165296341Sdelphij        /*
1166296341Sdelphij         * not a timeout, none of our business, let higher layers handle
1167296341Sdelphij         * this.  in fact it's probably an error
1168296341Sdelphij         */
1169296341Sdelphij        return code;
1170296341Sdelphij    }
1171238405Sjkim#ifndef OPENSSL_NO_HEARTBEATS
1172296341Sdelphij    /* done, no need to send a retransmit */
1173296341Sdelphij    if (!SSL_in_init(s) && !s->tlsext_hb_pending)
1174238405Sjkim#else
1175296341Sdelphij    /* done, no need to send a retransmit */
1176296341Sdelphij    if (!SSL_in_init(s))
1177238405Sjkim#endif
1178296341Sdelphij    {
1179296341Sdelphij        BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
1180296341Sdelphij        return code;
1181296341Sdelphij    }
1182296341Sdelphij#if 0                           /* for now, each alert contains only one
1183296341Sdelphij                                 * record number */
1184296341Sdelphij    item = pqueue_peek(state->rcvd_records);
1185296341Sdelphij    if (item) {
1186296341Sdelphij        /* send an alert immediately for all the missing records */
1187296341Sdelphij    } else
1188160814Ssimon#endif
1189160814Ssimon
1190296341Sdelphij#if 0                           /* no more alert sending, just retransmit the
1191296341Sdelphij                                 * last set of messages */
1192296341Sdelphij    if (state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
1193296341Sdelphij        ssl3_send_alert(s, SSL3_AL_WARNING,
1194296341Sdelphij                        DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
1195160814Ssimon#endif
1196160814Ssimon
1197296341Sdelphij    return dtls1_handle_timeout(s);
1198296341Sdelphij}
1199160814Ssimon
1200296341Sdelphijint dtls1_get_queue_priority(unsigned short seq, int is_ccs)
1201296341Sdelphij{
1202296341Sdelphij    /*
1203296341Sdelphij     * The index of the retransmission queue actually is the message sequence
1204296341Sdelphij     * number, since the queue only contains messages of a single handshake.
1205296341Sdelphij     * However, the ChangeCipherSpec has no message sequence number and so
1206296341Sdelphij     * using only the sequence will result in the CCS and Finished having the
1207296341Sdelphij     * same index. To prevent this, the sequence number is multiplied by 2.
1208296341Sdelphij     * In case of a CCS 1 is subtracted. This does not only differ CSS and
1209296341Sdelphij     * Finished, it also maintains the order of the index (important for
1210296341Sdelphij     * priority queues) and fits in the unsigned short variable.
1211296341Sdelphij     */
1212296341Sdelphij    return seq * 2 - is_ccs;
1213296341Sdelphij}
1214160814Ssimon
1215296341Sdelphijint dtls1_retransmit_buffered_messages(SSL *s)
1216296341Sdelphij{
1217296341Sdelphij    pqueue sent = s->d1->sent_messages;
1218296341Sdelphij    piterator iter;
1219296341Sdelphij    pitem *item;
1220296341Sdelphij    hm_fragment *frag;
1221296341Sdelphij    int found = 0;
1222160814Ssimon
1223296341Sdelphij    iter = pqueue_iterator(sent);
1224160814Ssimon
1225296341Sdelphij    for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
1226296341Sdelphij        frag = (hm_fragment *)item->data;
1227296341Sdelphij        if (dtls1_retransmit_message(s, (unsigned short)
1228296341Sdelphij                                     dtls1_get_queue_priority
1229296341Sdelphij                                     (frag->msg_header.seq,
1230296341Sdelphij                                      frag->msg_header.is_ccs), 0,
1231296341Sdelphij                                     &found) <= 0 && found) {
1232296341Sdelphij            fprintf(stderr, "dtls1_retransmit_message() failed\n");
1233296341Sdelphij            return -1;
1234296341Sdelphij        }
1235296341Sdelphij    }
1236160814Ssimon
1237296341Sdelphij    return 1;
1238296341Sdelphij}
1239160814Ssimon
1240296341Sdelphijint dtls1_buffer_message(SSL *s, int is_ccs)
1241296341Sdelphij{
1242296341Sdelphij    pitem *item;
1243296341Sdelphij    hm_fragment *frag;
1244296341Sdelphij    unsigned char seq64be[8];
1245160814Ssimon
1246296341Sdelphij    /*
1247296341Sdelphij     * this function is called immediately after a message has been
1248296341Sdelphij     * serialized
1249296341Sdelphij     */
1250296341Sdelphij    OPENSSL_assert(s->init_off == 0);
1251160814Ssimon
1252296341Sdelphij    frag = dtls1_hm_fragment_new(s->init_num, 0);
1253296341Sdelphij    if (!frag)
1254296341Sdelphij        return 0;
1255160814Ssimon
1256296341Sdelphij    memcpy(frag->fragment, s->init_buf->data, s->init_num);
1257160814Ssimon
1258296341Sdelphij    if (is_ccs) {
1259296341Sdelphij        OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
1260296341Sdelphij                       ((s->version ==
1261296341Sdelphij                         DTLS1_VERSION) ? DTLS1_CCS_HEADER_LENGTH : 3) ==
1262296341Sdelphij                       (unsigned int)s->init_num);
1263296341Sdelphij    } else {
1264296341Sdelphij        OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
1265296341Sdelphij                       DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
1266296341Sdelphij    }
1267160814Ssimon
1268296341Sdelphij    frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
1269296341Sdelphij    frag->msg_header.seq = s->d1->w_msg_hdr.seq;
1270296341Sdelphij    frag->msg_header.type = s->d1->w_msg_hdr.type;
1271296341Sdelphij    frag->msg_header.frag_off = 0;
1272296341Sdelphij    frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
1273296341Sdelphij    frag->msg_header.is_ccs = is_ccs;
1274160814Ssimon
1275296341Sdelphij    /* save current state */
1276296341Sdelphij    frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
1277296341Sdelphij    frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
1278296341Sdelphij    frag->msg_header.saved_retransmit_state.compress = s->compress;
1279296341Sdelphij    frag->msg_header.saved_retransmit_state.session = s->session;
1280296341Sdelphij    frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
1281205128Ssimon
1282296341Sdelphij    memset(seq64be, 0, sizeof(seq64be));
1283296341Sdelphij    seq64be[6] =
1284296341Sdelphij        (unsigned
1285296341Sdelphij         char)(dtls1_get_queue_priority(frag->msg_header.seq,
1286296341Sdelphij                                        frag->msg_header.is_ccs) >> 8);
1287296341Sdelphij    seq64be[7] =
1288296341Sdelphij        (unsigned
1289296341Sdelphij         char)(dtls1_get_queue_priority(frag->msg_header.seq,
1290296341Sdelphij                                        frag->msg_header.is_ccs));
1291160814Ssimon
1292296341Sdelphij    item = pitem_new(seq64be, frag);
1293296341Sdelphij    if (item == NULL) {
1294296341Sdelphij        dtls1_hm_fragment_free(frag);
1295296341Sdelphij        return 0;
1296296341Sdelphij    }
1297160814Ssimon#if 0
1298296341Sdelphij    fprintf(stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
1299296341Sdelphij    fprintf(stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
1300296341Sdelphij    fprintf(stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
1301160814Ssimon#endif
1302160814Ssimon
1303296341Sdelphij    pqueue_insert(s->d1->sent_messages, item);
1304296341Sdelphij    return 1;
1305296341Sdelphij}
1306160814Ssimon
1307160814Ssimonint
1308160814Ssimondtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
1309296341Sdelphij                         int *found)
1310296341Sdelphij{
1311296341Sdelphij    int ret;
1312296341Sdelphij    /* XDTLS: for now assuming that read/writes are blocking */
1313296341Sdelphij    pitem *item;
1314296341Sdelphij    hm_fragment *frag;
1315296341Sdelphij    unsigned long header_length;
1316296341Sdelphij    unsigned char seq64be[8];
1317296341Sdelphij    struct dtls1_retransmit_state saved_state;
1318296341Sdelphij    unsigned char save_write_sequence[8];
1319160814Ssimon
1320296341Sdelphij    /*-
1321296341Sdelphij      OPENSSL_assert(s->init_num == 0);
1322296341Sdelphij      OPENSSL_assert(s->init_off == 0);
1323296341Sdelphij     */
1324160814Ssimon
1325296341Sdelphij    /* XDTLS:  the requested message ought to be found, otherwise error */
1326296341Sdelphij    memset(seq64be, 0, sizeof(seq64be));
1327296341Sdelphij    seq64be[6] = (unsigned char)(seq >> 8);
1328296341Sdelphij    seq64be[7] = (unsigned char)seq;
1329160814Ssimon
1330296341Sdelphij    item = pqueue_find(s->d1->sent_messages, seq64be);
1331296341Sdelphij    if (item == NULL) {
1332296341Sdelphij        fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
1333296341Sdelphij        *found = 0;
1334296341Sdelphij        return 0;
1335296341Sdelphij    }
1336160814Ssimon
1337296341Sdelphij    *found = 1;
1338296341Sdelphij    frag = (hm_fragment *)item->data;
1339160814Ssimon
1340296341Sdelphij    if (frag->msg_header.is_ccs)
1341296341Sdelphij        header_length = DTLS1_CCS_HEADER_LENGTH;
1342296341Sdelphij    else
1343296341Sdelphij        header_length = DTLS1_HM_HEADER_LENGTH;
1344160814Ssimon
1345296341Sdelphij    memcpy(s->init_buf->data, frag->fragment,
1346296341Sdelphij           frag->msg_header.msg_len + header_length);
1347296341Sdelphij    s->init_num = frag->msg_header.msg_len + header_length;
1348160814Ssimon
1349296341Sdelphij    dtls1_set_message_header_int(s, frag->msg_header.type,
1350296341Sdelphij                                 frag->msg_header.msg_len,
1351296341Sdelphij                                 frag->msg_header.seq, 0,
1352296341Sdelphij                                 frag->msg_header.frag_len);
1353160814Ssimon
1354296341Sdelphij    /* save current state */
1355296341Sdelphij    saved_state.enc_write_ctx = s->enc_write_ctx;
1356296341Sdelphij    saved_state.write_hash = s->write_hash;
1357296341Sdelphij    saved_state.compress = s->compress;
1358296341Sdelphij    saved_state.session = s->session;
1359296341Sdelphij    saved_state.epoch = s->d1->w_epoch;
1360296341Sdelphij    saved_state.epoch = s->d1->w_epoch;
1361205128Ssimon
1362296341Sdelphij    s->d1->retransmitting = 1;
1363160814Ssimon
1364296341Sdelphij    /* restore state in which the message was originally sent */
1365296341Sdelphij    s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
1366296341Sdelphij    s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
1367296341Sdelphij    s->compress = frag->msg_header.saved_retransmit_state.compress;
1368296341Sdelphij    s->session = frag->msg_header.saved_retransmit_state.session;
1369296341Sdelphij    s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
1370172767Ssimon
1371296341Sdelphij    if (frag->msg_header.saved_retransmit_state.epoch ==
1372296341Sdelphij        saved_state.epoch - 1) {
1373296341Sdelphij        memcpy(save_write_sequence, s->s3->write_sequence,
1374296341Sdelphij               sizeof(s->s3->write_sequence));
1375296341Sdelphij        memcpy(s->s3->write_sequence, s->d1->last_write_sequence,
1376296341Sdelphij               sizeof(s->s3->write_sequence));
1377296341Sdelphij    }
1378160814Ssimon
1379296341Sdelphij    ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
1380296341Sdelphij                         SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
1381160814Ssimon
1382296341Sdelphij    /* restore current state */
1383296341Sdelphij    s->enc_write_ctx = saved_state.enc_write_ctx;
1384296341Sdelphij    s->write_hash = saved_state.write_hash;
1385296341Sdelphij    s->compress = saved_state.compress;
1386296341Sdelphij    s->session = saved_state.session;
1387296341Sdelphij    s->d1->w_epoch = saved_state.epoch;
1388172767Ssimon
1389296341Sdelphij    if (frag->msg_header.saved_retransmit_state.epoch ==
1390296341Sdelphij        saved_state.epoch - 1) {
1391296341Sdelphij        memcpy(s->d1->last_write_sequence, s->s3->write_sequence,
1392296341Sdelphij               sizeof(s->s3->write_sequence));
1393296341Sdelphij        memcpy(s->s3->write_sequence, save_write_sequence,
1394296341Sdelphij               sizeof(s->s3->write_sequence));
1395296341Sdelphij    }
1396160814Ssimon
1397296341Sdelphij    s->d1->retransmitting = 0;
1398160814Ssimon
1399296341Sdelphij    (void)BIO_flush(SSL_get_wbio(s));
1400296341Sdelphij    return ret;
1401296341Sdelphij}
1402172767Ssimon
1403296341Sdelphijunsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
1404296341Sdelphij                                        unsigned char mt, unsigned long len,
1405296341Sdelphij                                        unsigned long frag_off,
1406296341Sdelphij                                        unsigned long frag_len)
1407296341Sdelphij{
1408296341Sdelphij    /* Don't change sequence numbers while listening */
1409296341Sdelphij    if (frag_off == 0 && !s->d1->listen) {
1410296341Sdelphij        s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
1411296341Sdelphij        s->d1->next_handshake_write_seq++;
1412296341Sdelphij    }
1413296341Sdelphij
1414296341Sdelphij    dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
1415296341Sdelphij                                 frag_off, frag_len);
1416296341Sdelphij
1417296341Sdelphij    return p += DTLS1_HM_HEADER_LENGTH;
1418296341Sdelphij}
1419296341Sdelphij
1420160814Ssimon/* don't actually do the writing, wait till the MTU has been retrieved */
1421160814Ssimonstatic void
1422160814Ssimondtls1_set_message_header_int(SSL *s, unsigned char mt,
1423296341Sdelphij                             unsigned long len, unsigned short seq_num,
1424296341Sdelphij                             unsigned long frag_off, unsigned long frag_len)
1425296341Sdelphij{
1426296341Sdelphij    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
1427160814Ssimon
1428296341Sdelphij    msg_hdr->type = mt;
1429296341Sdelphij    msg_hdr->msg_len = len;
1430296341Sdelphij    msg_hdr->seq = seq_num;
1431296341Sdelphij    msg_hdr->frag_off = frag_off;
1432296341Sdelphij    msg_hdr->frag_len = frag_len;
1433296341Sdelphij}
1434172767Ssimon
1435160814Ssimonstatic void
1436160814Ssimondtls1_fix_message_header(SSL *s, unsigned long frag_off,
1437296341Sdelphij                         unsigned long frag_len)
1438296341Sdelphij{
1439296341Sdelphij    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
1440160814Ssimon
1441296341Sdelphij    msg_hdr->frag_off = frag_off;
1442296341Sdelphij    msg_hdr->frag_len = frag_len;
1443296341Sdelphij}
1444172767Ssimon
1445296341Sdelphijstatic unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p)
1446296341Sdelphij{
1447296341Sdelphij    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
1448160814Ssimon
1449296341Sdelphij    *p++ = msg_hdr->type;
1450296341Sdelphij    l2n3(msg_hdr->msg_len, p);
1451172767Ssimon
1452296341Sdelphij    s2n(msg_hdr->seq, p);
1453296341Sdelphij    l2n3(msg_hdr->frag_off, p);
1454296341Sdelphij    l2n3(msg_hdr->frag_len, p);
1455172767Ssimon
1456296341Sdelphij    return p;
1457296341Sdelphij}
1458172767Ssimon
1459296341Sdelphijunsigned int dtls1_link_min_mtu(void)
1460296341Sdelphij{
1461296341Sdelphij    return (g_probable_mtu[(sizeof(g_probable_mtu) /
1462296341Sdelphij                            sizeof(g_probable_mtu[0])) - 1]);
1463296341Sdelphij}
1464160814Ssimon
1465296341Sdelphijunsigned int dtls1_min_mtu(SSL *s)
1466296341Sdelphij{
1467296341Sdelphij    return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
1468296341Sdelphij}
1469160814Ssimon
1470160814Ssimonvoid
1471160814Ssimondtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
1472296341Sdelphij{
1473296341Sdelphij    memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
1474296341Sdelphij    msg_hdr->type = *(data++);
1475296341Sdelphij    n2l3(data, msg_hdr->msg_len);
1476160814Ssimon
1477296341Sdelphij    n2s(data, msg_hdr->seq);
1478296341Sdelphij    n2l3(data, msg_hdr->frag_off);
1479296341Sdelphij    n2l3(data, msg_hdr->frag_len);
1480296341Sdelphij}
1481172767Ssimon
1482296341Sdelphijvoid dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
1483296341Sdelphij{
1484296341Sdelphij    memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
1485172767Ssimon
1486296341Sdelphij    ccs_hdr->type = *(data++);
1487296341Sdelphij}
1488238405Sjkim
1489238405Sjkimint dtls1_shutdown(SSL *s)
1490296341Sdelphij{
1491296341Sdelphij    int ret;
1492238405Sjkim#ifndef OPENSSL_NO_SCTP
1493296341Sdelphij    if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
1494296341Sdelphij        !(s->shutdown & SSL_SENT_SHUTDOWN)) {
1495296341Sdelphij        ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
1496296341Sdelphij        if (ret < 0)
1497296341Sdelphij            return -1;
1498238405Sjkim
1499296341Sdelphij        if (ret == 0)
1500296341Sdelphij            BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1,
1501296341Sdelphij                     NULL);
1502296341Sdelphij    }
1503238405Sjkim#endif
1504296341Sdelphij    ret = ssl3_shutdown(s);
1505238405Sjkim#ifndef OPENSSL_NO_SCTP
1506296341Sdelphij    BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
1507238405Sjkim#endif
1508296341Sdelphij    return ret;
1509296341Sdelphij}
1510238405Sjkim
1511238405Sjkim#ifndef OPENSSL_NO_HEARTBEATS
1512296341Sdelphijint dtls1_process_heartbeat(SSL *s)
1513296341Sdelphij{
1514296341Sdelphij    unsigned char *p = &s->s3->rrec.data[0], *pl;
1515296341Sdelphij    unsigned short hbtype;
1516296341Sdelphij    unsigned int payload;
1517296341Sdelphij    unsigned int padding = 16;  /* Use minimum padding */
1518238405Sjkim
1519296341Sdelphij    if (s->msg_callback)
1520296341Sdelphij        s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
1521296341Sdelphij                        &s->s3->rrec.data[0], s->s3->rrec.length,
1522296341Sdelphij                        s, s->msg_callback_arg);
1523264266Sdelphij
1524296341Sdelphij    /* Read type and payload length first */
1525296341Sdelphij    if (1 + 2 + 16 > s->s3->rrec.length)
1526296341Sdelphij        return 0;               /* silently discard */
1527296341Sdelphij    if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)
1528296341Sdelphij        return 0;               /* silently discard per RFC 6520 sec. 4 */
1529273399Sdelphij
1530296341Sdelphij    hbtype = *p++;
1531296341Sdelphij    n2s(p, payload);
1532296341Sdelphij    if (1 + 2 + payload + 16 > s->s3->rrec.length)
1533296341Sdelphij        return 0;               /* silently discard per RFC 6520 sec. 4 */
1534296341Sdelphij    pl = p;
1535238405Sjkim
1536296341Sdelphij    if (hbtype == TLS1_HB_REQUEST) {
1537296341Sdelphij        unsigned char *buffer, *bp;
1538296341Sdelphij        unsigned int write_length = 1 /* heartbeat type */  +
1539296341Sdelphij            2 /* heartbeat length */  +
1540296341Sdelphij            payload + padding;
1541296341Sdelphij        int r;
1542238405Sjkim
1543296341Sdelphij        if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
1544296341Sdelphij            return 0;
1545264266Sdelphij
1546296341Sdelphij        /*
1547296341Sdelphij         * Allocate memory for the response, size is 1 byte message type,
1548296341Sdelphij         * plus 2 bytes payload length, plus payload, plus padding
1549296341Sdelphij         */
1550296341Sdelphij        buffer = OPENSSL_malloc(write_length);
1551296341Sdelphij        bp = buffer;
1552238405Sjkim
1553296341Sdelphij        /* Enter response type, length and copy payload */
1554296341Sdelphij        *bp++ = TLS1_HB_RESPONSE;
1555296341Sdelphij        s2n(payload, bp);
1556296341Sdelphij        memcpy(bp, pl, payload);
1557296341Sdelphij        bp += payload;
1558296341Sdelphij        /* Random padding */
1559296341Sdelphij        if (RAND_pseudo_bytes(bp, padding) < 0) {
1560296341Sdelphij            OPENSSL_free(buffer);
1561296341Sdelphij            return -1;
1562296341Sdelphij        }
1563238405Sjkim
1564296341Sdelphij        r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
1565238405Sjkim
1566296341Sdelphij        if (r >= 0 && s->msg_callback)
1567296341Sdelphij            s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
1568296341Sdelphij                            buffer, write_length, s, s->msg_callback_arg);
1569238405Sjkim
1570296341Sdelphij        OPENSSL_free(buffer);
1571238405Sjkim
1572296341Sdelphij        if (r < 0)
1573296341Sdelphij            return r;
1574296341Sdelphij    } else if (hbtype == TLS1_HB_RESPONSE) {
1575296341Sdelphij        unsigned int seq;
1576238405Sjkim
1577296341Sdelphij        /*
1578296341Sdelphij         * We only send sequence numbers (2 bytes unsigned int), and 16
1579296341Sdelphij         * random bytes, so we just try to read the sequence number
1580296341Sdelphij         */
1581296341Sdelphij        n2s(pl, seq);
1582238405Sjkim
1583296341Sdelphij        if (payload == 18 && seq == s->tlsext_hb_seq) {
1584296341Sdelphij            dtls1_stop_timer(s);
1585296341Sdelphij            s->tlsext_hb_seq++;
1586296341Sdelphij            s->tlsext_hb_pending = 0;
1587296341Sdelphij        }
1588296341Sdelphij    }
1589238405Sjkim
1590296341Sdelphij    return 0;
1591296341Sdelphij}
1592238405Sjkim
1593296341Sdelphijint dtls1_heartbeat(SSL *s)
1594296341Sdelphij{
1595296341Sdelphij    unsigned char *buf, *p;
1596296341Sdelphij    int ret = -1;
1597296341Sdelphij    unsigned int payload = 18;  /* Sequence number + random bytes */
1598296341Sdelphij    unsigned int padding = 16;  /* Use minimum padding */
1599238405Sjkim
1600296341Sdelphij    /* Only send if peer supports and accepts HB requests... */
1601296341Sdelphij    if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
1602296341Sdelphij        s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) {
1603296341Sdelphij        SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
1604296341Sdelphij        return -1;
1605296341Sdelphij    }
1606238405Sjkim
1607296341Sdelphij    /* ...and there is none in flight yet... */
1608296341Sdelphij    if (s->tlsext_hb_pending) {
1609296341Sdelphij        SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PENDING);
1610296341Sdelphij        return -1;
1611296341Sdelphij    }
1612238405Sjkim
1613296341Sdelphij    /* ...and no handshake in progress. */
1614296341Sdelphij    if (SSL_in_init(s) || s->in_handshake) {
1615296341Sdelphij        SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_UNEXPECTED_MESSAGE);
1616296341Sdelphij        return -1;
1617296341Sdelphij    }
1618238405Sjkim
1619296341Sdelphij    /*
1620296341Sdelphij     * Check if padding is too long, payload and padding must not exceed 2^14
1621296341Sdelphij     * - 3 = 16381 bytes in total.
1622296341Sdelphij     */
1623296341Sdelphij    OPENSSL_assert(payload + padding <= 16381);
1624238405Sjkim
1625296341Sdelphij    /*-
1626296341Sdelphij     * Create HeartBeat message, we just use a sequence number
1627296341Sdelphij     * as payload to distuingish different messages and add
1628296341Sdelphij     * some random stuff.
1629296341Sdelphij     *  - Message Type, 1 byte
1630296341Sdelphij     *  - Payload Length, 2 bytes (unsigned int)
1631296341Sdelphij     *  - Payload, the sequence number (2 bytes uint)
1632296341Sdelphij     *  - Payload, random bytes (16 bytes uint)
1633296341Sdelphij     *  - Padding
1634296341Sdelphij     */
1635296341Sdelphij    buf = OPENSSL_malloc(1 + 2 + payload + padding);
1636296341Sdelphij    p = buf;
1637296341Sdelphij    /* Message Type */
1638296341Sdelphij    *p++ = TLS1_HB_REQUEST;
1639296341Sdelphij    /* Payload length (18 bytes here) */
1640296341Sdelphij    s2n(payload, p);
1641296341Sdelphij    /* Sequence number */
1642296341Sdelphij    s2n(s->tlsext_hb_seq, p);
1643296341Sdelphij    /* 16 random bytes */
1644296341Sdelphij    if (RAND_pseudo_bytes(p, 16) < 0)
1645296341Sdelphij        goto err;
1646296341Sdelphij    p += 16;
1647296341Sdelphij    /* Random padding */
1648296341Sdelphij    if (RAND_pseudo_bytes(p, padding) < 0)
1649296341Sdelphij        goto err;
1650238405Sjkim
1651296341Sdelphij    ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
1652296341Sdelphij    if (ret >= 0) {
1653296341Sdelphij        if (s->msg_callback)
1654296341Sdelphij            s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
1655296341Sdelphij                            buf, 3 + payload + padding,
1656296341Sdelphij                            s, s->msg_callback_arg);
1657238405Sjkim
1658296341Sdelphij        dtls1_start_timer(s);
1659296341Sdelphij        s->tlsext_hb_pending = 1;
1660296341Sdelphij    }
1661238405Sjkim
1662296341Sdelphijerr:
1663296341Sdelphij    OPENSSL_free(buf);
1664238405Sjkim
1665296341Sdelphij    return ret;
1666296341Sdelphij}
1667238405Sjkim#endif
1668