int dtls1_accept(SSL *s) { BUF_MEM *buf = NULL; void (*cb)(const SSL *ssl, int type, int value) = NULL; uint32_t alg_a; int ret = -1; int new_state, state, skip = 0; assert(s->handshake_func == dtls1_accept); assert(s->server); assert(SSL_IS_DTLS(s)); ERR_clear_error(); ERR_clear_system_error(); if (s->info_callback != NULL) { cb = s->info_callback; } else if (s->ctx->info_callback != NULL) { cb = s->ctx->info_callback; } s->in_handshake++; for (;;) { state = s->state; switch (s->state) { case SSL_ST_ACCEPT: if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_START, 1); } if (s->init_buf == NULL) { buf = BUF_MEM_new(); if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; goto end; } s->init_buf = buf; buf = NULL; } s->init_num = 0; if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; goto end; } if (!ssl3_init_handshake_buffer(s)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } s->state = SSL3_ST_SR_CLNT_HELLO_A; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: case SSL3_ST_SR_CLNT_HELLO_D: s->shutdown = 0; ret = ssl3_get_client_hello(s); if (ret <= 0) { goto end; } dtls1_stop_timer(s); s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num = 0; break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: dtls1_start_timer(s); ret = ssl3_send_server_hello(s); if (ret <= 0) { goto end; } if (s->hit) { if (s->tlsext_ticket_expected) { s->state = SSL3_ST_SW_SESSION_TICKET_A; } else { s->state = SSL3_ST_SW_CHANGE_A; } } else { s->state = SSL3_ST_SW_CERT_A; } s->init_num = 0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { dtls1_start_timer(s); ret = ssl3_send_server_certificate(s); if (ret <= 0) { goto end; } if (s->s3->tmp.certificate_status_expected) { s->state = SSL3_ST_SW_CERT_STATUS_A; } else { s->state = SSL3_ST_SW_KEY_EXCH_A; } } else { skip = 1; s->state = SSL3_ST_SW_KEY_EXCH_A; } s->init_num = 0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret = ssl3_send_certificate_status(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: case SSL3_ST_SW_KEY_EXCH_C: alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* Send a ServerKeyExchange message if: * - The key exchange is ephemeral or anonymous * Diffie-Hellman. * - There is a PSK identity hint. * * TODO(davidben): This logic is currently duplicated * in s3_srvr.c. Fix this. In the meantime, keep them * in sync. */ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || ((alg_a & SSL_aPSK) && s->psk_identity_hint)) { dtls1_start_timer(s); ret = ssl3_send_server_key_exchange(s); if (ret <= 0) { goto end; } } else { skip = 1; } s->state = SSL3_ST_SW_CERT_REQ_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (s->s3->tmp.cert_request) { dtls1_start_timer(s); ret = ssl3_send_certificate_request(s); if (ret <= 0) { goto end; } } else { skip = 1; } s->state = SSL3_ST_SW_SRVR_DONE_A; s->init_num = 0; break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret = ssl3_send_server_done(s); if (ret <= 0) { goto end; } s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; break; case SSL3_ST_SW_FLUSH: s->rwstate = SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { ret = -1; goto end; } s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: if (s->s3->tmp.cert_request) { ret = ssl3_get_client_certificate(s); if (ret <= 0) { goto end; } } s->init_num = 0; s->state = SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: case SSL3_ST_SR_KEY_EXCH_C: ret = ssl3_get_client_key_exchange(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: ret = ssl3_get_cert_verify(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SR_CHANGE; s->init_num = 0; break; case SSL3_ST_SR_CHANGE: ret = s->method->ssl_read_change_cipher_spec(s); if (ret <= 0) { goto end; } if (!ssl3_do_change_cipher_spec(s)) { ret = -1; goto end; } s->state = SSL3_ST_SR_FINISHED_A; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->hit) { s->state = SSL_ST_OK; } else if (s->tlsext_ticket_expected) { s->state = SSL3_ST_SW_SESSION_TICKET_A; } else { s->state = SSL3_ST_SW_CHANGE_A; } s->init_num = 0; break; case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret = ssl3_send_new_session_ticket(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher = s->s3->tmp.new_cipher; if (!s->enc_method->setup_key_block(s)) { ret = -1; goto end; } ret = dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A, SSL3_ST_SW_CHANGE_B); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_FINISHED_A; s->init_num = 0; if (!s->enc_method->change_cipher_state( s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; goto end; } break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret = ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, s->enc_method->server_finished_label, s->enc_method->server_finished_label_len); if (ret <= 0) { goto end; } s->state = SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state = SSL3_ST_SR_CHANGE; } else { s->s3->tmp.next_state = SSL_ST_OK; } s->init_num = 0; break; case SSL_ST_OK: ssl3_cleanup_key_block(s); /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num = 0; s->s3->initial_handshake_complete = 1; ssl_update_cache(s, SSL_SESS_CACHE_SERVER); if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_DONE, 1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } if (!s->s3->tmp.reuse_message && !skip) { if (cb != NULL && s->state != state) { new_state = s->state; s->state = state; cb(s, SSL_CB_ACCEPT_LOOP, 1); s->state = new_state; } } skip = 0; } end: s->in_handshake--; BUF_MEM_free(buf); if (cb != NULL) { cb(s, SSL_CB_ACCEPT_EXIT, ret); } return ret; }
/* 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), ChangeCipherSpec records (not really * a surprise, but handled as if it were), or renegotiation requests. * 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 ssl3_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek) { int al, i, ret; unsigned int n; SSL3_RECORD *rr; void (*cb)(const SSL *ssl, int type2, int val) = NULL; if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || (peek && type != SSL3_RT_APPLICATION_DATA)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } if (type == SSL3_RT_HANDSHAKE && s->s3->handshake_fragment_len > 0) { /* (partially) satisfy request from storage */ uint8_t *src = s->s3->handshake_fragment; uint8_t *dst = buf; unsigned int k; /* peek == 0 */ n = 0; while (len > 0 && s->s3->handshake_fragment_len > 0) { *dst++ = *src++; len--; s->s3->handshake_fragment_len--; n++; } /* move any remaining fragment bytes: */ for (k = 0; k < s->s3->handshake_fragment_len; k++) { s->s3->handshake_fragment[k] = *src++; } return n; } /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ /* This may require multiple iterations. False Start will cause * |s->handshake_func| to signal success one step early, but the handshake * must be completely finished before other modes are accepted. * * TODO(davidben): Move this check up to a higher level. */ while (!s->in_handshake && SSL_in_init(s)) { assert(type == SSL3_RT_APPLICATION_DATA); i = s->handshake_func(s); if (i < 0) { return i; } if (i == 0) { OPENSSL_PUT_ERROR(SSL, 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->s3->rrec; /* get new packet if necessary */ if (rr->length == 0) { ret = ssl3_get_record(s); if (ret <= 0) { return ret; } } /* we now have a packet which can be read and processed */ /* |change_cipher_spec is set when we receive a ChangeCipherSpec and reset by * ssl3_get_finished. */ if (s->s3->change_cipher_spec && rr->type != SSL3_RT_HANDSHAKE && rr->type != SSL3_RT_ALERT) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); goto f_err; } /* If we are expecting a ChangeCipherSpec, it is illegal to receive a * Handshake record. */ if (rr->type == SSL3_RT_HANDSHAKE && (s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS); goto f_err; } /* If the other end has shut down, throw anything we read away (even in * 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { rr->length = 0; s->rwstate = SSL_NOTHING; return 0; } if (type != 0 && type == rr->type) { s->s3->warning_alert_count = 0; /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ /* 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->aead_read_ctx == NULL) { /* TODO(davidben): Is this check redundant with the handshake_func * check? */ al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE); goto f_err; } /* Discard empty records. */ if (rr->length == 0) { goto start; } if (len <= 0) { return len; } if ((unsigned int)len > rr->length) { n = rr->length; } else { n = (unsigned int)len; } memcpy(buf, &(rr->data[rr->off]), n); if (!peek) { rr->length -= n; rr->off += n; if (rr->length == 0) { rr->off = 0; /* The record has been consumed, so we may now clear the buffer. */ ssl_read_buffer_discard(s); } } return n; } /* Process unexpected records. */ if (rr->type == SSL3_RT_HANDSHAKE) { /* If peer renegotiations are disabled, all out-of-order handshake records * are fatal. Renegotiations as a server are never supported. */ if (s->server || !ssl3_can_renegotiate(s)) { al = SSL_AD_NO_RENEGOTIATION; OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); goto f_err; } /* HelloRequests may be fragmented across multiple records. */ const size_t size = sizeof(s->s3->handshake_fragment); const size_t avail = size - s->s3->handshake_fragment_len; const size_t todo = (rr->length < avail) ? rr->length : avail; memcpy(s->s3->handshake_fragment + s->s3->handshake_fragment_len, &rr->data[rr->off], todo); rr->off += todo; rr->length -= todo; s->s3->handshake_fragment_len += todo; if (s->s3->handshake_fragment_len < size) { goto start; /* fragment was too small */ } /* Parse out and consume a HelloRequest. */ if (s->s3->handshake_fragment[0] != SSL3_MT_HELLO_REQUEST || s->s3->handshake_fragment[1] != 0 || s->s3->handshake_fragment[2] != 0 || s->s3->handshake_fragment[3] != 0) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST); goto f_err; } s->s3->handshake_fragment_len = 0; if (s->msg_callback) { s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg); } if (!SSL_is_init_finished(s) || !s->s3->initial_handshake_complete) { /* This cannot happen. If a handshake is in progress, |type| must be * |SSL3_RT_HANDSHAKE|. */ assert(0); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } /* Renegotiation is only supported at quiescent points in the application * protocol, namely in HTTPS, just before reading the HTTP response. Require * the record-layer be idle and avoid complexities of sending a handshake * record while an application_data record is being written. */ if (ssl_write_buffer_is_pending(s)) { al = SSL_AD_NO_RENEGOTIATION; OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); goto f_err; } /* Begin a new handshake. */ s->s3->total_renegotiations++; s->state = SSL_ST_CONNECT; i = s->handshake_func(s); if (i < 0) { return i; } if (i == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE); return -1; } /* The handshake completed synchronously. Continue reading records. */ goto start; } /* If an alert record, process one alert out of the record. Note that we allow * a single record to contain multiple alerts. */ if (rr->type == SSL3_RT_ALERT) { /* Alerts may not be fragmented. */ if (rr->length < 2) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT); goto f_err; } if (s->msg_callback) { s->msg_callback(0, s->version, SSL3_RT_ALERT, &rr->data[rr->off], 2, s, s->msg_callback_arg); } const uint8_t alert_level = rr->data[rr->off++]; const uint8_t alert_descr = rr->data[rr->off++]; rr->length -= 2; if (s->info_callback != NULL) { cb = s->info_callback; } else if (s->ctx->info_callback != NULL) { cb = s->ctx->info_callback; } if (cb != NULL) { uint16_t alert = (alert_level << 8) | alert_descr; cb(s, SSL_CB_READ_ALERT, alert); } if (alert_level == SSL3_AL_WARNING) { s->s3->warn_alert = alert_descr; if (alert_descr == SSL_AD_CLOSE_NOTIFY) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return 0; } /* This is a warning but we receive it if we requested renegotiation and * the peer denied it. Terminate with a fatal alert because if * application tried to renegotiatie it presumably had a good reason and * expects it to succeed. * * In future we might have a renegotiation where we don't care if the * peer refused it where we carry on. */ else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { al = SSL_AD_HANDSHAKE_FAILURE; OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); goto f_err; } s->s3->warning_alert_count++; if (s->s3->warning_alert_count > kMaxWarningAlerts) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS); goto f_err; } } else if (alert_level == SSL3_AL_FATAL) { char tmp[16]; s->rwstate = SSL_NOTHING; s->s3->fatal_alert = alert_descr; OPENSSL_PUT_ERROR(SSL, 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); return 0; } else { al = SSL_AD_ILLEGAL_PARAMETER; OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE); goto f_err; } goto start; } if (s->shutdown & SSL_SENT_SHUTDOWN) { /* close_notify has been sent, so discard all records other than alerts. */ rr->length = 0; goto start; } if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { /* 'Change Cipher Spec' is just a single byte, so we know exactly what the * record payload has to look like */ if (rr->length != 1 || rr->off != 0 || rr->data[0] != SSL3_MT_CCS) { al = SSL_AD_ILLEGAL_PARAMETER; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } if (!(s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) { al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->s3->flags &= ~SSL3_FLAGS_EXPECT_CCS; rr->length = 0; if (s->msg_callback) { s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg); } s->s3->change_cipher_spec = 1; if (!ssl3_do_change_cipher_spec(s)) { goto err; } else { goto start; } } /* We already handled these. */ assert(rr->type != SSL3_RT_CHANGE_CIPHER_SPEC && rr->type != SSL3_RT_ALERT && rr->type != SSL3_RT_HANDSHAKE); al = SSL_AD_UNEXPECTED_MESSAGE; OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: return -1; }
MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt) { int al; long remain; remain = PACKET_remaining(pkt); /* * 'Change Cipher Spec' is just a single byte, which should already have * been consumed by ssl_get_message() so there should be no bytes left, * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes */ if (SSL_IS_DTLS(s)) { if ((s->version == DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH + 1) || (s->version != DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH - 1)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } else { if (remain != 0) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->s3->change_cipher_spec = 1; if (!ssl3_do_change_cipher_spec(s)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); goto f_err; } if (SSL_IS_DTLS(s)) { 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 } return MSG_PROCESS_CONTINUE_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }
/*- * 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), ChangeCipherSpec records (not really * a surprise, but handled as if it were), or renegotiation requests. * 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, 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, peek))) return ret; /* * 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 ((!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) && s->s3->in_read_app_data != 2)) #else if (!s->in_handshake && SSL_in_init(s)) #endif { /* 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 (s->state == SSL_ST_OK && 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; } } if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) { SSL3_RECORD_set_length(rr, 0); goto start; } /* 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_RT_APPLICATION_DATA or * SSL3_RT_HANDSHAKE */ /* * 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 (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_add_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 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 && (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) { 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 * 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) == TLS1_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 pathalogical 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 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; 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->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) { 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 goto start; } /* * Unexpected handshake message (Client Hello, or protocol violation) */ if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && !s->in_handshake) { 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 (((s->state & SSL_ST_MASK) == SSL_ST_OK) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; 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 s->in_handshake is set, 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) && (((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) ) )) { 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); err: return (-1); }