diff options
author | simon <simon@FreeBSD.org> | 2007-10-18 20:19:33 +0000 |
---|---|---|
committer | simon <simon@FreeBSD.org> | 2007-10-18 20:19:33 +0000 |
commit | 8f21bfc1756ff75fb4caf97e5c9612a4d7106243 (patch) | |
tree | 18668034f47decf1b245c279a6825a76c0eb0425 | |
parent | 8e9898839e1cab4cb5affa37125bb12602040d78 (diff) | |
download | FreeBSD-src-8f21bfc1756ff75fb4caf97e5c9612a4d7106243.zip FreeBSD-src-8f21bfc1756ff75fb4caf97e5c9612a4d7106243.tar.gz |
Import DTLS security fix from upstream OpenSSL_0_9_8-stable branch.
From the OpenSSL advisory:
Andy Polyakov discovered a flaw in OpenSSL's DTLS
implementation which could lead to the compromise of clients
and servers with DTLS enabled.
DTLS is a datagram variant of TLS specified in RFC 4347 first
supported in OpenSSL version 0.9.8. Note that the
vulnerabilities do not affect SSL and TLS so only clients and
servers explicitly using DTLS are affected.
We believe this flaw will permit remote code execution.
Security: CVE-2007-4995
Security: http://www.openssl.org/news/secadv_20071012.txt
-rw-r--r-- | crypto/openssl/ssl/d1_both.c | 1150 | ||||
-rw-r--r-- | crypto/openssl/ssl/dtls1.h | 7 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl.h | 1 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl_err.c | 1 |
4 files changed, 544 insertions, 615 deletions
diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index b746a50..22bd28a 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -138,38 +138,40 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long frag_len); static int dtls1_retransmit_buffered_messages(SSL *s); static long dtls1_get_message_fragment(SSL *s, int st1, int stn, - long max, int *ok); -static void dtls1_process_handshake_fragment(SSL *s, int frag_len); + long max, int *ok); static hm_fragment * dtls1_hm_fragment_new(unsigned long frag_len) - { - hm_fragment *frag = NULL; - unsigned char *buf = NULL; - - frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); - if ( frag == NULL) - return NULL; - - buf = (unsigned char *)OPENSSL_malloc(frag_len - + DTLS1_HM_HEADER_LENGTH); - if ( buf == NULL) - { - OPENSSL_free(frag); - return NULL; - } - - frag->fragment = buf; - - return frag; - } + { + hm_fragment *frag = NULL; + unsigned char *buf = 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; + + return frag; + } static void dtls1_hm_fragment_free(hm_fragment *frag) - { - OPENSSL_free(frag->fragment); - OPENSSL_free(frag); - } + { + if (frag->fragment) OPENSSL_free(frag->fragment); + OPENSSL_free(frag); + } /* 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) @@ -180,7 +182,7 @@ int dtls1_do_write(SSL *s, int type) /* AHA! Figure out the MTU, and stick to the right size */ 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); @@ -207,7 +209,7 @@ int dtls1_do_write(SSL *s, int type) mtu = curr_mtu; else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0) return ret; - + if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu) { ret = BIO_flush(SSL_get_wbio(s)); @@ -254,11 +256,11 @@ int dtls1_do_write(SSL *s, int type) s->init_off -= DTLS1_HM_HEADER_LENGTH; s->init_num += DTLS1_HM_HEADER_LENGTH; - /* write atleast DTLS1_HM_HEADER_LENGTH bytes */ + /* write atleast DTLS1_HM_HEADER_LENGTH bytes */ if ( len <= DTLS1_HM_HEADER_LENGTH) len += DTLS1_HM_HEADER_LENGTH; } - + dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); @@ -286,18 +288,40 @@ int dtls1_do_write(SSL *s, int type) } 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); - + 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 */ - ssl3_finish_mac(s, - (unsigned char *)&s->init_buf->data[s->init_off + - DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH); - + unsigned char *p = &s->init_buf->data[s->init_off]; + const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + int len; + + if (frag_off == 0 && s->client_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; + len = ret; + } + else + { + p += DTLS1_HM_HEADER_LENGTH; + len = ret - DTLS1_HM_HEADER_LENGTH; + } + + ssl3_finish_mac(s, p, len); + } + if (ret == s->init_num) { if (s->msg_callback) @@ -307,7 +331,7 @@ int dtls1_do_write(SSL *s, int type) s->init_off = 0; /* done writing this message */ s->init_num = 0; - + return(1); } s->init_off+=ret; @@ -327,6 +351,7 @@ int dtls1_do_write(SSL *s, int type) 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; /* s3->tmp is used to store messages that are unexpected, caused * by the absence of an optional handshake message */ @@ -344,25 +369,56 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } - + + msg_hdr = &s->d1->r_msg_hdr; do { - if ( s->d1->r_msg_hdr.frag_off == 0) + if ( msg_hdr->frag_off == 0) { /* s->d1->r_message_header.msg_len = 0; */ - memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st)); + memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); } i = dtls1_get_message_fragment(s, st1, stn, max, ok); if ( i == DTLS1_HM_BAD_FRAGMENT || - i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ + i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ continue; else if ( i <= 0 && !*ok) return i; - if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH) + /* Note that s->init_sum is used as a counter summing + * up fragments' lengths: as soon as they sum up to + * handshake packet length, we assume we have got all + * the fragments. Overlapping fragments would cause + * premature termination, so we don't expect overlaps. + * Well, handling overlaps would require something more + * drastic. Indeed, as it is now there is no way to + * tell if out-of-order fragment from the middle was + * the last. '>=' is the best/least we can do to control + * the potential damage caused by malformed overlaps. */ + if ((unsigned int)s->init_num >= msg_hdr->msg_len) { - memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st)); + unsigned char *p = s->init_buf->data; + unsigned long msg_len = msg_hdr->msg_len; + + /* reconstruct message header as if it was + * sent in single fragment */ + *(p++) = msg_hdr->type; + l2n3(msg_len,p); + s2n (msg_hdr->seq,p); + l2n3(0,p); + l2n3(msg_len,p); + if (s->client_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)); s->d1->handshake_read_seq++; /* we just read a handshake message from the other side: @@ -379,11 +435,11 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) * first data segment, but is there a better way? */ dtls1_clear_record_buffer(s); - s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; - return s->init_num - DTLS1_HM_HEADER_LENGTH; + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + return s->init_num; } else - s->d1->r_msg_hdr.frag_off = i; + msg_hdr->frag_off = i; } while(1) ; f_err: @@ -393,161 +449,183 @@ f_err: } -static int -dtls1_retrieve_buffered_fragment(SSL *s, unsigned long *copied) - { - /* (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; - unsigned long overlap; - unsigned char *p; - - item = pqueue_peek(s->d1->buffered_messages); - if ( item == NULL) - return 0; - - frag = (hm_fragment *)item->data; - - if ( s->d1->handshake_read_seq == frag->msg_header.seq && - frag->msg_header.frag_off <= (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH) - { - pqueue_pop(s->d1->buffered_messages); - overlap = s->init_num - DTLS1_HM_HEADER_LENGTH - - frag->msg_header.frag_off; - - p = frag->fragment; - - memcpy(&s->init_buf->data[s->init_num], - p + DTLS1_HM_HEADER_LENGTH + overlap, - frag->msg_header.frag_len - overlap); - - OPENSSL_free(frag->fragment); - OPENSSL_free(frag); - pitem_free(item); - - *copied = frag->msg_header.frag_len - overlap; - return *copied; - } - else - return 0; - } +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; -static int -dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr) -{ - hm_fragment *frag = NULL; - pitem *item = NULL; - PQ_64BIT seq64; + /* 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; + } - frag = dtls1_hm_fragment_new(msg_hdr->frag_len); - if ( frag == NULL) - goto err; + if ( (frag_off+frag_len) > (unsigned long)max) + { + SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SSL_AD_ILLEGAL_PARAMETER; + } - memcpy(frag->fragment, &(s->init_buf->data[s->init_num]), - msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH); + 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,(int)msg_len+DTLS1_HM_HEADER_LENGTH)) + { + SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB); + return SSL_AD_INTERNAL_ERROR; + } - memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + 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 */ + } - pq_64bit_init(&seq64); - pq_64bit_assign_word(&seq64, msg_hdr->seq); - item = pitem_new(seq64, frag); - if ( item == NULL) - goto err; +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; - pq_64bit_free(&seq64); + *ok = 0; + item = pqueue_peek(s->d1->buffered_messages); + if ( item == NULL) + return 0; - pqueue_insert(s->d1->buffered_messages, item); - return 1; + frag = (hm_fragment *)item->data; -err: - if ( frag != NULL) dtls1_hm_fragment_free(frag); - if ( item != NULL) OPENSSL_free(item); - return 0; -} + if ( s->d1->handshake_read_seq == frag->msg_header.seq) + { + pqueue_pop(s->d1->buffered_messages); + al=dtls1_preprocess_fragment(s,&frag->msg_header,max); -static void -dtls1_process_handshake_fragment(SSL *s, int frag_len) - { - unsigned char *p; + if (al==0) /* no alert */ + { + unsigned char *p = s->init_buf->data+DTLS1_HM_HEADER_LENGTH; + memcpy(&p[frag->msg_header.frag_off], + frag->fragment,frag->msg_header.frag_len); + } - p = (unsigned char *)s->init_buf->data; + dtls1_hm_fragment_free(frag); + pitem_free(item); - ssl3_finish_mac(s, &p[s->init_num - frag_len], frag_len); - } + if (al==0) + { + *ok = 1; + return frag->msg_header.frag_len; + } + + ssl3_send_alert(s,SSL3_AL_FATAL,al); + s->init_num = 0; + *ok = 0; + return -1; + } + else + return 0; + } static int -dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok) - { - int i; - unsigned char *p; - - /* make sure there's enough room to read this fragment */ - if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf, - (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num)) - { - SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB); - goto err; - } - - p = (unsigned char *)s->init_buf->data; - - /* read the body of the fragment (header has already been read */ - if ( msg_hdr->frag_len > 0) +dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) +{ + int i=-1; + hm_fragment *frag = NULL; + pitem *item = NULL; + PQ_64BIT seq64; + unsigned long frag_len = msg_hdr->frag_len; + + if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) + goto err; + + if (msg_hdr->seq <= s->d1->handshake_read_seq) { - i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, - &p[s->init_num], - msg_hdr->frag_len,0); - if (i <= 0) + unsigned char devnull [256]; + + while (frag_len) { - *ok = 0; - return i; + i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, + devnull, + frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0); + if (i<=0) goto err; + frag_len -= i; } } - if ( msg_hdr->seq > s->d1->handshake_read_seq) - dtls1_buffer_handshake_fragment(s, msg_hdr); - else - OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq); + frag = dtls1_hm_fragment_new(frag_len); + if ( frag == NULL) + goto err; + + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + + if (frag_len) + { + /* read the body of the fragment (header has already been read */ + i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, + frag->fragment,frag_len,0); + if (i<=0 || (unsigned long)i!=frag_len) + goto err; + } + + pq_64bit_init(&seq64); + pq_64bit_assign_word(&seq64, msg_hdr->seq); + + item = pitem_new(seq64, frag); + pq_64bit_free(&seq64); + if ( item == NULL) + goto err; + + pqueue_insert(s->d1->buffered_messages, item); + return DTLS1_HM_FRAGMENT_RETRY; - return DTLS1_HM_FRAGMENT_RETRY; err: - *ok = 0; - return -1; - } + if ( frag != NULL) dtls1_hm_fragment_free(frag); + if ( item != NULL) OPENSSL_free(item); + *ok = 0; + return i; + } static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) { - unsigned char *p; + unsigned char wire[DTLS1_HM_HEADER_LENGTH]; unsigned long l, frag_off, frag_len; int i,al; struct hm_header_st msg_hdr; - unsigned long overlap; - - /* see if we have the required fragment already */ - if (dtls1_retrieve_buffered_fragment(s, &l)) - { - /* compute MAC, remove fragment headers */ - dtls1_process_handshake_fragment(s, l); - s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; - s->state = stn; - return 1; - } - - /* get a handshake fragment from the record layer */ - p = (unsigned char *)s->init_buf->data; - - /* read handshake message header */ - i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num], + + /* see if we have the required fragment already */ + if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok) + { + if (*ok) s->init_num += frag_len; + return frag_len; + } + + /* read handshake message header */ + i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire, DTLS1_HM_HEADER_LENGTH, 0); if (i <= 0) /* nbio, or an error */ { @@ -555,130 +633,61 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) *ok = 0; return i; } - OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH); - p += s->init_num; - /* parse the message fragment header */ - - dtls1_get_message_header(p, &msg_hdr); + /* parse the message fragment header */ + dtls1_get_message_header(wire, &msg_hdr); - /* - * if this is a future (or stale) message it gets buffered - * (or dropped)--no further processing at this time - */ - if ( msg_hdr.seq != s->d1->handshake_read_seq) - return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); + /* + * if this is a future (or stale) message it gets buffered + * (or dropped)--no further processing at this time + */ + if ( msg_hdr.seq != s->d1->handshake_read_seq) + return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); - l = msg_hdr.msg_len; - frag_off = msg_hdr.frag_off; + l = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; frag_len = msg_hdr.frag_len; - /* sanity checking */ - if ( frag_off + frag_len > l) - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && - p[0] == SSL3_MT_HELLO_REQUEST) - { - /* The server may always send 'Hello Request' messages -- - * we are doing a handshake anyway now, so ignore them - * if their format is correct. Does not count for - * 'Finished' MAC. */ - if (p[1] == 0 && p[2] == 0 &&p[3] == 0) - { - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, - p, DTLS1_HM_HEADER_LENGTH, s, - s->msg_callback_arg); - - s->init_num = 0; - return dtls1_get_message_fragment(s, st1, stn, - max, ok); - } - else /* Incorrectly formated Hello request */ - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - } - - /* XDTLS: do a sanity check on the fragment */ - - s->init_num += i; - - if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ + wire[0] == SSL3_MT_HELLO_REQUEST) { - /* BUF_MEM_grow takes an 'int' parameter */ - if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH)) - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l - + DTLS1_HM_HEADER_LENGTH)) + /* The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them + * if their format is correct. Does not count for + * 'Finished' MAC. */ + if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB); - goto err; + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + wire, DTLS1_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + + s->init_num = 0; + return dtls1_get_message_fragment(s, st1, stn, + max, ok); } - /* Only do this test when we're reading the expected message. - * Stale messages will be dropped and future messages will be buffered */ - if ( l > (unsigned long)max) + else /* Incorrectly formated Hello request */ { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } - - s->s3->tmp.message_size=l; } - if ( frag_len > (unsigned long)max) - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH)) - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - - if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len - + DTLS1_HM_HEADER_LENGTH + s->init_num)) - { - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB); - goto err; - } - - if ( s->d1->r_msg_hdr.frag_off == 0) - { - s->s3->tmp.message_type = msg_hdr.type; - s->d1->r_msg_hdr.type = msg_hdr.type; - s->d1->r_msg_hdr.msg_len = l; - /* s->d1->r_msg_hdr.seq = seq_num; */ - } + if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max))) + goto f_err; /* XDTLS: ressurect this when restart is in place */ s->state=stn; - - /* next state (stn) */ - p = (unsigned char *)s->init_buf->data; if ( frag_len > 0) { + unsigned char *p=s->init_buf->data+DTLS1_HM_HEADER_LENGTH; + i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, - &p[s->init_num], - frag_len,0); - /* XDTLS: fix this--message fragments cannot span multiple packets */ + &p[frag_off],frag_len,0); + /* XDTLS: fix this--message fragments cannot span multiple packets */ if (i <= 0) { s->rwstate=SSL_READING; @@ -689,70 +698,23 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) else i = 0; - /* XDTLS: an incorrectly formatted fragment should cause the - * handshake to fail */ + /* XDTLS: an incorrectly formatted fragment should cause the + * handshake to fail */ OPENSSL_assert(i == (int)frag_len); -#if 0 - /* Successfully read a fragment. - * It may be (1) out of order, or - * (2) it's a repeat, in which case we dump it - * (3) the one we are expecting next (maybe with overlap) - * If it is next one, it may overlap with previously read bytes - */ - - /* case (1): buffer the future fragment - * (we can treat fragments from a future message the same - * as future fragments from the message being currently read, since - * they are sematically simply out of order. - */ - if ( msg_hdr.seq > s->d1->handshake_read_seq || - frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH) - { - dtls1_buffer_handshake_fragment(s, &msg_hdr); - return DTLS1_HM_FRAGMENT_RETRY; - } - - /* case (2): drop the entire fragment, and try again */ - if ( msg_hdr.seq < s->d1->handshake_read_seq || - frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH) - { - s->init_num -= DTLS1_HM_HEADER_LENGTH; - return DTLS1_HM_FRAGMENT_RETRY; - } -#endif + *ok = 1; - /* case (3): received a immediately useful fragment. Determine the - * possible overlap and copy the fragment. - */ - overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off; - - /* retain the header for the first fragment */ - if ( s->init_num > DTLS1_HM_HEADER_LENGTH) - { - memmove(&(s->init_buf->data[s->init_num]), - &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]), - frag_len - overlap); - - s->init_num += frag_len - overlap; - } - else - s->init_num += frag_len; - - dtls1_process_handshake_fragment(s, frag_len - overlap); - - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, - (size_t)s->init_num, s, - s->msg_callback_arg); - *ok=1; - - return s->init_num; + /* Note that s->init_num is *not* used as current offset in + * s->init_buf->data, but as a counter summing up fragments' + * lengths: as soon as they sum up to handshake packet + * length, we assume we have got all the fragments. */ + s->init_num += frag_len; + return frag_len; f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); - s->init_num = 0; -err: + s->init_num = 0; + *ok=0; return(-1); } @@ -790,7 +752,7 @@ int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) /* buffer the message to handle re-xmits */ dtls1_buffer_message(s, 0); - + s->state=b; } @@ -816,9 +778,14 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) *p++=SSL3_MT_CCS; s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; s->d1->next_handshake_write_seq++; - s2n(s->d1->handshake_write_seq,p); - s->init_num=DTLS1_CCS_HEADER_LENGTH; + + if (s->client_version == DTLS1_BAD_VER) + { + s2n(s->d1->handshake_write_seq,p); + s->init_num+=2; + } + s->init_off=0; dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, @@ -915,316 +882,278 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) } int dtls1_read_failed(SSL *s, int code) - { - DTLS1_STATE *state; - BIO *bio; - int send_alert = 0; - - if ( code > 0) - { - fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__); - return 1; - } - - bio = SSL_get_rbio(s); - if ( ! BIO_dgram_recv_timedout(bio)) - { - /* not a timeout, none of our business, - let higher layers handle this. in fact it's probably an error */ - return code; - } - - if ( ! SSL_in_init(s)) /* done, no need to send a retransmit */ - { - BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); - return code; - } - - state = s->d1; - state->timeout.num_alerts++; - if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) - { - /* fail the connection, enough alerts have been sent */ - SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED); - return 0; - } - - state->timeout.read_timeouts++; - if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) - { - send_alert = 1; - state->timeout.read_timeouts = 1; - } - - + { + DTLS1_STATE *state; + BIO *bio; + int send_alert = 0; + + if ( code > 0) + { + fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__); + return 1; + } + + bio = SSL_get_rbio(s); + if ( ! BIO_dgram_recv_timedout(bio)) + { + /* not a timeout, none of our business, + let higher layers handle this. in fact it's probably an error */ + return code; + } + + if ( ! SSL_in_init(s)) /* done, no need to send a retransmit */ + { + BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); + return code; + } + + state = s->d1; + state->timeout.num_alerts++; + if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) + { + /* fail the connection, enough alerts have been sent */ + SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED); + return 0; + } + + state->timeout.read_timeouts++; + if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) + { + send_alert = 1; + state->timeout.read_timeouts = 1; + } + + #if 0 /* for now, each alert contains only one record number */ - item = pqueue_peek(state->rcvd_records); - if ( item ) - { - /* send an alert immediately for all the missing records */ - } - else + item = pqueue_peek(state->rcvd_records); + if ( item ) + { + /* send an alert immediately for all the missing records */ + } + else #endif #if 0 /* no more alert sending, just retransmit the last set of messages */ - if ( send_alert) - ssl3_send_alert(s,SSL3_AL_WARNING, - DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); + if ( send_alert) + ssl3_send_alert(s,SSL3_AL_WARNING, + DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); #endif - return dtls1_retransmit_buffered_messages(s) ; - } + return dtls1_retransmit_buffered_messages(s) ; + } static int dtls1_retransmit_buffered_messages(SSL *s) - { - pqueue sent = s->d1->sent_messages; - piterator iter; - pitem *item; - hm_fragment *frag; - int found = 0; - - iter = pqueue_iterator(sent); - - for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) - { - frag = (hm_fragment *)item->data; - if ( dtls1_retransmit_message(s, frag->msg_header.seq, 0, &found) <= 0 && - found) - { - fprintf(stderr, "dtls1_retransmit_message() failed\n"); - return -1; - } - } - - return 1; - } + { + pqueue sent = s->d1->sent_messages; + piterator iter; + pitem *item; + hm_fragment *frag; + int found = 0; -#if 0 -static dtls1_message_buffer * -dtls1_message_buffer_new(unsigned int len) - { - dtls1_message_buffer *msg_buf; - - msg_buf = (dtls1_message_buffer *) - OPENSSL_malloc(sizeof(dtls1_message_buffer)); - if ( msg_buf == NULL) - return NULL; - - memset(msg_buf, 0x00, sizeof(dtls1_message_buffer)); - - msg_buf->data = (unsigned char *) OPENSSL_malloc(len); - if ( msg_buf->data == NULL) - { - OPENSSL_free(msg_buf); - return NULL; - } - - memset(msg_buf->data, 0x00, len); - return msg_buf; - } -#endif + iter = pqueue_iterator(sent); -#if 0 -static void -dtls1_message_buffer_free(dtls1_message_buffer *msg_buf) - { - if (msg_buf != NULL) - { - OPENSSL_free(msg_buf->data); - OPENSSL_free(msg_buf); - } - } -#endif + for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) + { + frag = (hm_fragment *)item->data; + if ( dtls1_retransmit_message(s, frag->msg_header.seq, 0, &found) <= 0 && + found) + { + fprintf(stderr, "dtls1_retransmit_message() failed\n"); + return -1; + } + } + + return 1; + } int dtls1_buffer_message(SSL *s, int is_ccs) - { - pitem *item; - hm_fragment *frag; + { + pitem *item; + hm_fragment *frag; PQ_64BIT seq64; - /* this function is called immediately after a message has - * been serialized */ - OPENSSL_assert(s->init_off == 0); - - frag = dtls1_hm_fragment_new(s->init_num); - - memcpy(frag->fragment, s->init_buf->data, s->init_num); - - if ( is_ccs) - { - OPENSSL_assert(s->d1->w_msg_hdr.msg_len + - DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num); - } - else - { - OPENSSL_assert(s->d1->w_msg_hdr.msg_len + - DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num); - } - - frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; - frag->msg_header.seq = s->d1->w_msg_hdr.seq; - frag->msg_header.type = s->d1->w_msg_hdr.type; - frag->msg_header.frag_off = 0; - frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; - frag->msg_header.is_ccs = is_ccs; - - pq_64bit_init(&seq64); - pq_64bit_assign_word(&seq64, frag->msg_header.seq); - - item = pitem_new(seq64, frag); - pq_64bit_free(&seq64); - if ( item == NULL) - { - dtls1_hm_fragment_free(frag); - return 0; - } + /* this function is called immediately after a message has + * been serialized */ + OPENSSL_assert(s->init_off == 0); + + frag = dtls1_hm_fragment_new(s->init_num); + + memcpy(frag->fragment, s->init_buf->data, s->init_num); + + if ( is_ccs) + { + OPENSSL_assert(s->d1->w_msg_hdr.msg_len + + DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num); + } + else + { + OPENSSL_assert(s->d1->w_msg_hdr.msg_len + + DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num); + } + + frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.seq = s->d1->w_msg_hdr.seq; + frag->msg_header.type = s->d1->w_msg_hdr.type; + frag->msg_header.frag_off = 0; + frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.is_ccs = is_ccs; + + pq_64bit_init(&seq64); + pq_64bit_assign_word(&seq64, frag->msg_header.seq); + + item = pitem_new(seq64, frag); + pq_64bit_free(&seq64); + if ( item == NULL) + { + dtls1_hm_fragment_free(frag); + return 0; + } #if 0 - fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type); - fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len); - fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num); + fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type); + fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len); + fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num); #endif - pqueue_insert(s->d1->sent_messages, item); - return 1; - } + pqueue_insert(s->d1->sent_messages, item); + return 1; + } int dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, - int *found) - { - int ret; - /* XDTLS: for now assuming that read/writes are blocking */ - pitem *item; - hm_fragment *frag ; - unsigned long header_length; + int *found) + { + int ret; + /* XDTLS: for now assuming that read/writes are blocking */ + pitem *item; + hm_fragment *frag ; + unsigned long header_length; PQ_64BIT seq64; - /* - OPENSSL_assert(s->init_num == 0); - OPENSSL_assert(s->init_off == 0); - */ - - /* XDTLS: the requested message ought to be found, otherwise error */ - pq_64bit_init(&seq64); - pq_64bit_assign_word(&seq64, seq); - - item = pqueue_find(s->d1->sent_messages, seq64); - pq_64bit_free(&seq64); - if ( item == NULL) - { - fprintf(stderr, "retransmit: message %d non-existant\n", seq); - *found = 0; - return 0; - } - - *found = 1; - frag = (hm_fragment *)item->data; - - if ( frag->msg_header.is_ccs) - header_length = DTLS1_CCS_HEADER_LENGTH; - else - header_length = DTLS1_HM_HEADER_LENGTH; - - memcpy(s->init_buf->data, frag->fragment, - frag->msg_header.msg_len + header_length); - s->init_num = frag->msg_header.msg_len + header_length; - - dtls1_set_message_header_int(s, frag->msg_header.type, - frag->msg_header.msg_len, frag->msg_header.seq, 0, - frag->msg_header.frag_len); - - s->d1->retransmitting = 1; - ret = dtls1_do_write(s, frag->msg_header.is_ccs ? - SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); - s->d1->retransmitting = 0; - - BIO_flush(SSL_get_wbio(s)); - return ret; - } + /* + OPENSSL_assert(s->init_num == 0); + OPENSSL_assert(s->init_off == 0); + */ + + /* XDTLS: the requested message ought to be found, otherwise error */ + pq_64bit_init(&seq64); + pq_64bit_assign_word(&seq64, seq); + + item = pqueue_find(s->d1->sent_messages, seq64); + pq_64bit_free(&seq64); + if ( item == NULL) + { + fprintf(stderr, "retransmit: message %d non-existant\n", seq); + *found = 0; + return 0; + } + + *found = 1; + frag = (hm_fragment *)item->data; + + if ( frag->msg_header.is_ccs) + header_length = DTLS1_CCS_HEADER_LENGTH; + else + header_length = DTLS1_HM_HEADER_LENGTH; + + memcpy(s->init_buf->data, frag->fragment, + frag->msg_header.msg_len + header_length); + s->init_num = frag->msg_header.msg_len + header_length; + + dtls1_set_message_header_int(s, frag->msg_header.type, + frag->msg_header.msg_len, frag->msg_header.seq, 0, + frag->msg_header.frag_len); + + s->d1->retransmitting = 1; + ret = dtls1_do_write(s, frag->msg_header.is_ccs ? + SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); + s->d1->retransmitting = 0; + + (void)BIO_flush(SSL_get_wbio(s)); + return ret; + } /* call this function when the buffered messages are no longer needed */ void dtls1_clear_record_buffer(SSL *s) - { - pitem *item; - - for(item = pqueue_pop(s->d1->sent_messages); - item != NULL; item = pqueue_pop(s->d1->sent_messages)) - { - dtls1_hm_fragment_free((hm_fragment *)item->data); - pitem_free(item); - } - } + { + pitem *item; + + for(item = pqueue_pop(s->d1->sent_messages); + item != NULL; item = pqueue_pop(s->d1->sent_messages)) + { + dtls1_hm_fragment_free((hm_fragment *)item->data); + pitem_free(item); + } + } unsigned char * dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, - unsigned long len, unsigned long frag_off, unsigned long frag_len) - { - if ( frag_off == 0) - { - s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; - s->d1->next_handshake_write_seq++; - } - - dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, - frag_off, frag_len); - - return p += DTLS1_HM_HEADER_LENGTH; - } + unsigned long len, unsigned long frag_off, unsigned long frag_len) + { + if ( frag_off == 0) + { + s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; + s->d1->next_handshake_write_seq++; + } + + dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, + frag_off, frag_len); + + return p += DTLS1_HM_HEADER_LENGTH; + } /* don't actually do the writing, wait till the MTU has been retrieved */ 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) - { - struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; - - msg_hdr->type = mt; - msg_hdr->msg_len = len; - msg_hdr->seq = seq_num; - msg_hdr->frag_off = frag_off; - msg_hdr->frag_len = frag_len; -} + unsigned long len, unsigned short seq_num, unsigned long frag_off, + unsigned long frag_len) + { + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->type = mt; + msg_hdr->msg_len = len; + msg_hdr->seq = seq_num; + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; + } static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, - unsigned long frag_len) - { - struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; - - msg_hdr->frag_off = frag_off; - msg_hdr->frag_len = frag_len; - } + unsigned long frag_len) + { + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; + } static unsigned char * dtls1_write_message_header(SSL *s, unsigned char *p) - { - struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; - - *p++ = msg_hdr->type; - l2n3(msg_hdr->msg_len, p); - - s2n(msg_hdr->seq, p); - l2n3(msg_hdr->frag_off, p); - l2n3(msg_hdr->frag_len, p); - - return p; - } + { + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + *p++ = msg_hdr->type; + l2n3(msg_hdr->msg_len, p); + + s2n(msg_hdr->seq, p); + l2n3(msg_hdr->frag_off, p); + l2n3(msg_hdr->frag_len, p); + + return p; + } static unsigned int dtls1_min_mtu(void) - { - return - g_probable_mtu[(sizeof(g_probable_mtu) / - sizeof(g_probable_mtu[0])) - 1]; - } + { + return (g_probable_mtu[(sizeof(g_probable_mtu) / + sizeof(g_probable_mtu[0])) - 1]); + } static unsigned int dtls1_guess_mtu(unsigned int curr_mtu) @@ -1237,27 +1166,26 @@ dtls1_guess_mtu(unsigned int curr_mtu) for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++) if ( curr_mtu > g_probable_mtu[i]) return g_probable_mtu[i]; - + return curr_mtu; } void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) - { - memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); - msg_hdr->type = *(data++); - n2l3(data, msg_hdr->msg_len); - - n2s(data, msg_hdr->seq); - n2l3(data, msg_hdr->frag_off); - n2l3(data, msg_hdr->frag_len); - } + { + memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + msg_hdr->type = *(data++); + n2l3(data, msg_hdr->msg_len); + + n2s(data, msg_hdr->seq); + n2l3(data, msg_hdr->frag_off); + n2l3(data, msg_hdr->frag_len); + } void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr) - { - memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); - - ccs_hdr->type = *(data++); - n2s(data, ccs_hdr->seq); -} + { + memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); + + ccs_hdr->type = *(data++); + } diff --git a/crypto/openssl/ssl/dtls1.h b/crypto/openssl/ssl/dtls1.h index b377cc5..a663cf8 100644 --- a/crypto/openssl/ssl/dtls1.h +++ b/crypto/openssl/ssl/dtls1.h @@ -67,9 +67,8 @@ extern "C" { #endif -#define DTLS1_VERSION 0x0100 -#define DTLS1_VERSION_MAJOR 0x01 -#define DTLS1_VERSION_MINOR 0x00 +#define DTLS1_VERSION 0xFEFF +#define DTLS1_BAD_VER 0x0100 #define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 @@ -83,7 +82,7 @@ extern "C" { #define DTLS1_HM_BAD_FRAGMENT -2 #define DTLS1_HM_FRAGMENT_RETRY -3 -#define DTLS1_CCS_HEADER_LENGTH 3 +#define DTLS1_CCS_HEADER_LENGTH 1 #define DTLS1_AL_HEADER_LENGTH 7 diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 2e067e7..85f72e0 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -1564,6 +1564,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253 #define SSL_F_DTLS1_GET_RECORD 254 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 +#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 #define SSL_F_DTLS1_PROCESS_RECORD 257 #define SSL_F_DTLS1_READ_BYTES 258 diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index e7f4d93..0ca4937 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -87,6 +87,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT), "DTLS1_GET_MESSAGE_FRAGMENT"}, {ERR_FUNC(SSL_F_DTLS1_GET_RECORD), "DTLS1_GET_RECORD"}, {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"}, +{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"}, {ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "DTLS1_READ_BYTES"}, |