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); }
/* Obtain handshake message of message type 'mt' (any if mt == -1), * maximum acceptable body length 'max'. * The first four bytes (msg_type and length) are read in state 'st1', * the body is read in state 'stn'. */ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) { unsigned char *p; unsigned long l; long n; int i,al; 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_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } *ok=1; s->init_msg = s->init_buf->data + 4; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } p=(unsigned char *)s->init_buf->data; if (s->state == st1) /* s->init_num < 4 */ { int skip_message; do { while (s->init_num < 4) { i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, &p[s->init_num],4 - s->init_num, 0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } s->init_num+=i; } skip_message = 0; if (!s->server) if (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) { s->init_num = 0; skip_message = 1; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg); } } while (skip_message); /* s->init_num == 4 */ if ((mt >= 0) && (*p != mt)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && (st1 == SSL3_ST_SR_CERT_A) && (stn == SSL3_ST_SR_CERT_B)) { /* At this point we have got an MS SGC second client * hello (maybe we should always allow the client to * start a new handshake?). We need to restart the mac. * Don't increment {num,total}_renegotiations because * we have not completed the handshake. */ ssl3_init_finished_mac(s); } s->s3->tmp.message_type= *(p++); n2l3(p,l); if (l > (unsigned long)max) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */ { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l+4)) { SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_size=l; s->state=stn; s->init_msg = s->init_buf->data + 4; s->init_num = 0; } /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } #ifndef OPENSSL_NO_NEXTPROTONEG /* If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif /* Feed this message into MAC computation. */ ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg); *ok=1; return s->init_num; f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: *ok=0; return(-1); }
int tls_get_message_header(SSL *s, int *mt) { /* s->init_num < SSL3_HM_HEADER_LENGTH */ int skip_message, i, recvd_type, al; unsigned char *p; unsigned long l; p = (unsigned char *)s->init_buf->data; do { while (s->init_num < SSL3_HM_HEADER_LENGTH) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0); if (i <= 0) { s->rwstate = SSL_READING; return 0; } if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { /* * A ChangeCipherSpec must be a single byte and may not occur * in the middle of a handshake message. */ if (s->init_num != 0 || i != 1 || p[0] != SSL3_MT_CCS) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC; s->init_num = i - 1; s->s3->tmp.message_size = i; return 1; } else if (recvd_type != SSL3_RT_HANDSHAKE) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->init_num += i; } skip_message = 0; if (!s->server) if (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) { s->init_num = 0; skip_message = 1; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, SSL3_HM_HEADER_LENGTH, s, s->msg_callback_arg); } } while (skip_message); /* s->init_num == SSL3_HM_HEADER_LENGTH */ *mt = *p; s->s3->tmp.message_type = *(p++); if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { /* * Only happens with SSLv3+ in an SSLv2 backward compatible * ClientHello * * Total message size is the remaining record bytes to read * plus the SSL3_HM_HEADER_LENGTH bytes that we already read */ l = RECORD_LAYER_get_rrec_length(&s->rlayer) + SSL3_HM_HEADER_LENGTH; s->s3->tmp.message_size = l; s->init_msg = s->init_buf->data; s->init_num = SSL3_HM_HEADER_LENGTH; } else { n2l3(p, l); /* BUF_MEM_grow takes an 'int' parameter */ if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } s->s3->tmp.message_size = l; s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; s->init_num = 0; } return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); return 0; }
/*- * Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) * - 0 (during a shutdown, no data has to be returned) * * If we don't have stored data to work from, read a SSL/TLS record first * (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) 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): * Change cipher spec protocol * just 1 byte needed, no need for keeping anything stored * Alert protocol * 2 bytes needed (AlertLevel, AlertDescription) * Handshake protocol * 4 bytes needed (HandshakeType, uint24 length) -- we just have * to detect unexpected Client Hello and Hello Request messages * here, anything else is handled by higher layers * Application data protocol * none of our business */ 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; SSL3_RECORD *rr; void (*cb) (const SSL *ssl, int type2, int val) = NULL; if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) { /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return (-1); } if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE)) || (peek && (type != SSL3_RT_APPLICATION_DATA))) { SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } /* * check whether there's a handshake message (client hello?) waiting */ 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 * type == SSL3_RT_HANDSHAKE. */ if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { /* type == SSL3_RT_APPLICATION_DATA */ 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); } } start: s->rwstate = SSL_NOTHING; /*- * s->s3->rrec.type - is the type of record * s->s3->rrec.data, - data * s->s3->rrec.off, - offset into 'data' for next read * s->s3->rrec.length, - number of bytes. */ 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 (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) { #ifndef OPENSSL_NO_SCTP /* Restore bio_dgram_sctp_rcvinfo struct */ if (BIO_dgram_is_sctp(SSL_get_rbio(s))) { DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo); } #endif dtls1_copy_record(s, item); OPENSSL_free(item->data); pitem_free(item); } } /* Check for timeout */ if (dtls1_handle_timeout(s) > 0) goto start; /* get new packet if necessary */ if ((SSL3_RECORD_get_length(rr) == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) { ret = dtls1_get_record(s); if (ret <= 0) { ret = dtls1_read_failed(s, ret); /* anything other than a timeout is an error */ if (ret <= 0) return (ret); else 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 */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, * reset by ssl3_get_finished */ && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) { /* * We now have application data between CCS and Finished. Most likely * the packets were reordered on their way, so buffer the application * 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) { SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } SSL3_RECORD_set_length(rr, 0); goto start; } /* * If the other end has shut down, throw anything we read away (even in * 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { SSL3_RECORD_set_length(rr, 0); s->rwstate = SSL_NOTHING; return (0); } 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 */ if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && (s->enc_read_ctx == NULL)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE); goto f_err; } if (recvd_type != NULL) *recvd_type = SSL3_RECORD_get_type(rr); if (len <= 0) return (len); if ((unsigned int)len > SSL3_RECORD_get_length(rr)) n = SSL3_RECORD_get_length(rr); else n = (unsigned int)len; memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); if (!peek) { 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; SSL3_RECORD_set_off(rr, 0); } } #ifndef OPENSSL_NO_SCTP /* * 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 * anymore, finally set shutdown. */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); } #endif return (n); } /* * If we get here, then type != rr->type; if we have a handshake message, * 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. */ { unsigned int k, dest_maxlen = 0; unsigned char *dest = NULL; unsigned int *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); } /* Not certain if this is the right error handling */ al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); 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_arg); if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; if (cb != NULL) { j = (alert_level << 8) | alert_descr; cb(s, SSL_CB_READ_ALERT, j); } 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 /* * With SCTP and streams the socket may deliver app data * after a close_notify alert. We have to check this first so * that nothing gets discarded. */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->d1->shutdown_received = 1; s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); return -1; } #endif 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]; s->rwstate = SSL_NOTHING; s->s3->fatal_alert = 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->session_ctx, s->session); return (0); } else { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE); goto f_err; } goto start; } if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a * shutdown */ s->rwstate = SSL_NOTHING; SSL3_RECORD_set_length(rr, 0); return (0); } if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { /* * We can't process a CCS now, because previous handshake messages * are still missing, so just drop it. */ SSL3_RECORD_set_length(rr, 0); goto start; } /* * 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)) { 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) { SSL3_RECORD_set_length(rr, 0); goto start; } /* * If we are server, we may have a repeated FINISHED of the client * here, then retransmit our CCS and FINISHED. */ if (msg_hdr.type == SSL3_MT_FINISHED) { if (dtls1_check_timeout_num(s) < 0) return -1; dtls1_retransmit_buffered_messages(s); SSL3_RECORD_set_length(rr, 0); 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; } 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); } } goto start; } 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; case SSL3_RT_CHANGE_CIPHER_SPEC: case SSL3_RT_ALERT: case SSL3_RT_HANDSHAKE: /* * we already handled all of these, with the possible exception of * 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); goto f_err; case SSL3_RT_APPLICATION_DATA: /* * At this point, we were expecting handshake data, but have * application data. If the library was running inside ssl3_read() * (i.e. in_read_app_data is set) and it makes sense to read * application data at this point (session renegotiation not yet * started), we will indulge it. */ if (s->s3->in_read_app_data && (s->s3->total_renegotiations != 0) && ossl_statem_app_data_allowed(s)) { s->s3->in_read_app_data = 2; return (-1); } else { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); goto f_err; } } /* not reached */ f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); return (-1); }
/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1), * maximum acceptable body length |max|. The first four bytes (msg_type and * length) are read in state |header_state|, the body is read in state * |body_state|. */ long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type, long max, enum ssl_hash_message_t hash_message, int *ok) { uint8_t *p; unsigned long l; long n; int al; if (ssl->s3->tmp.reuse_message) { /* A ssl_dont_hash_message call cannot be combined with reuse_message; the * ssl_dont_hash_message would have to have been applied to the previous * call. */ assert(hash_message == ssl_hash_message); ssl->s3->tmp.reuse_message = 0; if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } *ok = 1; ssl->state = body_state; ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4; ssl->init_num = (int)ssl->s3->tmp.message_size; return ssl->init_num; } p = (uint8_t *)ssl->init_buf->data; if (ssl->state == header_state) { assert(ssl->init_num < 4); for (;;) { while (ssl->init_num < 4) { int bytes_read = ssl3_read_bytes( ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], 4 - ssl->init_num, 0); if (bytes_read <= 0) { *ok = 0; return bytes_read; } ssl->init_num += bytes_read; } static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0}; if (ssl->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) { break; } /* 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. */ ssl->init_num = 0; if (ssl->msg_callback) { ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, p, 4, ssl, ssl->msg_callback_arg); } } /* ssl->init_num == 4 */ if (msg_type >= 0 && *p != msg_type) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } ssl->s3->tmp.message_type = *(p++); n2l3(p, l); if (l > (unsigned long)max) { al = SSL_AD_ILLEGAL_PARAMETER; OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l && !BUF_MEM_grow_clean(ssl->init_buf, l + 4)) { OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); goto err; } ssl->s3->tmp.message_size = l; ssl->state = body_state; ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4; ssl->init_num = 0; } /* next state (body_state) */ p = ssl->init_msg; n = ssl->s3->tmp.message_size - ssl->init_num; while (n > 0) { int bytes_read = ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], n, 0); if (bytes_read <= 0) { ssl->rwstate = SSL_READING; *ok = 0; return bytes_read; } ssl->init_num += bytes_read; n -= bytes_read; } /* Feed this message into MAC computation. */ if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) { goto err; } if (ssl->msg_callback) { ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data, (size_t)ssl->init_num + 4, ssl, ssl->msg_callback_arg); } *ok = 1; return ssl->init_num; f_err: ssl3_send_alert(ssl, SSL3_AL_FATAL, al); err: *ok = 0; return -1; }
/* Obtain handshake message of message type 'mt' (any if mt == -1), * maximum acceptable body length 'max'. * The first four bytes (msg_type and length) are read in state 'st1', * the body is read in state 'stn'. */ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) { unsigned char *p; unsigned long l; long n; int i,al; 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_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } *ok=1; return((int)s->s3->tmp.message_size); } p=(unsigned char *)s->init_buf->data; if (s->state == st1) /* s->init_num < 4 */ { int skip_message; do { while (s->init_num < 4) { i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num], 4 - s->init_num, 0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } s->init_num+=i; } skip_message = 0; if (!s->server) if (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) skip_message = 1; } while (skip_message); /* s->init_num == 4 */ if ((mt >= 0) && (*p != mt)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && (st1 == SSL3_ST_SR_CERT_A) && (stn == SSL3_ST_SR_CERT_B)) { /* At this point we have got an MS SGC second client * hello (maybe we should always allow the client to * start a new handshake?). We need to restart the mac. * Don't increment {num,total}_renegotiations because * we have not completed the handshake. */ ssl3_init_finished_mac(s); } ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, 4); s->s3->tmp.message_type= *(p++); n2l3(p,l); if (l > (unsigned long)max) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l && !BUF_MEM_grow(s->init_buf,(int)l)) { SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_size=l; s->state=stn; s->init_num=0; } /* next state (stn) */ p=(unsigned char *)s->init_buf->data; n=s->s3->tmp.message_size; while (n > 0) { i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0); if (i <= 0) { s->rwstate=SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num); *ok=1; return s->init_num; f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: *ok=0; return(-1); }
/* * Obtain handshake message of message type 'mt' (any if mt == -1), maximum * acceptable body length 'max'. The first four bytes (msg_type and length) * are read in state 'st1', the body is read in state 'stn'. */ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) { unsigned char *p; unsigned long l; long n; int i, al, recvd_type; 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_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } *ok = 1; s->state = stn; s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } p = (unsigned char *)s->init_buf->data; if (s->state == st1) { /* s->init_num < SSL3_HM_HEADER_LENGTH */ int skip_message; do { while (s->init_num < SSL3_HM_HEADER_LENGTH) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; return i; } if (s->init_num == 0 && recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC && (mt < 0 || mt == SSL3_MT_CHANGE_CIPHER_SPEC)) { if (*p != SSL3_MT_CCS) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } s->init_num = i - 1; s->init_msg = p + 1; s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; s->s3->tmp.message_size = i - 1; s->state = stn; *ok = 1; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, p, 1, s, s->msg_callback_arg); return i - 1; } else if (recvd_type != SSL3_RT_HANDSHAKE) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->init_num += i; } skip_message = 0; if (!s->server) if (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) { s->init_num = 0; skip_message = 1; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, SSL3_HM_HEADER_LENGTH, s, s->msg_callback_arg); } } while (skip_message); /* s->init_num == SSL3_HM_HEADER_LENGTH */ if ((mt >= 0) && (*p != mt)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } s->s3->tmp.message_type = *(p++); if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { /* * Only happens with SSLv3+ in an SSLv2 backward compatible * ClientHello */ /* * Total message size is the remaining record bytes to read * plus the SSL3_HM_HEADER_LENGTH bytes that we already read */ l = RECORD_LAYER_get_rrec_length(&s->rlayer) + SSL3_HM_HEADER_LENGTH; if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) { SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_size = l; s->state = stn; s->init_msg = s->init_buf->data; s->init_num = SSL3_HM_HEADER_LENGTH; } else { n2l3(p, l); if (l > (unsigned long)max) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } /* BUF_MEM_grow takes an 'int' parameter */ if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l + SSL3_HM_HEADER_LENGTH)) { SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); goto err; } s->s3->tmp.message_size = l; s->state = stn; s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; s->init_num = 0; } } /* next state (stn) */ p = s->init_msg; n = s->s3->tmp.message_size - s->init_num; while (n > 0) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, &p[s->init_num], n, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; return i; } s->init_num += i; n -= i; } #ifndef OPENSSL_NO_NEXTPROTONEG /* * If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif /* Feed this message into MAC computation. */ if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num); if (s->msg_callback) s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, (size_t)s->init_num, s, s->msg_callback_arg); } else { ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + SSL3_HM_HEADER_LENGTH); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, s->msg_callback_arg); } *ok = 1; return s->init_num; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: *ok = 0; return (-1); }