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)) { if (!SSL_clear(s)) return -1; } #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; s->state = SSL_ST_ERR; goto end; } /* s->version=SSL3_VERSION; */ s->type = SSL_ST_CONNECT; if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; buf = NULL; } if (!ssl3_setup_buffers(s)) { ret = -1; s->state = SSL_ST_ERR; goto end; } /* setup buffing BIO */ if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; s->state = SSL_ST_ERR; 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; /* * Should have been reset by ssl3_get_finished, too. */ s->s3->change_cipher_spec = 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 = ssl3_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); if (SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0) <= 0) { ret = -1; s->state = SSL_ST_ERR; goto end; } BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif s->state = SSL3_ST_CR_CHANGE_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: /* 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; 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; } 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; s->state = SSL_ST_ERR; 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 = ssl3_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 = ssl3_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); if (SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0) <= 0) { ret = -1; s->state = SSL_ST_ERR; goto end; } 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->init_num = 0; break; case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: dtls1_start_timer(s); ret = ssl3_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; 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; 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; s->state = SSL_ST_ERR; goto end; } if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; s->state = SSL_ST_ERR; 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 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 = ssl3_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; 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 } else { #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 /* * Allow NewSessionTicket if ticket expected */ if (s->tlsext_ticket_expected) s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A; else s->s3->tmp.next_state = SSL3_ST_CR_CHANGE_A; } s->init_num = 0; break; 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_CHANGE_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; case SSL3_ST_CR_CHANGE_A: case SSL3_ST_CR_CHANGE_B: ret = ssl3_get_change_cipher_spec(s, SSL3_ST_CR_CHANGE_A, SSL3_ST_CR_CHANGE_B); if (ret <= 0) goto end; s->state = SSL3_ST_CR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: 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); /* Remove the buffering */ ssl_free_wbio_buffer(s); 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; */ case SSL_ST_ERR: default: SSLerr(SSL_F_DTLS1_CONNECT, SSL_R_UNKNOWN_STATE); ret = -1; goto end; /* break; */ } /* did we do anything */ 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_CONNECT_LOOP, 1); s->state = new_state; } } skip = 0; } end: s->in_handshake--; #ifndef OPENSSL_NO_SCTP /* * Notify SCTP BIO socket to leave handshake mode and allow 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 BUF_MEM_free(buf); if (cb != NULL) cb(s, SSL_CB_CONNECT_EXIT, ret); return (ret); }
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; #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; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) { if (!SSL_clear(s)) return -1; } #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_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; s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(buf); ret = -1; s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; } if (!ssl3_setup_buffers(s)) { ret = -1; s->state = SSL_ST_ERR; goto end; } s->init_num = 0; /* * Should have been reset by ssl3_get_finished, too. */ s->s3->change_cipher_spec = 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; s->state = SSL_ST_ERR; 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; 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_CHANGE_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); if (SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0) <= 0) { ret = -1; s->state = SSL_ST_ERR; goto end; } 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 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; 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; /* * clear this, it may get reset by * send_server_key_exchange */ s->s3->tmp.use_rsa_tmp = 0; /* * only send if a DH key exchange or RSA but we have a sign only * certificate */ if (0 /* * PSK: send ServerKeyExchange if PSK identity hint if * provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->cert->psk_identity_hint) #endif || (alg_k & SSL_kDHE) || (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)) /* * 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; 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 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: 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: 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); if (SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0) <= 0) { ret = -1; s->state = SSL_ST_ERR; goto end; } 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_CHANGE_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; if (!s->s3->handshake_buffer) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; return -1; } /* * For sigalgs freeze the handshake buffer. If we support * extms we've done this already. */ if (!ssl3_digest_cached_records(s, 1)) { s->state = SSL_ST_ERR; 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: 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_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SR_CHANGE_A: case SSL3_ST_SR_CHANGE_B: ret = ssl3_get_change_cipher_spec(s, SSL3_ST_SR_CHANGE_A, SSL3_ST_SR_CHANGE_B); if (ret <= 0) goto end; s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; 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_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; s->state = SSL_ST_ERR; 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; s->state = SSL_ST_ERR; 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_CHANGE_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; */ case SSL_ST_ERR: 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); }