summaryrefslogtreecommitdiffstats
path: root/ssl/d1_both.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-01-22 03:29:12 +0000
committerMatt Caswell <matt@openssl.org>2015-01-22 09:31:38 +0000
commitae5c8664e587f2445c8e4eb436cffbb64af4f6b8 (patch)
tree6d5b2cbee6396484f83126f8c7e7a36b9777a652 /ssl/d1_both.c
parentaae3233e1e08e9f11742f8f351af5c98cd8add16 (diff)
Run util/openssl-format-source -v -c .
Reviewed-by: Tim Hudson <tjh@openssl.org>
Diffstat (limited to 'ssl/d1_both.c')
-rw-r--r--ssl/d1_both.c2634
1 files changed, 1307 insertions, 1327 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 99a067cbe9..d731d47150 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -1,7 +1,7 @@
/* ssl/d1_both.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -62,21 +62,21 @@
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
- *
+ *
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
+ *
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -91,10 +91,10 @@
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
+ * 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
+ *
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -106,7 +106,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
+ *
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
@@ -126,1418 +126,1398 @@
#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
- if ((end) - (start) <= 8) { \
- long ii; \
- for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
- } else { \
- long ii; \
- bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
- for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
- bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
- } }
+ if ((end) - (start) <= 8) { \
+ long ii; \
+ for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
+ } else { \
+ long ii; \
+ bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
+ for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
+ bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
+ } }
#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
- long ii; \
- OPENSSL_assert((msg_len) > 0); \
- is_complete = 1; \
- if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
- if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
- if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
+ long ii; \
+ OPENSSL_assert((msg_len) > 0); \
+ is_complete = 1; \
+ if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
+ if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
+ if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
#if 0
-#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
- long ii; \
- printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
- printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
- printf("\n"); }
+# define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
+ long ii; \
+ printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
+ printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
+ printf("\n"); }
#endif
-static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
-static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
+static unsigned char bitmask_start_values[] =
+ { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
+static unsigned char bitmask_end_values[] =
+ { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
/* XDTLS: figure out the right values */
-static const unsigned int g_probable_mtu[] = {1500, 512, 256};
+static const unsigned int g_probable_mtu[] = { 1500, 512, 256 };
-static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
- unsigned long frag_len);
-static unsigned char *dtls1_write_message_header(SSL *s,
- unsigned char *p);
+static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
+ unsigned long frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
- unsigned long len, unsigned short seq_num, unsigned long frag_off,
- unsigned long frag_len);
-static long dtls1_get_message_fragment(SSL *s, int st1, int stn,
- long max, int *ok);
-
-static hm_fragment *
-dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
- {
- hm_fragment *frag = NULL;
- unsigned char *buf = NULL;
- unsigned char *bitmask = NULL;
-
- frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
- if ( frag == NULL)
- return NULL;
-
- if (frag_len)
- {
- buf = (unsigned char *)OPENSSL_malloc(frag_len);
- if ( buf == NULL)
- {
- OPENSSL_free(frag);
- return NULL;
- }
- }
-
- /* zero length fragment gets zero frag->fragment */
- frag->fragment = buf;
-
- /* Initialize reassembly bitmask if necessary */
- if (reassembly)
- {
- bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
- if (bitmask == NULL)
- {
- if (buf != NULL) OPENSSL_free(buf);
- OPENSSL_free(frag);
- return NULL;
- }
- memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
- }
-
- frag->reassembly = bitmask;
-
- return frag;
- }
+ unsigned long len,
+ unsigned short seq_num,
+ unsigned long frag_off,
+ unsigned long frag_len);
+static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max,
+ int *ok);
+
+static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
+ int reassembly)
+{
+ hm_fragment *frag = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *bitmask = NULL;
+
+ frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
+ if (frag == NULL)
+ return NULL;
+
+ if (frag_len) {
+ buf = (unsigned char *)OPENSSL_malloc(frag_len);
+ if (buf == NULL) {
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ /* zero length fragment gets zero frag->fragment */
+ frag->fragment = buf;
+
+ /* Initialize reassembly bitmask if necessary */
+ if (reassembly) {
+ bitmask =
+ (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
+ if (bitmask == NULL) {
+ if (buf != NULL)
+ OPENSSL_free(buf);
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
+ }
+
+ frag->reassembly = bitmask;
+
+ return frag;
+}
void dtls1_hm_fragment_free(hm_fragment *frag)
- {
-
- if (frag->msg_header.is_ccs)
- {
- EVP_CIPHER_CTX_free(frag->msg_header.saved_retransmit_state.enc_write_ctx);
- EVP_MD_CTX_destroy(frag->msg_header.saved_retransmit_state.write_hash);
- }
- if (frag->fragment) OPENSSL_free(frag->fragment);
- if (frag->reassembly) OPENSSL_free(frag->reassembly);
- OPENSSL_free(frag);
- }
+{
+
+ if (frag->msg_header.is_ccs) {
+ EVP_CIPHER_CTX_free(frag->msg_header.
+ saved_retransmit_state.enc_write_ctx);
+ EVP_MD_CTX_destroy(frag->msg_header.
+ saved_retransmit_state.write_hash);
+ }
+ if (frag->fragment)
+ OPENSSL_free(frag->fragment);
+ if (frag->reassembly)
+ OPENSSL_free(frag->reassembly);
+ OPENSSL_free(frag);
+}
static int dtls1_query_mtu(SSL *s)
{
- if(s->d1->link_mtu)
- {
- s->d1->mtu = s->d1->link_mtu-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
- s->d1->link_mtu = 0;
- }
-
- /* AHA! Figure out the MTU, and stick to the right size */
- if (s->d1->mtu < dtls1_min_mtu(s))
- {
- if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
- {
- s->d1->mtu =
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
-
- /* I've seen the kernel return bogus numbers when it doesn't know
- * (initial write), so just make sure we have a reasonable number */
- if (s->d1->mtu < dtls1_min_mtu(s))
- {
- /* Set to min mtu */
- s->d1->mtu = dtls1_min_mtu(s);
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
- s->d1->mtu, NULL);
- }
- }
- else
- return 0;
- }
- return 1;
+ if (s->d1->link_mtu) {
+ s->d1->mtu =
+ s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+ s->d1->link_mtu = 0;
+ }
+
+ /* AHA! Figure out the MTU, and stick to the right size */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ s->d1->mtu =
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+
+ /*
+ * I've seen the kernel return bogus numbers when it doesn't know
+ * (initial write), so just make sure we have a reasonable number
+ */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ /* Set to min mtu */
+ s->d1->mtu = dtls1_min_mtu(s);
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
+ s->d1->mtu, NULL);
+ }
+ } else
+ return 0;
+ }
+ return 1;
}
-/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
int dtls1_do_write(SSL *s, int type)
- {
- int ret;
- unsigned int curr_mtu;
- int retry = 1;
- unsigned int len, frag_off, mac_size, blocksize, used_len;
-
- if(!dtls1_query_mtu(s))
- return -1;
-
- OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something reasonable now */
-
- if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
- OPENSSL_assert(s->init_num ==
- (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
-
- if (s->write_hash)
- {
- if (s->enc_write_ctx && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE)
- mac_size = 0;
- else
- mac_size = EVP_MD_CTX_size(s->write_hash);
- }
- else
- mac_size = 0;
-
- if (s->enc_write_ctx &&
- (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
- blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
- else
- blocksize = 0;
-
- frag_off = 0;
- /* s->init_num shouldn't ever be < 0...but just in case */
- while(s->init_num > 0)
- {
- used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
- + mac_size + blocksize;
- if(s->d1->mtu > used_len)
- curr_mtu = s->d1->mtu - used_len;
- else
- curr_mtu = 0;
-
- if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
- {
- /* grr.. we could get an error if MTU picked was wrong */
- ret = BIO_flush(SSL_get_wbio(s));
- if ( ret <= 0)
- return ret;
- used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
- if(s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH)
- {
- curr_mtu = s->d1->mtu - used_len;
- }
- else
- {
- /* Shouldn't happen */
- return -1;
- }
- }
-
- /* We just checked that s->init_num > 0 so this cast should be safe */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
-
- /* Shouldn't ever happen */
- if(len > INT_MAX)
- len = INT_MAX;
-
- /* XDTLS: this function is too long. split out the CCS part */
- if ( type == SSL3_RT_HANDSHAKE)
- {
- if ( s->init_off != 0)
- {
- OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
- s->init_off -= DTLS1_HM_HEADER_LENGTH;
- s->init_num += DTLS1_HM_HEADER_LENGTH;
-
- /* We just checked that s->init_num > 0 so this cast should be safe */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
- }
-
- /* Shouldn't ever happen */
- if(len > INT_MAX)
- len = INT_MAX;
-
- if ( len < DTLS1_HM_HEADER_LENGTH )
- {
- /*
- * len is so small that we really can't do anything sensible
- * so fail
- */
- return -1;
- }
- dtls1_fix_message_header(s, frag_off,
- len - DTLS1_HM_HEADER_LENGTH);
-
- dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);
- }
-
- ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
- len);
- if (ret < 0)
- {
- /* might need to update MTU here, but we don't know
- * which previous packet caused the failure -- so can't
- * really retransmit anything. continue as if everything
- * is fine and wait for an alert to handle the
- * retransmit
- */
- if ( retry && BIO_ctrl(SSL_get_wbio(s),
- BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 )
- {
- if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
- {
- if(!dtls1_query_mtu(s))
- return -1;
- /* Have one more go */
- retry = 0;
- }
- else
- return -1;
- }
- else
- {
- return(-1);
- }
- }
- else
- {
-
- /* bad if this assert fails, only part of the handshake
- * message got sent. but why would this happen? */
- OPENSSL_assert(len == (unsigned int)ret);
-
- if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
- {
- /* should not be done for 'Hello Request's, but in that case
- * we'll ignore the result anyway */
- unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
- const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
- int xlen;
-
- if (frag_off == 0 && s->version != DTLS1_BAD_VER)
- {
- /* reconstruct message header is if it
- * is being sent in single fragment */
- *p++ = msg_hdr->type;
- l2n3(msg_hdr->msg_len,p);
- s2n (msg_hdr->seq,p);
- l2n3(0,p);
- l2n3(msg_hdr->msg_len,p);
- p -= DTLS1_HM_HEADER_LENGTH;
- xlen = ret;
- }
- else
- {
- p += DTLS1_HM_HEADER_LENGTH;
- xlen = ret - DTLS1_HM_HEADER_LENGTH;
- }
-
- ssl3_finish_mac(s, p, xlen);
- }
-
- if (ret == s->init_num)
- {
- if (s->msg_callback)
- s->msg_callback(1, s->version, type, s->init_buf->data,
- (size_t)(s->init_off + s->init_num), s,
- s->msg_callback_arg);
-
- s->init_off = 0; /* done writing this message */
- s->init_num = 0;
-
- return(1);
- }
- s->init_off+=ret;
- s->init_num-=ret;
- frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
- }
- }
- return(0);
- }
-
-
-/* Obtain handshake message of message type 'mt' (any if mt == -1),
- * maximum acceptable body length 'max'.
- * Read an entire handshake message. Handshake messages arrive in
- * fragments.
+{
+ int ret;
+ unsigned int curr_mtu;
+ int retry = 1;
+ unsigned int len, frag_off, mac_size, blocksize, used_len;
+
+ if (!dtls1_query_mtu(s))
+ return -1;
+
+ OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something
+ * reasonable now */
+
+ if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
+ OPENSSL_assert(s->init_num ==
+ (int)s->d1->w_msg_hdr.msg_len +
+ DTLS1_HM_HEADER_LENGTH);
+
+ if (s->write_hash) {
+ if (s->enc_write_ctx
+ && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE)
+ mac_size = 0;
+ else
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ } else
+ mac_size = 0;
+
+ if (s->enc_write_ctx &&
+ (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
+ blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
+ else
+ blocksize = 0;
+
+ frag_off = 0;
+ /* s->init_num shouldn't ever be < 0...but just in case */
+ while (s->init_num > 0) {
+ used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
+ + mac_size + blocksize;
+ if (s->d1->mtu > used_len)
+ curr_mtu = s->d1->mtu - used_len;
+ else
+ curr_mtu = 0;
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * grr.. we could get an error if MTU picked was wrong
+ */
+ ret = BIO_flush(SSL_get_wbio(s));
+ if (ret <= 0)
+ return ret;
+ used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
+ if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
+ curr_mtu = s->d1->mtu - used_len;
+ } else {
+ /* Shouldn't happen */
+ return -1;
+ }
+ }
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+
+ /* Shouldn't ever happen */
+ if (len > INT_MAX)
+ len = INT_MAX;
+
+ /*
+ * XDTLS: this function is too long. split out the CCS part
+ */
+ if (type == SSL3_RT_HANDSHAKE) {
+ if (s->init_off != 0) {
+ OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should
+ * be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+ }
+
+ /* Shouldn't ever happen */
+ if (len > INT_MAX)
+ len = INT_MAX;
+
+ if (len < DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * len is so small that we really can't do anything sensible
+ * so fail
+ */
+ return -1;
+ }
+ dtls1_fix_message_header(s, frag_off,
+ len - DTLS1_HM_HEADER_LENGTH);
+
+ dtls1_write_message_header(s,
+ (unsigned char *)&s->init_buf->
+ data[s->init_off]);
+ }
+
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off],
+ len);
+ if (ret < 0) {
+ /*
+ * might need to update MTU here, but we don't know which
+ * previous packet caused the failure -- so can't really
+ * retransmit anything. continue as if everything is fine and
+ * wait for an alert to handle the retransmit
+ */
+ if (retry && BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ if (!dtls1_query_mtu(s))
+ return -1;
+ /* Have one more go */
+ retry = 0;
+ } else
+ return -1;
+ } else {
+ return (-1);
+ }
+ } else {
+
+ /*
+ * bad if this assert fails, only part of the handshake message
+ * got sent. but why would this happen?
+ */
+ OPENSSL_assert(len == (unsigned int)ret);
+
+ if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
+ /*
+ * should not be done for 'Hello Request's, but in that case
+ * we'll ignore the result anyway
+ */
+ unsigned char *p =
+ (unsigned char *)&s->init_buf->data[s->init_off];
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ int xlen;
+
+ if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
+ /*
+ * reconstruct message header is if it is being sent in
+ * single fragment
+ */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ p -= DTLS1_HM_HEADER_LENGTH;
+ xlen = ret;
+ } else {
+ p += DTLS1_HM_HEADER_LENGTH;
+ xlen = ret - DTLS1_HM_HEADER_LENGTH;
+ }
+
+ ssl3_finish_mac(s, p, xlen);
+ }
+
+ if (ret == s->init_num) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, type, s->init_buf->data,
+ (size_t)(s->init_off + s->init_num), s,
+ s->msg_callback_arg);
+
+ s->init_off = 0; /* done writing this message */
+ s->init_num = 0;
+
+ return (1);
+ }
+ s->init_off += ret;
+ s->init_num -= ret;
+ frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Obtain handshake message of message type 'mt' (any if mt == -1), maximum
+ * acceptable body length 'max'. Read an entire handshake message. Handshake
+ * messages arrive in fragments.
*/
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
- {
- int i, al;
- struct hm_header_st *msg_hdr;
- unsigned char *p;
- unsigned long msg_len;
-
- /* s3->tmp is used to store messages that are unexpected, caused
- * by the absence of an optional handshake message */
- if (s->s3->tmp.reuse_message)
- {
- s->s3->tmp.reuse_message=0;
- if ((mt >= 0) && (s->s3->tmp.message_type != mt))
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
- *ok=1;
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- s->init_num = (int)s->s3->tmp.message_size;
- return s->init_num;
- }
-
- msg_hdr = &s->d1->r_msg_hdr;
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-
-again:
- i = dtls1_get_message_fragment(s, st1, stn, max, ok);
- if ( i == DTLS1_HM_BAD_FRAGMENT ||
- i == DTLS1_HM_FRAGMENT_RETRY)
- {
- /* bad fragment received */
- goto again;
- }
- else if ( i <= 0 && !*ok)
- {
- return i;
- }
-
- p = (unsigned char *)s->init_buf->data;
- msg_len = msg_hdr->msg_len;
-
- /* reconstruct message header */
- *(p++) = msg_hdr->type;
- l2n3(msg_len,p);
- s2n (msg_hdr->seq,p);
- l2n3(0,p);
- l2n3(msg_len,p);
- if (s->version != DTLS1_BAD_VER) {
- p -= DTLS1_HM_HEADER_LENGTH;
- msg_len += DTLS1_HM_HEADER_LENGTH;
- }
-
- ssl3_finish_mac(s, p, msg_len);
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, msg_len,
- s, s->msg_callback_arg);
-
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-
- /* Don't change sequence numbers while listening */
- if (!s->d1->listen)
- s->d1->handshake_read_seq++;
-
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- return s->init_num;
-
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- *ok = 0;
- return -1;
- }
-
-
-static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
- {
- size_t frag_off,frag_len,msg_len;
-
- msg_len = msg_hdr->msg_len;
- frag_off = msg_hdr->frag_off;
- frag_len = msg_hdr->frag_len;
-
- /* sanity checking */
- if ( (frag_off+frag_len) > msg_len)
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- if ( (frag_off+frag_len) > (unsigned long)max)
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
- {
- /* msg_len is limited to 2^24, but is effectively checked
- * against max above */
- if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH))
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
- return SSL_AD_INTERNAL_ERROR;
- }
-
- s->s3->tmp.message_size = msg_len;
- s->d1->r_msg_hdr.msg_len = msg_len;
- s->s3->tmp.message_type = msg_hdr->type;
- s->d1->r_msg_hdr.type = msg_hdr->type;
- s->d1->r_msg_hdr.seq = msg_hdr->seq;
- }
- else if (msg_len != s->d1->r_msg_hdr.msg_len)
- {
- /* They must be playing with us! BTW, failure to enforce
- * upper limit would open possibility for buffer overrun. */
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- return 0; /* no error */
- }
+{
+ int i, al;
+ struct hm_header_st *msg_hdr;
+ unsigned char *p;
+ unsigned long msg_len;
+
+ /*
+ * s3->tmp is used to store messages that are unexpected, caused by the
+ * absence of an optional handshake message
+ */
+ if (s->s3->tmp.reuse_message) {
+ s->s3->tmp.reuse_message = 0;
+ if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ *ok = 1;
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ s->init_num = (int)s->s3->tmp.message_size;
+ return s->init_num;
+ }
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+ again:
+ i = dtls1_get_message_fragment(s, st1, stn, max, ok);
+ if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) {
+ /* bad fragment received */
+ goto again;
+ } else if (i <= 0 && !*ok) {
+ return i;
+ }
+
+ p = (unsigned char *)s->init_buf->data;
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ ssl3_finish_mac(s, p, msg_len);
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, msg_len, s, s->msg_callback_arg);
+
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+ /* Don't change sequence numbers while listening */
+ if (!s->d1->listen)
+ s->d1->handshake_read_seq++;
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ return s->init_num;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ *ok = 0;
+ return -1;
+}
+static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr,
+ int max)
+{
+ size_t frag_off, frag_len, msg_len;
+
+ msg_len = msg_hdr->msg_len;
+ frag_off = msg_hdr->frag_off;
+ frag_len = msg_hdr->frag_len;
+
+ /* sanity checking */
+ if ((frag_off + frag_len) > msg_len) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if ((frag_off + frag_len) > (unsigned long)max) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
+ /*
+ * msg_len is limited to 2^24, but is effectively checked against max
+ * above
+ */
+ if (!BUF_MEM_grow_clean
+ (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
+ return SSL_AD_INTERNAL_ERROR;
+ }
+
+ s->s3->tmp.message_size = msg_len;
+ s->d1->r_msg_hdr.msg_len = msg_len;
+ s->s3->tmp.message_type = msg_hdr->type;
+ s->d1->r_msg_hdr.type = msg_hdr->type;
+ s->d1->r_msg_hdr.seq = msg_hdr->seq;
+ } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
+ /*
+ * They must be playing with us! BTW, failure to enforce upper limit
+ * would open possibility for buffer overrun.
+ */
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ return 0; /* no error */
+}
-static int
-dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
- {
- /*-
- * (0) check whether the desired fragment is available
- * if so:
- * (1) copy over the fragment to s->init_buf->data[]
- * (2) update s->init_num
- */
- pitem *item;
- hm_fragment *frag;
- int al;
-
- *ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if ( item == NULL)
- return 0;
-
- frag = (hm_fragment *)item->data;
-
- /* Don't return if reassembly still in progress */
- if (frag->reassembly != NULL)
- return 0;
-
- if ( s->d1->handshake_read_seq == frag->msg_header.seq)
- {
- unsigned long frag_len = frag->msg_header.frag_len;
- pqueue_pop(s->d1->buffered_messages);
-
- al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
-
- if (al==0) /* no alert */
- {
- unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
- memcpy(&p[frag->msg_header.frag_off],
- frag->fragment,frag->msg_header.frag_len);
- }
-
- dtls1_hm_fragment_free(frag);
- pitem_free(item);
-
- if (al==0)
- {
- *ok = 1;
- return frag_len;
- }
-
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- s->init_num = 0;
- *ok = 0;
- return -1;
- }
- else
- return 0;
- }
-
-/* dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
- * be greater if the maximum certificate list size requires it. */
+static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
+{
+ /*-
+ * (0) check whether the desired fragment is available
+ * if so:
+ * (1) copy over the fragment to s->init_buf->data[]
+ * (2) update s->init_num
+ */
+ pitem *item;
+ hm_fragment *frag;
+ int al;
+
+ *ok = 0;
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ /* Don't return if reassembly still in progress */
+ if (frag->reassembly != NULL)
+ return 0;
+
+ if (s->d1->handshake_read_seq == frag->msg_header.seq) {
+ unsigned long frag_len = frag->msg_header.frag_len;
+ pqueue_pop(s->d1->buffered_messages);