X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fd1_both.c;h=9d20dfe6094b8fb605d0fdf7c51eb1fce5aaa296;hp=7d48cc4df39e8f60e73acb838f7267ae5ead0b6e;hb=76af303761670cd54a93f1b196bcd7b2eaf7c29c;hpb=9e9858d1cf28e39cfd214b5c508188d5016728fd diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 7d48cc4df3..9d20dfe609 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -160,8 +160,9 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt, 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, +static long dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, int *ok); +static int dtls_get_reassembled_message(SSL *s, long *len); static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) @@ -170,12 +171,12 @@ static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len, unsigned char *buf = NULL; unsigned char *bitmask = NULL; - frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); + frag = OPENSSL_malloc(sizeof(*frag)); if (frag == NULL) return NULL; if (frag_len) { - buf = (unsigned char *)OPENSSL_malloc(frag_len); + buf = OPENSSL_malloc(frag_len); if (buf == NULL) { OPENSSL_free(frag); return NULL; @@ -187,15 +188,12 @@ static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len, /* Initialize reassembly bitmask if necessary */ if (reassembly) { - bitmask = - (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len)); + bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len)); if (bitmask == NULL) { - if (buf != NULL) - OPENSSL_free(buf); + OPENSSL_free(buf); OPENSSL_free(frag); return NULL; } - memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); } frag->reassembly = bitmask; @@ -205,17 +203,16 @@ static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len, void dtls1_hm_fragment_free(hm_fragment *frag) { - + if (!frag) + return; 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->fragment); + OPENSSL_free(frag->reassembly); OPENSSL_free(frag); } @@ -273,7 +270,8 @@ int dtls1_do_write(SSL *s, int type) if (s->write_hash) { if (s->enc_write_ctx - && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE) + && ((EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE) || + (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CCM_MODE))) mac_size = 0; else mac_size = EVP_MD_CTX_size(s->write_hash); @@ -457,23 +455,34 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) * 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; + + + /* + * Messages reused from dtls1_listen also have the record header in + * the buffer which we need to skip over. + */ + if (s->s3->tmp.reuse_message == DTLS1_SKIP_RECORD_HEADER) { + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH + + DTLS1_RT_HEADER_LENGTH; + } else { + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + } s->init_num = (int)s->s3->tmp.message_size; + s->s3->tmp.reuse_message = 0; return s->init_num; } msg_hdr = &s->d1->r_msg_hdr; - memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + memset(msg_hdr, 0, sizeof(*msg_hdr)); again: - i = dtls1_get_message_fragment(s, st1, stn, max, ok); + i = dtls1_get_message_fragment(s, st1, stn, mt, ok); if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) { /* bad fragment received */ goto again; @@ -481,7 +490,27 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) return i; } + 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; + } + p = (unsigned char *)s->init_buf->data; + + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, + p, 1, s, s->msg_callback_arg); + } + /* + * This isn't a real handshake message so skip the processing below. + * dtls1_get_message_fragment() will never return a CCS if mt == -1, + * so we are ok to continue in that case. + */ + return i; + } + msg_len = msg_hdr->msg_len; /* reconstruct message header */ @@ -495,16 +524,21 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) msg_len += DTLS1_HM_HEADER_LENGTH; } + if (msg_len > (unsigned long)max) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto f_err; + } + 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)); + memset(msg_hdr, 0, sizeof(*msg_hdr)); + + s->d1->handshake_read_seq++; - /* 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; @@ -515,8 +549,72 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) return -1; } -static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, - int max) +int dtls_get_message(SSL *s, int *mt, unsigned long *len) +{ + struct hm_header_st *msg_hdr; + unsigned char *p; + unsigned long msg_len; + int ok; + long tmplen; + + msg_hdr = &s->d1->r_msg_hdr; + memset(msg_hdr, 0, sizeof(*msg_hdr)); + + again: + ok = dtls_get_reassembled_message(s, &tmplen); + if (tmplen == DTLS1_HM_BAD_FRAGMENT + || tmplen == DTLS1_HM_FRAGMENT_RETRY) { + /* bad fragment received */ + goto again; + } else if (tmplen <= 0 && !ok) { + return 0; + } + + *mt = s->s3->tmp.message_type; + + p = (unsigned char *)s->init_buf->data; + + if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, + p, 1, s, s->msg_callback_arg); + } + /* + * This isn't a real handshake message so skip the processing below. + */ + return 1; + } + + 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, 0, sizeof(*msg_hdr)); + + s->d1->handshake_read_seq++; + + + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + *len = s->init_num; + + return 1; +} + +static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr) { size_t frag_off, frag_len, msg_len; @@ -530,11 +628,6 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, 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 @@ -563,7 +656,7 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, return 0; /* no error */ } -static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) +static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok) { /*- * (0) check whether the desired fragment is available @@ -590,7 +683,7 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) unsigned long frag_len = frag->msg_header.frag_len; pqueue_pop(s->d1->buffered_messages); - al = dtls1_preprocess_fragment(s, &frag->msg_header, max); + al = dtls1_preprocess_fragment(s, &frag->msg_header); if (al == 0) { /* no alert */ unsigned char *p = @@ -676,7 +769,7 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok) unsigned char devnull[256]; while (frag_len) { - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, devnull, frag_len > sizeof(devnull) ? sizeof(devnull) : @@ -689,7 +782,7 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok) } /* read the body of the fragment (header has already been read */ - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, frag->fragment + msg_hdr->frag_off, frag_len, 0); if ((unsigned long)i != frag_len) @@ -728,7 +821,7 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok) return DTLS1_HM_FRAGMENT_RETRY; err: - if (frag != NULL && item == NULL) + if (item == NULL) dtls1_hm_fragment_free(frag); *ok = 0; return i; @@ -772,7 +865,7 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr, unsigned char devnull[256]; while (frag_len) { - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, devnull, frag_len > sizeof(devnull) ? sizeof(devnull) : @@ -798,7 +891,7 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr, /* * read the body of the fragment (header has already been read */ - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, frag->fragment, frag_len, 0); if ((unsigned long)i != frag_len) i = -1; @@ -825,62 +918,117 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr, return DTLS1_HM_FRAGMENT_RETRY; err: - if (frag != NULL && item == NULL) + if (item == NULL) dtls1_hm_fragment_free(frag); *ok = 0; return i; } static long -dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) +dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, int *ok) +{ + long len; + + do { + *ok = dtls_get_reassembled_message(s, &len); + /* A CCS isn't a real handshake message, so if we get one there is no + * message sequence number to give us confidence that this was really + * intended to be at this point in the handshake sequence. Therefore we + * only allow this if we were explicitly looking for it (i.e. if |mt| + * is -1 we still don't allow it). If we get one when we're not + * expecting it then probably something got re-ordered or this is a + * retransmit. We should drop this and try again. + */ + } while (*ok && mt != SSL3_MT_CHANGE_CIPHER_SPEC + && s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC); + + if (*ok) + s->state = stn; + + return len; +} + +static int dtls_get_reassembled_message(SSL *s, long *len) { unsigned char wire[DTLS1_HM_HEADER_LENGTH]; - unsigned long len, frag_off, frag_len; - int i, al; + unsigned long mlen, frag_off, frag_len; + int i, al, recvd_type; struct hm_header_st msg_hdr; + int ok; redo: /* see if we have the required fragment already */ - if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) { - if (*ok) + if ((frag_len = dtls1_retrieve_buffered_fragment(s, &ok)) || ok) { + if (ok) s->init_num = frag_len; - return frag_len; + *len = frag_len; + return ok; } /* read handshake message header */ - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire, DTLS1_HM_HEADER_LENGTH, 0); if (i <= 0) { /* nbio, or an error */ s->rwstate = SSL_READING; - *ok = 0; - return i; + *len = i; + return 0; } + if(recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + if (wire[0] != SSL3_MT_CCS) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto f_err; + } + + memcpy(s->init_buf->data, wire, i); + s->init_num = i - 1; + s->init_msg = s->init_buf->data + 1; + s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; + s->s3->tmp.message_size = i - 1; + *len = i - 1; + return 1; + } + /* Handshake fails if message header is incomplete */ if (i != DTLS1_HM_HEADER_LENGTH) { al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_UNEXPECTED_MESSAGE); + SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } /* parse the message fragment header */ dtls1_get_message_header(wire, &msg_hdr); + mlen = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; + frag_len = msg_hdr.frag_len; + + /* + * We must have at least frag_len bytes left in the record to be read. + * Fragments must not span records. + */ + if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) { + al = SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH); + goto f_err; + } + /* * if this is a future (or stale) message it gets buffered * (or dropped)--no further processing at this time * While listening, we accept seq 1 (ClientHello with cookie) * although we're still expecting seq 0 (ClientHello) */ - if (msg_hdr.seq != s->d1->handshake_read_seq - && !(s->d1->listen && msg_hdr.seq == 1)) - return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); - - len = msg_hdr.msg_len; - frag_off = msg_hdr.frag_off; - frag_len = msg_hdr.frag_len; + if (msg_hdr.seq != s->d1->handshake_read_seq) { + *len = dtls1_process_out_of_seq_message(s, &msg_hdr, &ok); + return ok; + } - if (frag_len && frag_len < len) - return dtls1_reassemble_fragment(s, &msg_hdr, ok); + if (frag_len && frag_len < mlen) { + *len = dtls1_reassemble_fragment(s, &msg_hdr, &ok); + return ok; + } if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && wire[0] == SSL3_MT_HELLO_REQUEST) { @@ -900,31 +1048,30 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) } else { /* Incorrectly formated Hello request */ al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, + SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } } - if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max))) + if ((al = dtls1_preprocess_fragment(s, &msg_hdr))) goto f_err; - /* XDTLS: ressurect this when restart is in place */ - s->state = stn; - if (frag_len > 0) { unsigned char *p = (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; - i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, &p[frag_off], frag_len, 0); + /* - * XDTLS: fix this--message fragments cannot span multiple packets + * This shouldn't ever fail due to NBIO because we already checked + * that we have enough data in the record */ if (i <= 0) { s->rwstate = SSL_READING; - *ok = 0; - return i; + *len = i; + return 0; } } else i = 0; @@ -935,33 +1082,30 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) */ if (i != (int)frag_len) { al = SSL3_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL3_AD_ILLEGAL_PARAMETER); goto f_err; } - *ok = 1; - /* * 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; + *len = s->init_num = frag_len; + return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); s->init_num = 0; - - *ok = 0; - return (-1); + *len = -1; + return 0; } /*- * for these 2 messages, we need to * ssl->enc_read_ctx re-init - * ssl->s3->read_sequence zero + * ssl->rlayer.read_sequence zero * ssl->s3->read_mac_secret re-init * ssl->session->read_sym_enc assign * ssl->session->read_compression assign @@ -989,7 +1133,10 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) s->d1->handshake_write_seq, 0, 0); /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 1); + if (!dtls1_buffer_message(s, 1)) { + SSLerr(SSL_F_DTLS1_SEND_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); + return -1; + } s->state = b; } @@ -1086,8 +1233,10 @@ int dtls1_buffer_message(SSL *s, int is_ccs) memcpy(frag->fragment, s->init_buf->data, s->init_num); if (is_ccs) { + /* For DTLS1_BAD_VER the header length is non-standard */ OPENSSL_assert(s->d1->w_msg_hdr.msg_len + - DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num); + ((s->version==DTLS1_BAD_VER)?3: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); @@ -1105,7 +1254,8 @@ int dtls1_buffer_message(SSL *s, int is_ccs) frag->msg_header.saved_retransmit_state.write_hash = s->write_hash; frag->msg_header.saved_retransmit_state.compress = s->compress; frag->msg_header.saved_retransmit_state.session = s->session; - frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch; + frag->msg_header.saved_retransmit_state.epoch = + DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer); memset(seq64be, 0, sizeof(seq64be)); seq64be[6] = @@ -1138,7 +1288,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, unsigned long header_length; unsigned char seq64be[8]; struct dtls1_retransmit_state saved_state; - unsigned char save_write_sequence[8]; /*- OPENSSL_assert(s->init_num == 0); @@ -1179,8 +1328,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, saved_state.write_hash = s->write_hash; saved_state.compress = s->compress; saved_state.session = s->session; - saved_state.epoch = s->d1->w_epoch; - saved_state.epoch = s->d1->w_epoch; + saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer); s->d1->retransmitting = 1; @@ -1189,15 +1337,8 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, s->write_hash = frag->msg_header.saved_retransmit_state.write_hash; s->compress = frag->msg_header.saved_retransmit_state.compress; s->session = frag->msg_header.saved_retransmit_state.session; - s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch; - - if (frag->msg_header.saved_retransmit_state.epoch == - saved_state.epoch - 1) { - memcpy(save_write_sequence, s->s3->write_sequence, - sizeof(s->s3->write_sequence)); - memcpy(s->s3->write_sequence, s->d1->last_write_sequence, - sizeof(s->s3->write_sequence)); - } + DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, + frag->msg_header.saved_retransmit_state.epoch); ret = dtls1_do_write(s, frag->msg_header.is_ccs ? SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); @@ -1207,15 +1348,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, s->write_hash = saved_state.write_hash; s->compress = saved_state.compress; s->session = saved_state.session; - s->d1->w_epoch = saved_state.epoch; - - if (frag->msg_header.saved_retransmit_state.epoch == - saved_state.epoch - 1) { - memcpy(s->d1->last_write_sequence, s->s3->write_sequence, - sizeof(s->s3->write_sequence)); - memcpy(s->s3->write_sequence, save_write_sequence, - sizeof(s->s3->write_sequence)); - } + DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch); s->d1->retransmitting = 0; @@ -1235,21 +1368,18 @@ void dtls1_clear_record_buffer(SSL *s) } } -unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p, +void dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, unsigned long len, unsigned long frag_off, unsigned long frag_len) { - /* Don't change sequence numbers while listening */ - if (frag_off == 0 && !s->d1->listen) { + 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 */ @@ -1305,7 +1435,7 @@ unsigned int dtls1_min_mtu(SSL *s) void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) { - memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + memset(msg_hdr, 0, sizeof(*msg_hdr)); msg_hdr->type = *(data++); n2l3(data, msg_hdr->msg_len); @@ -1314,20 +1444,16 @@ dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) 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++); -} - int dtls1_shutdown(SSL *s) { int ret; #ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && + BIO *wbio; + + wbio = SSL_get_wbio(s); + if (wbio != NULL && BIO_dgram_is_sctp(wbio) && !(s->shutdown & SSL_SENT_SHUTDOWN)) { - ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); + ret = BIO_dgram_sctp_wait_for_dry(wbio); if (ret < 0) return -1; @@ -1344,27 +1470,26 @@ int dtls1_shutdown(SSL *s) } #ifndef OPENSSL_NO_HEARTBEATS -int dtls1_process_heartbeat(SSL *s) +int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length) { - unsigned char *p = &s->s3->rrec.data[0], *pl; + unsigned char *pl; unsigned short hbtype; unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, - &s->s3->rrec.data[0], s->s3->rrec.length, - s, s->msg_callback_arg); + p, length, s, s->msg_callback_arg); /* Read type and payload length first */ - if (1 + 2 + 16 > s->s3->rrec.length) + if (1 + 2 + 16 > length) return 0; /* silently discard */ - if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH) + if (length > SSL3_RT_MAX_PLAIN_LENGTH) return 0; /* silently discard per RFC 6520 sec. 4 */ hbtype = *p++; n2s(p, payload); - if (1 + 2 + payload + 16 > s->s3->rrec.length) + if (1 + 2 + payload + 16 > length) return 0; /* silently discard per RFC 6520 sec. 4 */ pl = p; @@ -1393,7 +1518,10 @@ int dtls1_process_heartbeat(SSL *s) memcpy(bp, pl, payload); bp += payload; /* Random padding */ - RAND_pseudo_bytes(bp, padding); + if (RAND_bytes(bp, padding) <= 0) { + OPENSSL_free(buffer); + return -1; + } r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); @@ -1427,7 +1555,7 @@ int dtls1_process_heartbeat(SSL *s) int dtls1_heartbeat(SSL *s) { unsigned char *buf, *p; - int ret; + int ret = -1; unsigned int payload = 18; /* Sequence number + random bytes */ unsigned int padding = 16; /* Use minimum padding */ @@ -1479,10 +1607,16 @@ int dtls1_heartbeat(SSL *s) /* Sequence number */ s2n(s->tlsext_hb_seq, p); /* 16 random bytes */ - RAND_pseudo_bytes(p, 16); + if (RAND_bytes(p, 16) <= 0) { + SSLerr(SSL_F_DTLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR); + goto err; + } p += 16; /* Random padding */ - RAND_pseudo_bytes(p, padding); + if (RAND_bytes(p, padding) <= 0) { + SSLerr(SSL_F_DTLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR); + goto err; + } ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding); if (ret >= 0) { @@ -1495,6 +1629,7 @@ int dtls1_heartbeat(SSL *s) s->tlsext_hb_pending = 1; } + err: OPENSSL_free(buf); return ret;