X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=ssl%2Frecord%2Frec_layer_d1.c;h=c9fd0669edfb76851e3f95761ec4642b4134c758;hb=8e6d03cac4c34dc089751f36120b69c512f77756;hp=45324ecb15ec8d0fae8c057c18d5bc1207a1fa85;hpb=16f8d4ebf0fd4847fa83d9c61f4150273cb4f533;p=openssl.git diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index 45324ecb15..c9fd0669ed 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -1,116 +1,10 @@ -/* ssl/record/rec_layer_d1.c */ /* - * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. - */ -/* ==================================================================== - * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * 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 - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. * - */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * 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: - * 1. Redistributions of source code must retain the copyright - * 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 the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * 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 - * 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 - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * 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 - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include @@ -119,26 +13,23 @@ #include "../ssl_locl.h" #include #include -#include -#include #include "record_locl.h" int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl) { DTLS_RECORD_LAYER *d; - + if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) return (0); - rl->d = d; d->unprocessed_rcds.q = pqueue_new(); d->processed_rcds.q = pqueue_new(); d->buffered_app_data.q = pqueue_new(); - if (!d->unprocessed_rcds.q || !d->processed_rcds.q - || !d->buffered_app_data.q) { + if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL + || d->buffered_app_data.q == NULL) { pqueue_free(d->unprocessed_rcds.q); pqueue_free(d->processed_rcds.q); pqueue_free(d->buffered_app_data.q); @@ -165,12 +56,12 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) DTLS_RECORD_LAYER *d; pitem *item = NULL; DTLS1_RECORD_DATA *rdata; - pqueue unprocessed_rcds; - pqueue processed_rcds; - pqueue buffered_app_data; + pqueue *unprocessed_rcds; + pqueue *processed_rcds; + pqueue *buffered_app_data; d = rl->d; - + while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) { rdata = (DTLS1_RECORD_DATA *)item->data; OPENSSL_free(rdata->rbuf.buf); @@ -205,18 +96,14 @@ void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e) { if (e == rl->d->w_epoch - 1) { memcpy(rl->d->curr_write_sequence, - rl->write_sequence, - sizeof(rl->write_sequence)); + rl->write_sequence, sizeof(rl->write_sequence)); memcpy(rl->write_sequence, - rl->d->last_write_sequence, - sizeof(rl->write_sequence)); + rl->d->last_write_sequence, sizeof(rl->write_sequence)); } else if (e == rl->d->w_epoch + 1) { memcpy(rl->d->last_write_sequence, - rl->write_sequence, - sizeof(unsigned char[8])); + rl->write_sequence, sizeof(unsigned char[8])); memcpy(rl->write_sequence, - rl->d->curr_write_sequence, - sizeof(rl->write_sequence)); + rl->d->curr_write_sequence, sizeof(rl->write_sequence)); } rl->d->w_epoch = e; } @@ -226,8 +113,13 @@ void DTLS_RECORD_LAYER_resync_write(RECORD_LAYER *rl) memcpy(rl->write_sequence, rl->read_sequence, sizeof(rl->write_sequence)); } +void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq) +{ + memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE); +} + static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, - int len, int peek); + int len); /* copy buffered record into SSL structure */ static int dtls1_copy_record(SSL *s, pitem *item) @@ -277,8 +169,8 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) #ifndef OPENSSL_NO_SCTP /* Store bio_dgram_sctp_rcvinfo struct */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - (s->state == SSL3_ST_SR_FINISHED_A - || s->state == SSL3_ST_CR_FINISHED_A)) { + (SSL_get_state(s) == TLS_ST_SR_FINISHED + || SSL_get_state(s) == TLS_ST_CR_FINISHED)) { BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo); } @@ -334,25 +226,73 @@ int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) dtls1_retrieve_buffered_record((s), \ &((s)->rlayer.d->unprocessed_rcds)) - int dtls1_process_buffered_records(SSL *s) { pitem *item; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q); if (item) { /* Check if epoch is current. */ if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch) - return (1); /* Nothing to do. */ + return 1; /* Nothing to do. */ + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + + rb = RECORD_LAYER_get_rbuf(&s->rlayer); + + if (SSL3_BUFFER_get_left(rb) > 0) { + /* + * We've still got data from the current packet to read. There could + * be a record from the new epoch in it - so don't overwrite it + * with the unprocessed records yet (we'll do it when we've + * finished reading the current packet). + */ + return 1; + } /* Process all the records. */ while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { dtls1_get_unprocessed_record(s); - if (!dtls1_process_record(s)) - return (0); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_SCTP + /* Only do replay check if no SCTP bio */ + if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) +#endif + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + /* dump this record */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + continue; + } + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), - SSL3_RECORD_get_seq_num(&s->rlayer.rrec)) < 0) - return -1; + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) + return 0; } } @@ -363,10 +303,9 @@ int dtls1_process_buffered_records(SSL *s) s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch; s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1; - return (1); + return 1; } - /*- * Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: @@ -379,8 +318,9 @@ int dtls1_process_buffered_records(SSL *s) * (possibly multiple records if we still don't have anything to return). * * This function must handle any surprises the peer may have for us, such as - * Alert records (e.g. close_notify), ChangeCipherSpec records (not really - * a surprise, but handled as if it were), or renegotiation requests. + * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec + * messages are treated as if they were handshake messages *if* the |recd_type| + * argument is non NULL. * Also if record payloads contain fragments too small to process, we store * them until there is enough for the respective protocol (the record protocol * may use arbitrary fragmentation and even interleaving): @@ -395,7 +335,8 @@ int dtls1_process_buffered_records(SSL *s) * Application data protocol * none of our business */ -int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) +int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, + int len, int peek) { int al, i, j, ret; unsigned int n; @@ -418,8 +359,10 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) /* * check whether there's a handshake message (client hello?) waiting */ - if ((ret = have_handshake_fragment(s, type, buf, len, peek))) + if ((ret = have_handshake_fragment(s, type, buf, len))) { + *recvd_type = SSL3_RT_HANDSHAKE; return ret; + } /* * Now s->rlayer.d->handshake_fragment_len == 0 if @@ -431,13 +374,12 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * Continue handshake if it had to be interrupted to read app data with * SCTP. */ - if ((!s->in_handshake && SSL_in_init(s)) || - (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - (s->state == DTLS1_SCTP_ST_SR_READ_SOCK - || s->state == DTLS1_SCTP_ST_CR_READ_SOCK) + if ((!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) || + (BIO_dgram_is_sctp(SSL_get_rbio(s)) + && ossl_statem_in_sctp_read_sock(s) && s->s3->in_read_app_data != 2)) #else - if (!s->in_handshake && SSL_in_init(s)) + if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) #endif { /* type == SSL3_RT_APPLICATION_DATA */ @@ -459,13 +401,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * s->s3->rrec.off, - offset into 'data' for next read * s->s3->rrec.length, - number of bytes. */ - rr = &s->rlayer.rrec; + rr = s->rlayer.rrec; /* * We are not handshaking and have no data yet, so process data buffered * during the last handshake in advance, if any. */ - if (s->state == SSL_ST_OK && SSL3_RECORD_get_length(rr) == 0) { + if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) { pitem *item; item = pqueue_pop(s->rlayer.d->buffered_app_data.q); if (item) { @@ -491,7 +433,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) /* get new packet if necessary */ if ((SSL3_RECORD_get_length(rr) == 0) - || (s->rlayer.rstate == SSL_ST_READ_BODY)) { + || (s->rlayer.rstate == SSL_ST_READ_BODY)) { ret = dtls1_get_record(s); if (ret <= 0) { ret = dtls1_read_failed(s, ret); @@ -503,10 +445,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) } } - if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) { - SSL3_RECORD_set_length(rr, 0); - goto start; - } + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT + && SSL3_RECORD_get_length(rr) != 0) + s->rlayer.alert_count = 0; /* we now have a packet which can be read and processed */ @@ -519,7 +464,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * data for later processing rather than dropping the connection. */ if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), - SSL3_RECORD_get_seq_num(rr)) < 0) { + SSL3_RECORD_get_seq_num(rr)) < 0) { SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } @@ -537,9 +482,14 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) return (0); } - if (type == SSL3_RECORD_get_type(rr)) { - /* SSL3_RT_APPLICATION_DATA or - * SSL3_RT_HANDSHAKE */ + if (type == SSL3_RECORD_get_type(rr) + || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) { + /* + * SSL3_RT_APPLICATION_DATA or + * SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC + */ /* * make sure that we are not getting application data when we are * doing a handshake for the first time @@ -551,6 +501,9 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) goto f_err; } + if (recvd_type != NULL) + *recvd_type = SSL3_RECORD_get_type(rr); + if (len <= 0) return (len); @@ -561,7 +514,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); if (!peek) { - SSL3_RECORD_add_length(rr, -n); + SSL3_RECORD_sub_length(rr, n); SSL3_RECORD_add_off(rr, n); if (SSL3_RECORD_get_length(rr) == 0) { s->rlayer.rstate = SSL_ST_READ_HEADER; @@ -575,8 +528,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA && - (s->state == DTLS1_SCTP_ST_SR_READ_SOCK - || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) { + ossl_statem_in_sctp_read_sock(s)) { s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); @@ -621,10 +573,10 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) dest_len = &s->rlayer.d->alert_fragment_len; } #ifndef OPENSSL_NO_HEARTBEATS - else if (SSL3_RECORD_get_type(rr) == TLS1_RT_HEARTBEAT) { + else if (SSL3_RECORD_get_type(rr) == DTLS1_RT_HEARTBEAT) { /* We allow a 0 return */ if (dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr), - SSL3_RECORD_get_length(rr)) < 0) { + SSL3_RECORD_get_length(rr)) < 0) { return -1; } /* Exit and notify application to read again */ @@ -641,7 +593,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * Application data while renegotiating is allowed. Try again * reading. */ - if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) { + if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) { BIO *bio; s->s3->in_read_app_data = 2; bio = SSL_get_rbio(s); @@ -659,17 +611,17 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (dest_maxlen > 0) { /* - * XDTLS: In a pathalogical case, the Client Hello may be + * XDTLS: In a pathological case, the Client Hello may be * fragmented--don't always expect dest_maxlen bytes */ - if (SSL3_RECORD_get_length(rr) < dest_maxlen) { + if (SSL3_RECORD_get_length(rr) < dest_maxlen) { #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE /* * for normal alerts rr->length is 2, while * dest_maxlen is 7 if we were to handle this * non-existing alert... */ - FIX ME + FIX ME; #endif s->rlayer.rstate = SSL_ST_READ_HEADER; SSL3_RECORD_set_length(rr, 0); @@ -704,7 +656,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) (s->rlayer.d->handshake_fragment[3] != 0)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST); - goto err; + goto f_err; } /* @@ -727,8 +679,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (i < 0) return (i); if (i == 0) { - SSLerr(SSL_F_DTLS1_READ_BYTES, - SSL_R_SSL_HANDSHAKE_FAILURE); + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); return (-1); } @@ -781,6 +732,14 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (alert_level == SSL3_AL_WARNING) { s->s3->warn_alert = alert_descr; + + s->rlayer.alert_count++; + if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); + goto f_err; + } + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { #ifndef OPENSSL_NO_SCTP /* @@ -833,12 +792,11 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) s->rwstate = SSL_NOTHING; s->s3->fatal_alert = alert_descr; - SSLerr(SSL_F_DTLS1_READ_BYTES, - SSL_AD_REASON_OFFSET + alert_descr); + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr); ERR_add_error_data(2, "SSL alert number ", tmp); s->shutdown |= SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx, s->session); + SSL_CTX_remove_session(s->session_ctx, s->session); return (0); } else { al = SSL_AD_ILLEGAL_PARAMETER; @@ -857,62 +815,11 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) } if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { - struct ccs_header_st ccs_hdr; - unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH; - - dtls1_get_ccs_header(SSL3_RECORD_get_data(rr), &ccs_hdr); - - if (s->version == DTLS1_BAD_VER) - ccs_hdr_len = 3; - - /* - * 'Change Cipher Spec' is just a single byte, so we know exactly - * what the record payload has to look like - */ - /* XDTLS: check that epoch is consistent */ - if ((SSL3_RECORD_get_length(rr) != ccs_hdr_len) - || (SSL3_RECORD_get_off(rr) != 0) - || (SSL3_RECORD_get_data(rr)[0] != SSL3_MT_CCS)) { - i = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto err; - } - - SSL3_RECORD_set_length(rr, 0); - - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, - SSL3_RECORD_get_data(rr), 1, s, s->msg_callback_arg); - /* * We can't process a CCS now, because previous handshake messages * are still missing, so just drop it. */ - if (!s->d1->change_cipher_spec_ok) { - goto start; - } - - s->d1->change_cipher_spec_ok = 0; - - s->s3->change_cipher_spec = 1; - if (!ssl3_do_change_cipher_spec(s)) - goto err; - - /* do this whenever CCS is processed */ - dtls1_reset_seq_numbers(s, SSL3_CC_READ); - - if (s->version == DTLS1_BAD_VER) - s->d1->handshake_read_seq++; - -#ifndef OPENSSL_NO_SCTP - /* - * Remember that a CCS has been received, so that an old key of - * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no - * SCTP is used - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL); -#endif - + SSL3_RECORD_set_length(rr, 0); goto start; } @@ -920,7 +827,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * Unexpected handshake message (Client Hello, or protocol violation) */ if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && - !s->in_handshake) { + !ossl_statem_get_in_handshake(s)) { struct hm_header_st msg_hdr; /* this may just be a stale retransmit */ @@ -943,9 +850,9 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) goto start; } - if (((s->state & SSL_ST_MASK) == SSL_ST_OK) && + if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; + ossl_statem_set_in_init(s, 1); s->renegotiate = 1; s->new_session = 1; } @@ -992,8 +899,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) case SSL3_RT_HANDSHAKE: /* * we already handled all of these, with the possible exception of - * SSL3_RT_HANDSHAKE when s->in_handshake is set, but that should not - * happen when type != rr->type + * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but + * that should not happen when type != rr->type */ al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); @@ -1008,14 +915,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) */ if (s->s3->in_read_app_data && (s->s3->total_renegotiations != 0) && - (((s->state & SSL_ST_CONNECT) && - (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && - (s->state <= SSL3_ST_CR_SRVR_HELLO_A) - ) || ((s->state & SSL_ST_ACCEPT) && - (s->state <= SSL3_ST_SW_HELLO_REQ_A) && - (s->state >= SSL3_ST_SR_CLNT_HELLO_A) - ) - )) { + ossl_statem_app_data_allowed(s)) { s->s3->in_read_app_data = 2; return (-1); } else { @@ -1028,21 +928,19 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: return (-1); } - /* * this only happens when a client hello is received and a handshake * is started. */ static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, - int len, int peek) + int len) { if ((type == SSL3_RT_HANDSHAKE) - && (s->rlayer.d->handshake_fragment_len > 0)) + && (s->rlayer.d->handshake_fragment_len > 0)) /* (partially) satisfy request from storage */ { unsigned char *src = s->rlayer.d->handshake_fragment; @@ -1087,11 +985,11 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, int i, mac_size, clear = 0; int prefix_len = 0; int eivlen; - SSL3_RECORD *wr; + SSL3_RECORD wr; SSL3_BUFFER *wb; SSL_SESSION *sess; - wb = &s->rlayer.wbuf; + wb = &s->rlayer.wbuf[0]; /* * first check if there is a SSL3_BUFFER still being written out. This @@ -1113,7 +1011,6 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, if (len == 0 && !create_empty_fragment) return 0; - wr = &s->rlayer.wrec; sess = s->session; if ((sess == NULL) || @@ -1133,13 +1030,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, /* write the header */ *(p++) = type & 0xff; - SSL3_RECORD_set_type(wr, type); + SSL3_RECORD_set_type(&wr, type); /* * Special case: for hello verify request, client version 1.0 and we * haven't decided which version to use yet send back using version 1.0 * header: otherwise some clients will ignore it. */ - if (s->method->version == DTLS_ANY_VERSION) { + if (s->method->version == DTLS_ANY_VERSION && + s->max_proto_version != DTLS1_BAD_VER) { *(p++) = DTLS1_VERSION >> 8; *(p++) = DTLS1_VERSION & 0xff; } else { @@ -1162,55 +1060,66 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, /* Need explicit part of IV for GCM mode */ else if (mode == EVP_CIPH_GCM_MODE) eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + else if (mode == EVP_CIPH_CCM_MODE) + eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; else eivlen = 0; } else eivlen = 0; /* lets setup the record stuff. */ - SSL3_RECORD_set_data(wr, p + eivlen); /* make room for IV in case of CBC */ - SSL3_RECORD_set_length(wr, (int)len); - SSL3_RECORD_set_input(wr, (unsigned char *)buf); + SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */ + SSL3_RECORD_set_length(&wr, (int)len); + SSL3_RECORD_set_input(&wr, (unsigned char *)buf); /* - * we now 'read' from wr->input, wr->length bytes into wr->data + * we now 'read' from wr.input, wr.length bytes into wr.data */ /* first we compress */ if (s->compress != NULL) { - if (!ssl3_do_compress(s)) { + if (!ssl3_do_compress(s, &wr)) { SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_COMPRESSION_FAILURE); goto err; } } else { - memcpy(SSL3_RECORD_get_data(wr), SSL3_RECORD_get_input(wr), - SSL3_RECORD_get_length(wr)); - SSL3_RECORD_reset_input(wr); + memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr), + SSL3_RECORD_get_length(&wr)); + SSL3_RECORD_reset_input(&wr); } /* - * we should still have the output to wr->data and the input from - * wr->input. Length should be wr->length. wr->data still points in the + * we should still have the output to wr.data and the input from + * wr.input. Length should be wr.length. wr.data still points in the * wb->buf */ - if (mac_size != 0) { - if (s->method->ssl3_enc->mac(s, - &(p[SSL3_RECORD_get_length(wr) + eivlen]), 1) < 0) + if (!SSL_USE_ETM(s) && mac_size != 0) { + if (s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr) + eivlen]), + 1) < 0) goto err; - SSL3_RECORD_add_length(wr, mac_size); + SSL3_RECORD_add_length(&wr, mac_size); } /* this is true regardless of mac size */ - SSL3_RECORD_set_data(wr, p); - SSL3_RECORD_reset_input(wr); + SSL3_RECORD_set_data(&wr, p); + SSL3_RECORD_reset_input(&wr); if (eivlen) - SSL3_RECORD_add_length(wr, eivlen); + SSL3_RECORD_add_length(&wr, eivlen); - if (s->method->ssl3_enc->enc(s, 1) < 1) + if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) goto err; + if (SSL_USE_ETM(s) && mac_size != 0) { + if (s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr)]), + 1) < 0) + goto err; + SSL3_RECORD_add_length(&wr, mac_size); + } + /* record length after mac and block padding */ /* * if (type == SSL3_RT_APPLICATION_DATA || (type == SSL3_RT_ALERT && ! @@ -1228,18 +1137,18 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, memcpy(pseq, &(s->rlayer.write_sequence[2]), 6); pseq += 6; - s2n(SSL3_RECORD_get_length(wr), pseq); + s2n(SSL3_RECORD_get_length(&wr), pseq); if (s->msg_callback) s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); /* - * we should now have wr->data pointing to the encrypted data, which is + * we should now have wr.data pointing to the encrypted data, which is * wr->length long */ - SSL3_RECORD_set_type(wr, type); /* not needed but helps for debugging */ - SSL3_RECORD_add_length(wr, DTLS1_RT_HEADER_LENGTH); + SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */ + SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH); ssl3_record_sequence_update(&(s->rlayer.write_sequence[0])); @@ -1248,11 +1157,11 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, * we are in a recursive call; just return the length, don't write * out anything here */ - return wr->length; + return wr.length; } /* now let's set up wb */ - SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(wr)); + SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr)); SSL3_BUFFER_set_offset(wb, 0); /* @@ -1271,7 +1180,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, } DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, - unsigned int *is_next_epoch) + unsigned int *is_next_epoch) { *is_next_epoch = 0; @@ -1280,9 +1189,14 @@ DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, if (rr->epoch == s->rlayer.d->r_epoch) return &s->rlayer.d->bitmap; - /* Only HM and ALERT messages can be from the next epoch */ + /* + * Only HM and ALERT messages can be from the next epoch and only if we + * have already processed all of the unprocessed records from the last + * epoch + */ else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) && - (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { + s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch && + (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { *is_next_epoch = 1; return &s->rlayer.d->next_bitmap; } @@ -1300,8 +1214,13 @@ void dtls1_reset_seq_numbers(SSL *s, int rw) s->rlayer.d->r_epoch++; memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap, sizeof(s->rlayer.d->bitmap)); - memset(&s->rlayer.d->next_bitmap, 0, - sizeof(s->rlayer.d->next_bitmap)); + memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); } else { seq = s->rlayer.write_sequence; memcpy(s->rlayer.d->last_write_sequence, seq,