int dtls1_accept(SSL *s) { BUF_MEM *buf; unsigned long Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; unsigned long alg_k; int ret= -1; int new_state,state,skip=0; int listen; #ifndef OPENSSL_NO_SCTP unsigned char sctpauthkey[64]; char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; #endif RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; #ifndef OPENSSL_NO_SCTP /* Notify SCTP BIO socket to enter handshake * mode and prevent stream identifier other * than 0. Will be ignored if no SCTP is used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL); #endif if (s->cert == NULL) { SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET); return(-1); } #ifndef OPENSSL_NO_HEARTBEATS /* If we're awaiting a HeartbeatResponse, pretend we * already got and don't await it anymore, because * Heartbeats don't make sense during handshakes anyway. */ if (s->tlsext_hb_pending) { dtls1_stop_timer(s); s->tlsext_hb_pending = 0; s->tlsext_hb_seq++; } #endif for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ #ifndef OPENSSL_NO_SCTP if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) #endif if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if ( ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ if (s->version != DTLS1_BAD_VER) ssl3_init_finished_mac(s); break; #ifndef OPENSSL_NO_SCTP case DTLS1_SCTP_ST_SR_READ_SOCK: if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } s->state=SSL3_ST_SR_FINISHED_A; break; case DTLS1_SCTP_ST_SW_WRITE_SOCK: ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); if (ret < 0) goto end; if (ret == 0) { if (s->d1->next_state != SSL_ST_OK) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } } s->state=s->d1->next_state; break; #endif case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif #ifndef OPENSSL_NO_TLSEXT 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_CHANGE_A; #endif } 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: /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_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; } #else } else skip=1; s->state=SSL3_ST_SW_KEY_EXCH_A; #endif s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* clear this, it may get reset by * send_server_key_exchange */ if ((s->options & SSL_OP_EPHEMERAL_RSA) #ifndef OPENSSL_NO_KRB5 && !(alg_k & SSL_kKRB5) #endif /* OPENSSL_NO_KRB5 */ ) /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key * even when forbidden by protocol specs * (handshake may fail as clients are not required to * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; /* only send if a DH key exchange or * RSA but we have a sign only certificate */ if (s->s3->tmp.use_rsa_tmp /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif || (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) || (alg_k & SSL_kECDHE) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) ) ) ) ) { 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 (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } else { s->s3->tmp.cert_request=1; dtls1_start_timer(s); ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #endif 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) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; } 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: /* Check for second client hello (MS SGC) */ ret = ssl3_check_client_hello(s); if (ret <= 0) goto end; if (ret == 2) { dtls1_stop_timer(s); s->state = SSL3_ST_SR_CLNT_HELLO_C; } else { /* could be sent for a DH cert, even if we * have not asked for it :-) */ 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: ret=ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state=SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else if (SSL_USE_SIGALGS(s)) { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (!s->session->peer) break; /* For sigalgs freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) { SSLerr(SSL_F_DTLS1_ACCEPT,ERR_R_INTERNAL_ERROR); return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; if (!ssl3_digest_cached_records(s)) return -1; } else { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && state == SSL_ST_RENEGOTIATE) s->state=DTLS1_SCTP_ST_SR_READ_SOCK; else #endif s->state=SSL3_ST_SR_FINISHED_A; s->init_num=0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; 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; #ifndef OPENSSL_NO_TLSEXT else if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; #endif else s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; #endif case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->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; #ifndef OPENSSL_NO_SCTP if (!s->hit) { /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); } #endif s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); 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->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->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_FINISHED_A; #ifndef OPENSSL_NO_SCTP /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); #endif } else { s->s3->tmp.next_state=SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } s->init_num=0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 BUF_MEM_free(s->init_buf); s->init_buf=NULL; #endif /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=dtls1_accept; 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; /* break; */ default: SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ }
int dtls1_connect(SSL *s) { BUF_MEM *buf=NULL; unsigned long Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state,skip=0; #ifndef OPENSSL_NO_SCTP unsigned char sctpauthkey[64]; char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; #endif RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_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++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); #ifndef OPENSSL_NO_SCTP /* Notify SCTP BIO socket to enter handshake * mode and prevent stream identifier other * than 0. Will be ignored if no SCTP is used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL); #endif #ifndef OPENSSL_NO_HEARTBEATS /* If we're awaiting a HeartbeatResponse, pretend we * already got and don't await it anymore, because * Heartbeats don't make sense during handshakes anyway. */ if (s->tlsext_hb_pending) { dtls1_stop_timer(s); s->tlsext_hb_pending = 0; s->tlsext_hb_seq++; } #endif for (;;) { state=s->state; switch(s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; s->state=SSL_ST_CONNECT; s->ctx->stats.sess_connect_renegotiate++; /* break */ case SSL_ST_BEFORE: case SSL_ST_CONNECT: case SSL_ST_BEFORE|SSL_ST_CONNECT: case SSL_ST_OK|SSL_ST_CONNECT: s->server=0; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) && (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00)) { SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } /* s->version=SSL3_VERSION; */ s->type=SSL_ST_CONNECT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; buf=NULL; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } /* setup buffing BIO */ if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; } /* don't push the buffering BIO quite yet */ s->state=SSL3_ST_CW_CLNT_HELLO_A; s->ctx->stats.sess_connect++; s->init_num=0; /* mark client_random uninitialized */ memset(s->s3->client_random,0,sizeof(s->s3->client_random)); s->d1->send_cookie = 0; s->hit = 0; break; #ifndef OPENSSL_NO_SCTP case DTLS1_SCTP_ST_CR_READ_SOCK: if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } s->state=s->s3->tmp.next_state; break; case DTLS1_SCTP_ST_CW_WRITE_SOCK: /* read app data until dry event */ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); if (ret < 0) goto end; if (ret == 0) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } s->state=s->d1->next_state; break; #endif case SSL3_ST_CW_CLNT_HELLO_A: case SSL3_ST_CW_CLNT_HELLO_B: s->shutdown=0; /* every DTLS ClientHello resets Finished MAC */ ssl3_init_finished_mac(s); dtls1_start_timer(s); ret=dtls1_client_hello(s); if (ret <= 0) goto end; if ( s->d1->send_cookie) { s->state=SSL3_ST_CW_FLUSH; s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A; } else s->state=SSL3_ST_CR_SRVR_HELLO_A; s->init_num=0; #ifndef OPENSSL_NO_SCTP /* Disable buffering for SCTP */ if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) { #endif /* turn on buffering for the next lot of output */ if (s->bbio != s->wbio) s->wbio=BIO_push(s->bbio,s->wbio); #ifndef OPENSSL_NO_SCTP } #endif break; case SSL3_ST_CR_SRVR_HELLO_A: case SSL3_ST_CR_SRVR_HELLO_B: ret=ssl3_get_server_hello(s); if (ret <= 0) goto end; else { if (s->hit) { #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif s->state=SSL3_ST_CR_FINISHED_A; } else s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; } s->init_num=0; break; case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: ret = dtls1_get_hello_verify(s); if ( ret <= 0) goto end; dtls1_stop_timer(s); if ( s->d1->send_cookie) /* start again, with a cookie */ s->state=SSL3_ST_CW_CLNT_HELLO_A; else s->state = SSL3_ST_CR_CERT_A; s->init_num = 0; break; case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: #ifndef OPENSSL_NO_TLSEXT ret=ssl3_check_finished(s); if (ret <= 0) goto end; if (ret == 2) { s->hit = 1; if (s->tlsext_ticket_expected) s->state=SSL3_ST_CR_SESSION_TICKET_A; else s->state=SSL3_ST_CR_FINISHED_A; s->init_num=0; break; } #endif /* Check if it is anon DH or PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret=ssl3_get_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_status_expected) s->state=SSL3_ST_CR_CERT_STATUS_A; else s->state=SSL3_ST_CR_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_CR_KEY_EXCH_A; } #else } else skip=1; s->state=SSL3_ST_CR_KEY_EXCH_A; #endif s->init_num=0; break; case SSL3_ST_CR_KEY_EXCH_A: case SSL3_ST_CR_KEY_EXCH_B: ret=ssl3_get_key_exchange(s); if (ret <= 0) goto end; s->state=SSL3_ST_CR_CERT_REQ_A; s->init_num=0; /* at this point we check that we have the * required stuff from the server */ if (!ssl3_check_cert_and_algorithm(s)) { ret= -1; goto end; } break; case SSL3_ST_CR_CERT_REQ_A: case SSL3_ST_CR_CERT_REQ_B: ret=ssl3_get_certificate_request(s); if (ret <= 0) goto end; s->state=SSL3_ST_CR_SRVR_DONE_A; s->init_num=0; break; case SSL3_ST_CR_SRVR_DONE_A: case SSL3_ST_CR_SRVR_DONE_B: ret=ssl3_get_server_done(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->s3->tmp.cert_req) s->s3->tmp.next_state=SSL3_ST_CW_CERT_A; else s->s3->tmp.next_state=SSL3_ST_CW_KEY_EXCH_A; s->init_num=0; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && state == SSL_ST_RENEGOTIATE) s->state=DTLS1_SCTP_ST_CR_READ_SOCK; else #endif s->state=s->s3->tmp.next_state; break; case SSL3_ST_CW_CERT_A: case SSL3_ST_CW_CERT_B: case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: dtls1_start_timer(s); ret=dtls1_send_client_certificate(s); if (ret <= 0) goto end; s->state=SSL3_ST_CW_KEY_EXCH_A; s->init_num=0; break; case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: dtls1_start_timer(s); ret=dtls1_send_client_key_exchange(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif /* EAY EAY EAY need to check for DH fix cert * sent back */ /* For TLS, cert_req is set to 2, so a cert chain * of nothing is sent, but no verify packet is sent */ if (s->s3->tmp.cert_req == 1) { s->state=SSL3_ST_CW_CERT_VRFY_A; } else { #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state=SSL3_ST_CW_CHANGE_A; s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK; } else #endif s->state=SSL3_ST_CW_CHANGE_A; s->s3->change_cipher_spec=0; } s->init_num=0; break; case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: dtls1_start_timer(s); ret=dtls1_send_client_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state=SSL3_ST_CW_CHANGE_A; s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK; } else #endif s->state=SSL3_ST_CW_CHANGE_A; s->init_num=0; s->s3->change_cipher_spec=0; break; case SSL3_ST_CW_CHANGE_A: case SSL3_ST_CW_CHANGE_B: if (!s->hit) dtls1_start_timer(s); ret=dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); #endif s->state=SSL3_ST_CW_FINISHED_A; s->init_num=0; s->session->cipher=s->s3->tmp.new_cipher; #ifdef OPENSSL_NO_COMP s->session->compress_meth=0; #else if (s->s3->tmp.new_compression == NULL) s->session->compress_meth=0; else s->session->compress_meth= s->s3->tmp.new_compression->id; #endif if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: if (!s->hit) dtls1_start_timer(s); ret=dtls1_send_finished(s, SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, s->method->ssl3_enc->client_finished_label, s->method->ssl3_enc->client_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_CW_FLUSH; /* clear flags */ s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; if (s->hit) { s->s3->tmp.next_state=SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state=DTLS1_SCTP_ST_CW_WRITE_SOCK; } #endif if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) { s->state=SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL_ST_OK; s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK; } #endif s->s3->flags|=SSL3_FLAGS_POP_BUFFER; s->s3->delay_buf_pop_ret=0; } } else { #ifndef OPENSSL_NO_TLSEXT /* Allow NewSessionTicket if ticket expected */ if (s->tlsext_ticket_expected) s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A; else #endif s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A; } s->init_num=0; break; #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_CR_SESSION_TICKET_A: case SSL3_ST_CR_SESSION_TICKET_B: ret=ssl3_get_new_session_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_CR_FINISHED_A; s->init_num=0; break; case SSL3_ST_CR_CERT_STATUS_A: case SSL3_ST_CR_CERT_STATUS_B: ret=ssl3_get_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_CR_KEY_EXCH_A; s->init_num=0; break; #endif case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state=SSL3_ST_CW_CHANGE_A; else s->state=SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && state == SSL_ST_RENEGOTIATE) { s->d1->next_state=s->state; s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK; } #endif s->init_num=0; break; case SSL3_ST_CW_FLUSH: s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; } ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 if (s->init_buf != NULL) { BUF_MEM_free(s->init_buf); s->init_buf=NULL; } #endif /* If we are not 'joining' the last two packets, * remove the buffering now */ if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) ssl_free_wbio_buffer(s); /* else do it later in ssl3_write */ s->init_num=0; s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); if (s->hit) s->ctx->stats.sess_hit++; ret=1; /* s->server=0; */ s->handshake_func=dtls1_connect; s->ctx->stats.sess_connect_good++; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ }
/*- * 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); }
/*- * 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, size_t len, int peek, size_t *readbytes) { int i, j, iret; size_t 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)) { /* SSLfatal() already called */ return -1; } } if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE)) || (peek && (type != SSL3_RT_APPLICATION_DATA))) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { /* type == SSL3_RT_APPLICATION_DATA */ i = s->handshake_func(s); /* SSLfatal() already called if appropriate */ if (i < 0) return i; if (i == 0) 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; } else if (ossl_statem_in_error(s)) { /* dtls1_handle_timeout() has failed with a fatal error */ return -1; } /* get new packet if necessary */ if ((SSL3_RECORD_get_length(rr) == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) { RECORD_LAYER_set_numrpipes(&s->rlayer, 0); iret = dtls1_get_record(s); if (iret <= 0) { iret = dtls1_read_failed(s, iret); /* * Anything other than a timeout is an error. SSLfatal() already * called if appropriate. */ if (iret <= 0) return iret; else goto start; } RECORD_LAYER_set_numrpipes(&s->rlayer, 1); } /* * 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) { /* SSLfatal() already called */ return -1; } SSL3_RECORD_set_length(rr, 0); SSL3_RECORD_set_read(rr); 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); SSL3_RECORD_set_read(rr); 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)) { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE); return -1; } if (recvd_type != NULL) *recvd_type = SSL3_RECORD_get_type(rr); if (len == 0) { /* * Mark a zero length record as read. This ensures multiple calls to * SSL_read() with a zero length buffer will eventually cause * SSL_pending() to report data as being available. */ if (SSL3_RECORD_get_length(rr) == 0) SSL3_RECORD_set_read(rr); return 0; } if (len > SSL3_RECORD_get_length(rr)) n = SSL3_RECORD_get_length(rr); else n = len; memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); if (peek) { if (SSL3_RECORD_get_length(rr) == 0) SSL3_RECORD_set_read(rr); } else { 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); SSL3_RECORD_set_read(rr); } } #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 *readbytes = n; return 1; } /* * If we get here, then type != rr->type; if we have a handshake message, * then it was unexpected (Hello Request or Client Hello). */ 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; 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) { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, SSL_R_INVALID_ALERT); return -1; } if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 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; SSL3_RECORD_set_read(rr); s->rlayer.alert_count++; if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); return -1; } 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; } } else if (alert_level == SSL3_AL_FATAL) { char tmp[16]; s->rwstate = SSL_NOTHING; s->s3.fatal_alert = alert_descr; SSLfatal(s, SSL_AD_NO_ALERT, 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; SSL3_RECORD_set_read(rr); SSL_CTX_remove_session(s->session_ctx, s->session); return 0; } else { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE); return -1; } 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); SSL3_RECORD_set_read(rr); 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); SSL3_RECORD_set_read(rr); goto start; } /* * Unexpected handshake message (Client Hello, or protocol violation) */ 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. 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); SSL3_RECORD_set_read(rr); 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. */ if (msg_hdr.type == SSL3_MT_FINISHED) { if (dtls1_check_timeout_num(s) < 0) { /* SSLfatal) already called */ return -1; } if (dtls1_retransmit_buffered_messages(s) <= 0) { /* Fail if we encountered a fatal error */ if (ossl_statem_in_error(s)) return -1; } SSL3_RECORD_set_length(rr, 0); SSL3_RECORD_set_read(rr); if (!(s->mode & SSL_MODE_AUTO_RETRY)) { if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { /* no read-ahead left? */ BIO *bio; s->rwstate = SSL_READING; bio = SSL_get_rbio(s); BIO_clear_retry_flags(bio); BIO_set_retry_read(bio); return -1; } } goto start; } /* * 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))) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } /* We found handshake data, so we're going back into init */ ossl_statem_set_in_init(s, 1); i = s->handshake_func(s); /* SSLfatal() called if appropriate */ if (i < 0) return i; if (i == 0) 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: SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); return -1; 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 */ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; 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 { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); return -1; } } /* not reached */ }
int dtls1_accept(SSL *s) { void (*cb)(const SSL *ssl, int type, int val) = NULL; unsigned long alg_k; int ret = -1; int new_state, state, skip = 0; int listen; #ifndef OPENSSL_NO_SCTP unsigned char sctpauthkey[64]; char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; #endif ERR_clear_error(); errno = 0; if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; #ifndef OPENSSL_NO_SCTP /* Notify SCTP BIO socket to enter handshake * mode and prevent stream identifier other * than 0. Will be ignored if no SCTP is used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL); #endif if (s->cert == NULL) { SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_NO_CERTIFICATE_SET); return (-1); } for (;;) { state = s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate = 1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server = 1; if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type = SSL_ST_ACCEPT; if (s->init_buf == NULL) { BUF_MEM *buf; if ((buf = BUF_MEM_new()) == NULL) { ret = -1; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(buf); ret = -1; goto end; } s->init_buf = buf; } if (!ssl3_setup_buffers(s)) { ret = -1; goto end; } s->init_num = 0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ #ifndef OPENSSL_NO_SCTP if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) #endif if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; goto end; } ssl3_init_finished_mac(s); s->state = SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state = SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown = 0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret = dtls1_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state = SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown = 0; ret = ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num = 0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_FLUSH; s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ if (s->version != DTLS1_BAD_VER) ssl3_init_finished_mac(s); break; #ifndef OPENSSL_NO_SCTP case DTLS1_SCTP_ST_SR_READ_SOCK: if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->s3->in_read_app_data = 2; s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } s->state = SSL3_ST_SR_FINISHED_A; break; case DTLS1_SCTP_ST_SW_WRITE_SOCK: ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); if (ret < 0) goto end; if (ret == 0) { if (s->d1->next_state != SSL_ST_OK) { s->s3->in_read_app_data = 2; s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } } s->state = s->d1->next_state; break; #endif case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret = dtls1_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char*)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif 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: /* Check if it is anon DH. */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) { dtls1_start_timer(s); ret = dtls1_send_server_certificate(s); if (ret <= 0) goto end; if (s->tlsext_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_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* Only send if using a DH key exchange. */ if (alg_k & (SSL_kDHE|SSL_kECDHE)) { dtls1_start_timer(s); ret = dtls1_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: /* * Determine whether or not we need to request a * certificate. * * Do not request a certificate if: * * - We did not ask for it (SSL_VERIFY_PEER is unset). * * - SSL_VERIFY_CLIENT_ONCE is set and we are * renegotiating. * * - We are using an anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246) ... except when the application * insists on verification (against the specs, but * s3_clnt.c accepts this for SSL 3). */ if (!(s->verify_mode & SSL_VERIFY_PEER) || ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { /* no cert request */ skip = 1; s->s3->tmp.cert_request = 0; s->state = SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } else { s->s3->tmp.cert_request = 1; dtls1_start_timer(s); ret = dtls1_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state = SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #else s->state = SSL3_ST_SW_FLUSH; s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #endif s->init_num = 0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret = dtls1_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) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; } 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: /* Check for second client hello (MS SGC) */ ret = ssl3_check_client_hello(s); if (ret <= 0) goto end; if (ret == 2) { dtls1_stop_timer(s); s->state = SSL3_ST_SR_CLNT_HELLO_C; } else { /* could be sent for a DH cert, even if we * have not asked for it :-) */ 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: ret = ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else { s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret = ssl3_get_cert_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && state == SSL_ST_RENEGOTIATE) s->state = DTLS1_SCTP_ST_SR_READ_SOCK; else #endif s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; 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 = dtls1_send_newsession_ticket(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret = ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_KEY_EXCH_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->method->ssl3_enc->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; #ifndef OPENSSL_NO_SCTP if (!s->hit) { /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); } #endif s->state = SSL3_ST_SW_FINISHED_A; s->init_num = 0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret = dtls1_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->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_FINISHED_A; #ifndef OPENSSL_NO_SCTP /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); #endif } else { s->s3->tmp.next_state = SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } s->init_num = 0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num = 0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate = 0; s->new_session = 0; ssl_update_cache(s, SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func = dtls1_accept; 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; /* break; */ default: SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE); ret = -1; goto end; /* break; */ } if (!s->s3->tmp.reuse_message && !skip) { if (s->debug) { if ((ret = BIO_flush(s->wbio)) <= 0) goto end; } 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: /* BIO_flush(s->wbio); */ s->in_handshake--; #ifndef OPENSSL_NO_SCTP /* Notify SCTP BIO socket to leave handshake * mode and prevent stream identifier other * than 0. Will be ignored if no SCTP is used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL); #endif if (cb != NULL) cb(s, SSL_CB_ACCEPT_EXIT, ret); return (ret); }