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