X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=ssl%2Frecord%2Frec_layer_d1.c;h=5e7aa6345afe4512ba94c8969850cc8d7f53c839;hb=0e97f1e1a7f43be3a5e5c6256fe6bcb90caf9e01;hp=d2bb67832307590961ee8c8ec4a6c75132df1613;hpb=02ba18a63e1f4ae1d0c0a185f9b7701fcddc1835;p=openssl.git diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index d2bb678323..5e7aa6345a 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -9,11 +9,12 @@ #include #include -#define USE_SOCKETS #include "../ssl_locl.h" #include #include #include "record_locl.h" +#include "../packet_locl.h" +#include "internal/cryptlib.h" int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl) { @@ -108,19 +109,11 @@ void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e) rl->d->w_epoch = e; } -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 size_t have_handshake_fragment(SSL *s, int type, unsigned char *buf, - size_t len); - /* copy buffered record into SSL structure */ static int dtls1_copy_record(SSL *s, pitem *item) { @@ -339,7 +332,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, size_t len, int peek, size_t *readbytes) { int al, i, j, iret; - size_t ret, n; + size_t n; SSL3_RECORD *rr; void (*cb) (const SSL *ssl, int type2, int val) = NULL; @@ -356,33 +349,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, return -1; } - /* - * check whether there's a handshake message (client hello?) waiting - */ - ret = have_handshake_fragment(s, type, buf, len); - if (ret > 0) { - *recvd_type = SSL3_RT_HANDSHAKE; - *readbytes = ret; - return 1; - } - - /* - * Now s->rlayer.d->handshake_fragment_len == 0 if - * type == SSL3_RT_HANDSHAKE. - */ - -#ifndef OPENSSL_NO_SCTP - /* - * Continue handshake if it had to be interrupted to read app data with - * SCTP. - */ - 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 (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) -#endif { /* type == SSL3_RT_APPLICATION_DATA */ i = s->handshake_func(s); @@ -524,18 +491,6 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, } } #ifndef OPENSSL_NO_SCTP - /* - * We were about to renegotiate but had to read belated application - * data first, so retry. - */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA && - 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)); - } - /* * We might had to delay a close_notify alert because of reordered * app data. If there was an alert and there is no message to read @@ -557,170 +512,23 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, * then it was unexpected (Hello Request or Client Hello). */ - /* - * In case of record types for which we have 'fragment' storage, fill - * that so that we can process the data at a fixed place. - */ - { - size_t k, dest_maxlen = 0; - unsigned char *dest = NULL; - size_t *dest_len = NULL; - - if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) { - dest_maxlen = sizeof s->rlayer.d->handshake_fragment; - dest = s->rlayer.d->handshake_fragment; - dest_len = &s->rlayer.d->handshake_fragment_len; - } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { - dest_maxlen = sizeof(s->rlayer.d->alert_fragment); - dest = s->rlayer.d->alert_fragment; - dest_len = &s->rlayer.d->alert_fragment_len; - } -#ifndef OPENSSL_NO_HEARTBEATS - 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) { - return -1; - } - /* Exit and notify application to read again */ - SSL3_RECORD_set_length(rr, 0); - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - return -1; - } -#endif - /* else it's a CCS message, or application data or wrong */ - else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) { - /* - * Application data while renegotiating is allowed. Try again - * reading. - */ - if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) { - BIO *bio; - s->s3->in_read_app_data = 2; - bio = SSL_get_rbio(s); - s->rwstate = SSL_READING; - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return -1; - } + if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { + unsigned int alert_level, alert_descr; + unsigned char *alert_bytes = SSL3_RECORD_get_data(rr) + + SSL3_RECORD_get_off(rr); + PACKET alert; - /* Not certain if this is the right error handling */ + if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr)) + || !PACKET_get_1(&alert, &alert_level) + || !PACKET_get_1(&alert, &alert_descr) + || PACKET_remaining(&alert) != 0) { al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_INVALID_ALERT); goto f_err; } - if (dest_maxlen > 0) { - /* - * 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) { -#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; -#endif - s->rlayer.rstate = SSL_ST_READ_HEADER; - SSL3_RECORD_set_length(rr, 0); - goto start; - } - - /* now move 'n' bytes: */ - for (k = 0; k < dest_maxlen; k++) { - dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]; - SSL3_RECORD_add_off(rr, 1); - SSL3_RECORD_add_length(rr, -1); - } - *dest_len = dest_maxlen; - } - } - - /*- - * s->rlayer.d->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE; - * s->rlayer.d->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT. - * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) - */ - - /* If we are a client, check for an incoming 'Hello Request': */ - if ((!s->server) && - (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && - (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && - (s->session != NULL) && (s->session->cipher != NULL)) { - s->rlayer.d->handshake_fragment_len = 0; - - if ((s->rlayer.d->handshake_fragment[1] != 0) || - (s->rlayer.d->handshake_fragment[2] != 0) || - (s->rlayer.d->handshake_fragment[3] != 0)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST); - goto f_err; - } - - /* - * no need to check sequence number on HELLO REQUEST messages - */ - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, - s->rlayer.d->handshake_fragment, 4, s, - s->msg_callback_arg); - - if (SSL_is_init_finished(s) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && - !s->s3->renegotiate) { - s->d1->handshake_read_seq++; - s->new_session = 1; - ssl3_renegotiate(s); - if (ssl3_renegotiate_check(s)) { - i = s->handshake_func(s); - if (i < 0) - return i; - if (i == 0) { - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); - return -1; - } - - if (!(s->mode & SSL_MODE_AUTO_RETRY)) { - if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { - /* no read-ahead left? */ - BIO *bio; - /* - * In the case where we try to read application data, - * but we trigger an SSL handshake, we return -1 with - * the retry option set. Otherwise renegotiation may - * cause nasty problems in the blocking world - */ - s->rwstate = SSL_READING; - bio = SSL_get_rbio(s); - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return -1; - } - } - } - } - /* - * we either finished a handshake or ignored the request, now try - * again to obtain the (application) data we were asked for - */ - goto start; - } - - if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) { - int alert_level = s->rlayer.d->alert_fragment[0]; - int alert_descr = s->rlayer.d->alert_fragment[1]; - - s->rlayer.d->alert_fragment_len = 0; - - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_ALERT, - s->rlayer.d->alert_fragment, 2, s, + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s, s->msg_callback_arg); if (s->info_callback != NULL) @@ -762,34 +570,6 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, s->shutdown |= SSL_RECEIVED_SHUTDOWN; return 0; } -#if 0 - /* XXX: this is a possible improvement in the future */ - /* now check if it's a missing record */ - if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) { - unsigned short seq; - unsigned int frag_off; - unsigned char *p = &(s->rlayer.d->alert_fragment[2]); - - n2s(p, seq); - n2l3(p, frag_off); - - dtls1_retransmit_message(s, - dtls1_get_queue_priority - (frag->msg_header.seq, 0), frag_off, - &found); - if (!found && SSL_in_init(s)) { - /* - * fprintf( stderr,"in init = %d\n", SSL_in_init(s)); - */ - /* - * requested a message not yet sent, send an alert - * ourselves - */ - ssl3_send_alert(s, SSL3_AL_WARNING, - DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); - } - } -#endif } else if (alert_level == SSL3_AL_FATAL) { char tmp[16]; @@ -829,17 +609,22 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, /* * Unexpected handshake message (Client Hello, or protocol violation) */ - if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && - !ossl_statem_get_in_handshake(s)) { + if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) && + !ossl_statem_get_in_handshake(s)) { struct hm_header_st msg_hdr; - /* this may just be a stale retransmit */ - dtls1_get_message_header(rr->data, &msg_hdr); - if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) { + /* + * This may just be a stale retransmit. Also sanity check that we have + * at least enough record bytes for a message header + */ + if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch + || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) { SSL3_RECORD_set_length(rr, 0); goto start; } + dtls1_get_message_header(rr->data, &msg_hdr); + /* * If we are server, we may have a repeated FINISHED of the client * here, then retransmit our CCS and FINISHED. @@ -853,12 +638,21 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, goto start; } - if (SSL_is_init_finished(s) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - ossl_statem_set_in_init(s, 1); - s->renegotiate = 1; - s->new_session = 1; + /* + * To get here we must be trying to read app data but found handshake + * data. But if we're trying to read app data, and we're not in init + * (which is tested for at the top of this function) then init must be + * finished + */ + if (!ossl_assert(SSL_is_init_finished(s))) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); + goto f_err; } + + /* We found handshake data, so we're going back into init */ + ossl_statem_set_in_init(s, 1); + i = s->handshake_func(s); if (i < 0) return i; @@ -889,11 +683,6 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, switch (SSL3_RECORD_get_type(rr)) { default: - /* TLS just ignores unknown message types */ - if (s->version == TLS1_VERSION) { - SSL3_RECORD_set_length(rr, 0); - goto start; - } al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); goto f_err; @@ -934,39 +723,6 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, return -1; } -/* - * this only happens when a client hello is received and a handshake - * is started. - */ -static size_t have_handshake_fragment(SSL *s, int type, unsigned char *buf, - size_t len) -{ - - if ((type == SSL3_RT_HANDSHAKE) - && (s->rlayer.d->handshake_fragment_len > 0)) - /* (partially) satisfy request from storage */ - { - unsigned char *src = s->rlayer.d->handshake_fragment; - unsigned char *dst = buf; - size_t k, n; - - /* peek == 0 */ - n = 0; - while ((len > 0) && (s->rlayer.d->handshake_fragment_len > 0)) { - *dst++ = *src++; - len--; - s->rlayer.d->handshake_fragment_len--; - n++; - } - /* move any remaining fragment bytes: */ - for (k = 0; k < s->rlayer.d->handshake_fragment_len; k++) - s->rlayer.d->handshake_fragment[k] = *src++; - return n; - } - - return 0; -} - /* * Call this to write data in records of type 'type' It will return <= 0 if * not all data has been sent or non-blocking IO. @@ -976,7 +732,10 @@ int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len, { int i; - OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH); + if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLerr(SSL_F_DTLS1_WRITE_BYTES, ERR_R_INTERNAL_ERROR); + return -1; + } s->rwstate = SSL_NOTHING; i = do_dtls1_write(s, type, buf, len, 0, written); return i; @@ -999,9 +758,9 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, * first check if there is a SSL3_BUFFER still being written out. This * will happen with non blocking IO */ - if (SSL3_BUFFER_get_left(wb) != 0) { - OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */ - return ssl3_write_pending(s, type, buf, len, written); + if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) { + SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR); + return 0; } /* If we have an alert to send, lets send it */ @@ -1015,6 +774,11 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, if (len == 0 && !create_empty_fragment) return 0; + if (len > s->max_send_fragment) { + SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); + return 0; + } + sess = s->session; if ((sess == NULL) || @@ -1098,7 +862,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, * wb->buf */ - if (!SSL_USE_ETM(s) && mac_size != 0) { + if (!SSL_WRITE_ETM(s) && mac_size != 0) { if (!s->method->ssl3_enc->mac(s, &wr, &(p[SSL3_RECORD_get_length(&wr) + eivlen]), 1)) @@ -1116,7 +880,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) goto err; - if (SSL_USE_ETM(s) && mac_size != 0) { + if (SSL_WRITE_ETM(s) && mac_size != 0) { if (!s->method->ssl3_enc->mac(s, &wr, &(p[SSL3_RECORD_get_length(&wr)]), 1)) goto err; @@ -1124,20 +888,11 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, } /* record length after mac and block padding */ - /* - * if (type == SSL3_RT_APPLICATION_DATA || (type == SSL3_RT_ALERT && ! - * SSL_in_init(s))) - */ /* there's only one epoch between handshake and app data */ s2n(s->rlayer.d->w_epoch, pseq); - /* XDTLS: ?? */ - /* - * else s2n(s->d1->handshake_epoch, pseq); - */ - memcpy(pseq, &(s->rlayer.write_sequence[2]), 6); pseq += 6; s2n(SSL3_RECORD_get_length(&wr), pseq);