diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2017-10-10 15:13:27 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2017-10-10 15:13:27 +0000 |
commit | 80dc1b4d92d9760afe2ed500f7548d67e8826fd5 (patch) | |
tree | 92d9c8cb146a3db8f2d1bc38f7afa73094c7d34b /lib | |
parent | a00fa196b7d1e42160ed969d99f8ee3ff75f8d26 (diff) |
Merge dtls1_connect() into ssl3_connect(), removing a large amount of
duplicated code. For now this is essentially adds a diff of the two
functions with 'if (SSL_IS_DTLS(s))' - further clean up and improvement
will follow.
ok inoguchi@
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libssl/d1_clnt.c | 436 | ||||
-rw-r--r-- | lib/libssl/d1_meth.c | 4 | ||||
-rw-r--r-- | lib/libssl/ssl_clnt.c | 132 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 4 |
4 files changed, 117 insertions, 459 deletions
diff --git a/lib/libssl/d1_clnt.c b/lib/libssl/d1_clnt.c index 5a5e17699d8..f3a7e5ff22a 100644 --- a/lib/libssl/d1_clnt.c +++ b/lib/libssl/d1_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_clnt.c,v 1.78 2017/10/08 16:54:28 jsing Exp $ */ +/* $OpenBSD: d1_clnt.c,v 1.79 2017/10/10 15:13:26 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -127,8 +127,6 @@ #include "bytestring.h" -static int dtls1_get_hello_verify(SSL *s); - static const SSL_METHOD_INTERNAL DTLSv1_client_method_internal_data = { .version = DTLS1_VERSION, .min_version = DTLS1_VERSION, @@ -137,7 +135,7 @@ static const SSL_METHOD_INTERNAL DTLSv1_client_method_internal_data = { .ssl_clear = dtls1_clear, .ssl_free = dtls1_free, .ssl_accept = ssl_undefined_function, - .ssl_connect = dtls1_connect, + .ssl_connect = ssl3_connect, .ssl_read = ssl3_read, .ssl_peek = ssl3_peek, .ssl_write = ssl3_write, @@ -178,436 +176,6 @@ dtls1_get_client_method(int ver) } int -dtls1_connect(SSL *s) -{ - void (*cb)(const SSL *ssl, int type, int val) = NULL; - int ret = -1; - int new_state, state, skip = 0; - - ERR_clear_error(); - errno = 0; - - if (s->internal->info_callback != NULL) - cb = s->internal->info_callback; - else if (s->ctx->internal->info_callback != NULL) - cb = s->ctx->internal->info_callback; - - s->internal->in_handshake++; - if (!SSL_in_init(s) || SSL_in_before(s)) - SSL_clear(s); - - for (;;) { - state = S3I(s)->hs.state; - - switch (S3I(s)->hs.state) { - case SSL_ST_RENEGOTIATE: - s->internal->renegotiate = 1; - S3I(s)->hs.state = SSL_ST_CONNECT; - s->ctx->internal->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)) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } - - /* s->version=SSL3_VERSION; */ - s->internal->type = SSL_ST_CONNECT; - - if (!ssl3_setup_init_buffer(s)) { - ret = -1; - goto end; - } - if (!ssl3_setup_buffers(s)) { - ret = -1; - goto end; - } - if (!ssl_init_wbio_buffer(s, 0)) { - ret = -1; - goto end; - } - - /* don't push the buffering BIO quite yet */ - - S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; - s->ctx->internal->stats.sess_connect++; - s->internal->init_num = 0; - /* mark client_random uninitialized */ - memset(s->s3->client_random, 0, - sizeof(s->s3->client_random)); - D1I(s)->send_cookie = 0; - s->internal->hit = 0; - break; - - case SSL3_ST_CW_CLNT_HELLO_A: - case SSL3_ST_CW_CLNT_HELLO_B: - - s->internal->shutdown = 0; - - /* every DTLS ClientHello resets Finished MAC */ - if (!tls1_init_finished_mac(s)) { - ret = -1; - goto end; - } - - dtls1_start_timer(s); - ret = ssl3_client_hello(s); - if (ret <= 0) - goto end; - - if (D1I(s)->send_cookie) { - S3I(s)->hs.state = SSL3_ST_CW_FLUSH; - S3I(s)->hs.next_state = SSL3_ST_CR_SRVR_HELLO_A; - } else - S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A; - - s->internal->init_num = 0; - - /* turn on buffering for the next lot of output */ - if (s->bbio != s->wbio) - s->wbio = BIO_push(s->bbio, s->wbio); - - 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; - if (s->internal->hit) - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; - else - S3I(s)->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; - s->internal->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 ( D1I(s)->send_cookie) /* start again, with a cookie */ - S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; - else - S3I(s)->hs.state = SSL3_ST_CR_CERT_A; - s->internal->init_num = 0; - break; - - case SSL3_ST_CR_CERT_A: - case SSL3_ST_CR_CERT_B: - ret = ssl3_check_finished(s); - if (ret <= 0) - goto end; - if (ret == 2) { - s->internal->hit = 1; - if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A; - else - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; - s->internal->init_num = 0; - break; - } - /* Check if it is anon DH/ECDH. */ - if (!(S3I(s)->hs.new_cipher->algorithm_auth & - SSL_aNULL)) { - ret = ssl3_get_server_certificate(s); - if (ret <= 0) - goto end; - if (s->internal->tlsext_status_expected) - S3I(s)->hs.state = SSL3_ST_CR_CERT_STATUS_A; - else - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; - } else { - skip = 1; - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; - } - s->internal->init_num = 0; - break; - - case SSL3_ST_CR_KEY_EXCH_A: - case SSL3_ST_CR_KEY_EXCH_B: - ret = ssl3_get_server_key_exchange(s); - if (ret <= 0) - goto end; - S3I(s)->hs.state = SSL3_ST_CR_CERT_REQ_A; - s->internal->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; - S3I(s)->hs.state = SSL3_ST_CR_SRVR_DONE_A; - s->internal->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 (S3I(s)->tmp.cert_req) - S3I(s)->hs.state = SSL3_ST_CW_CERT_A; - else - S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_A; - s->internal->init_num = 0; - 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; - S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_A; - s->internal->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; - /* - * 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 - */ - /* - * XXX: For now, we do not support client - * authentication in ECDH cipher suites with - * ECDH (rather than ECDSA) certificates. - * We need to skip the certificate verify - * message when client's ECDH public key is sent - * inside the client certificate. - */ - if (S3I(s)->tmp.cert_req == 1) { - S3I(s)->hs.state = SSL3_ST_CW_CERT_VRFY_A; - } else { - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - S3I(s)->change_cipher_spec = 0; - } - - s->internal->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; - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - s->internal->init_num = 0; - S3I(s)->change_cipher_spec = 0; - break; - - case SSL3_ST_CW_CHANGE_A: - case SSL3_ST_CW_CHANGE_B: - if (!s->internal->hit) - dtls1_start_timer(s); - ret = ssl3_send_change_cipher_spec(s, - SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B); - if (ret <= 0) - goto end; - - S3I(s)->hs.state = SSL3_ST_CW_FINISHED_A; - s->internal->init_num = 0; - - s->session->cipher = S3I(s)->hs.new_cipher; - if (!tls1_setup_key_block(s)) { - ret = -1; - goto end; - } - - if (!tls1_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->internal->hit) - dtls1_start_timer(s); - ret = ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, - SSL3_ST_CW_FINISHED_B, TLS_MD_CLIENT_FINISH_CONST, - TLS_MD_CLIENT_FINISH_CONST_SIZE); - if (ret <= 0) - goto end; - S3I(s)->hs.state = SSL3_ST_CW_FLUSH; - - /* clear flags */ - s->s3->flags &= ~SSL3_FLAGS_POP_BUFFER; - if (s->internal->hit) { - S3I(s)->hs.next_state = SSL_ST_OK; - if (s->s3->flags & - SSL3_FLAGS_DELAY_CLIENT_FINISHED) { - S3I(s)->hs.state = SSL_ST_OK; - s->s3->flags |= SSL3_FLAGS_POP_BUFFER; - S3I(s)->delay_buf_pop_ret = 0; - } - } else { - /* Allow NewSessionTicket if ticket expected */ - if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.next_state = - SSL3_ST_CR_SESSION_TICKET_A; - else - S3I(s)->hs.next_state = - SSL3_ST_CR_FINISHED_A; - } - s->internal->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; - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; - s->internal->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; - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; - s->internal->init_num = 0; - break; - - case SSL3_ST_CR_FINISHED_A: - case SSL3_ST_CR_FINISHED_B: - D1I(s)->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->internal->hit) - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - else - S3I(s)->hs.state = SSL_ST_OK; - - s->internal->init_num = 0; - break; - - case SSL3_ST_CW_FLUSH: - s->internal->rwstate = SSL_WRITING; - if (BIO_flush(s->wbio) <= 0) { - /* If the write error was fatal, stop trying */ - if (!BIO_should_retry(s->wbio)) { - s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.next_state; - } - - ret = -1; - goto end; - } - s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.next_state; - break; - - case SSL_ST_OK: - /* clean a few things up */ - tls1_cleanup_key_block(s); - - /* - * 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->internal->init_num = 0; - s->internal->renegotiate = 0; - s->internal->new_session = 0; - - ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); - if (s->internal->hit) - s->ctx->internal->stats.sess_hit++; - - ret = 1; - /* s->server=0; */ - s->internal->handshake_func = dtls1_connect; - s->ctx->internal->stats.sess_connect_good++; - - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_DONE, 1); - - /* done with handshaking */ - D1I(s)->handshake_read_seq = 0; - D1I(s)->next_handshake_write_seq = 0; - goto end; - /* break; */ - - default: - SSLerror(s, SSL_R_UNKNOWN_STATE); - ret = -1; - goto end; - /* break; */ - } - - /* did we do anything */ - if (!S3I(s)->tmp.reuse_message && !skip) { - if (s->internal->debug) { - if ((ret = BIO_flush(s->wbio)) <= 0) - goto end; - } - - if ((cb != NULL) && (S3I(s)->hs.state != state)) { - new_state = S3I(s)->hs.state; - S3I(s)->hs.state = state; - cb(s, SSL_CB_CONNECT_LOOP, 1); - S3I(s)->hs.state = new_state; - } - } - skip = 0; - } - -end: - s->internal->in_handshake--; - if (cb != NULL) - cb(s, SSL_CB_CONNECT_EXIT, ret); - - return (ret); -} - -static int dtls1_get_hello_verify(SSL *s) { long n; diff --git a/lib/libssl/d1_meth.c b/lib/libssl/d1_meth.c index fcd8906c456..e513c4a9be9 100644 --- a/lib/libssl/d1_meth.c +++ b/lib/libssl/d1_meth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_meth.c,v 1.13 2017/01/23 13:36:13 jsing Exp $ */ +/* $OpenBSD: d1_meth.c,v 1.14 2017/10/10 15:13:26 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -73,7 +73,7 @@ static const SSL_METHOD_INTERNAL DTLSv1_method_internal_data = { .ssl_clear = dtls1_clear, .ssl_free = dtls1_free, .ssl_accept = dtls1_accept, - .ssl_connect = dtls1_connect, + .ssl_connect = ssl3_connect, .ssl_read = ssl3_read, .ssl_peek = ssl3_peek, .ssl_write = ssl3_write, diff --git a/lib/libssl/ssl_clnt.c b/lib/libssl/ssl_clnt.c index fb4d9da1740..dce5a7d008f 100644 --- a/lib/libssl/ssl_clnt.c +++ b/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.18 2017/10/08 16:42:21 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.19 2017/10/10 15:13:26 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -210,10 +210,18 @@ ssl3_connect(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); - if ((s->version & 0xff00) != 0x0300) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; + if (SSL_IS_DTLS(s)) { + if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + } else { + if ((s->version & 0xff00) != 0x0300) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } } /* s->version=SSL3_VERSION; */ @@ -234,24 +242,50 @@ ssl3_connect(SSL *s) /* don't push the buffering BIO quite yet */ - if (!tls1_init_finished_mac(s)) { - ret = -1; - goto end; + if (!SSL_IS_DTLS(s)) { + if (!tls1_init_finished_mac(s)) { + ret = -1; + goto end; + } } S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; s->ctx->internal->stats.sess_connect++; s->internal->init_num = 0; + + if (SSL_IS_DTLS(s)) { + /* mark client_random uninitialized */ + memset(s->s3->client_random, 0, + sizeof(s->s3->client_random)); + D1I(s)->send_cookie = 0; + s->internal->hit = 0; + } break; case SSL3_ST_CW_CLNT_HELLO_A: case SSL3_ST_CW_CLNT_HELLO_B: - s->internal->shutdown = 0; + + if (SSL_IS_DTLS(s)) { + /* every DTLS ClientHello resets Finished MAC */ + if (!tls1_init_finished_mac(s)) { + ret = -1; + goto end; + } + + dtls1_start_timer(s); + } + ret = ssl3_client_hello(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A; + + if (SSL_IS_DTLS(s) && D1I(s)->send_cookie) { + S3I(s)->hs.state = SSL3_ST_CW_FLUSH; + S3I(s)->hs.next_state = SSL3_ST_CR_SRVR_HELLO_A; + } else + S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A; + s->internal->init_num = 0; /* turn on buffering for the next lot of output */ @@ -268,11 +302,29 @@ ssl3_connect(SSL *s) if (s->internal->hit) { S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; - if (s->internal->tlsext_ticket_expected) { - /* receive renewed session ticket */ - S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + if (!SSL_IS_DTLS(s)) { + if (s->internal->tlsext_ticket_expected) { + /* receive renewed session ticket */ + S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + } } - } else + } else if (SSL_IS_DTLS(s)) { + S3I(s)->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; + } else { + S3I(s)->hs.state = SSL3_ST_CR_CERT_A; + } + s->internal->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 (D1I(s)->send_cookie) /* start again, with a cookie */ + S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; + else S3I(s)->hs.state = SSL3_ST_CR_CERT_A; s->internal->init_num = 0; break; @@ -340,6 +392,8 @@ ssl3_connect(SSL *s) ret = ssl3_get_server_done(s); if (ret <= 0) goto end; + if (SSL_IS_DTLS(s)) + dtls1_stop_timer(s); if (S3I(s)->tmp.cert_req) S3I(s)->hs.state = SSL3_ST_CW_CERT_A; else @@ -352,6 +406,8 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_CERT_B: case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: + if (SSL_IS_DTLS(s)) + dtls1_start_timer(s); ret = ssl3_send_client_certificate(s); if (ret <= 0) goto end; @@ -361,6 +417,8 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: + if (SSL_IS_DTLS(s)) + dtls1_start_timer(s); ret = ssl3_send_client_key_exchange(s); if (ret <= 0) goto end; @@ -386,9 +444,11 @@ ssl3_connect(SSL *s) S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; S3I(s)->change_cipher_spec = 0; } - if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - S3I(s)->change_cipher_spec = 0; + if (!SSL_IS_DTLS(s)) { + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; + S3I(s)->change_cipher_spec = 0; + } } s->internal->init_num = 0; @@ -396,6 +456,8 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: + if (SSL_IS_DTLS(s)) + dtls1_start_timer(s); ret = ssl3_send_client_verify(s); if (ret <= 0) goto end; @@ -406,6 +468,8 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_CHANGE_A: case SSL3_ST_CW_CHANGE_B: + if (SSL_IS_DTLS(s) && !s->internal->hit) + dtls1_start_timer(s); ret = ssl3_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B); if (ret <= 0) @@ -426,16 +490,22 @@ ssl3_connect(SSL *s) goto end; } + if (SSL_IS_DTLS(s)) + dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); + break; case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: + if (SSL_IS_DTLS(s) && !s->internal->hit) + dtls1_start_timer(s); ret = ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B, TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE); if (ret <= 0) goto end; - s->s3->flags |= SSL3_FLAGS_CCS_OK; + if (!SSL_IS_DTLS(s)) + s->s3->flags |= SSL3_FLAGS_CCS_OK; S3I(s)->hs.state = SSL3_ST_CW_FLUSH; /* clear flags */ @@ -480,11 +550,16 @@ ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - s->s3->flags |= SSL3_FLAGS_CCS_OK; + if (SSL_IS_DTLS(s)) + D1I(s)->change_cipher_spec_ok = 1; + else + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; + if (SSL_IS_DTLS(s)) + dtls1_stop_timer(s); if (s->internal->hit) S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; @@ -496,6 +571,13 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_FLUSH: s->internal->rwstate = SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { + if (SSL_IS_DTLS(s)) { + /* If the write error was fatal, stop trying */ + if (!BIO_should_retry(s->wbio)) { + s->internal->rwstate = SSL_NOTHING; + S3I(s)->hs.state = S3I(s)->hs.next_state; + } + } ret = -1; goto end; } @@ -507,8 +589,10 @@ ssl3_connect(SSL *s) /* clean a few things up */ tls1_cleanup_key_block(s); - BUF_MEM_free(s->internal->init_buf); - s->internal->init_buf = NULL; + if (!SSL_IS_DTLS(s)) { + BUF_MEM_free(s->internal->init_buf); + s->internal->init_buf = NULL; + } /* * If we are not 'joining' the last two packets, @@ -534,6 +618,12 @@ ssl3_connect(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_DONE, 1); + if (SSL_IS_DTLS(s)) { + /* done with handshaking */ + D1I(s)->handshake_read_seq = 0; + D1I(s)->next_handshake_write_seq = 0; + } + goto end; /* break; */ diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index 2fec36fba9a..eed0803a852 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.194 2017/10/08 16:24:02 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.195 2017/10/10 15:13:26 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1199,6 +1199,7 @@ void dtls1_double_timeout(SSL *s); unsigned int dtls1_min_mtu(void); /* some client-only functions */ +int dtls1_get_hello_verify(SSL *s); int ssl3_client_hello(SSL *s); int ssl3_get_server_hello(SSL *s); int ssl3_get_certificate_request(SSL *s); @@ -1236,7 +1237,6 @@ void tls1_clear(SSL *s); int dtls1_new(SSL *s); int dtls1_accept(SSL *s); -int dtls1_connect(SSL *s); void dtls1_free(SSL *s); void dtls1_clear(SSL *s); long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); |