From 49ae742398aecd81551d59f421e4116a5b8a4ea9 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 8 Sep 2015 09:13:50 +0100 Subject: [PATCH] Remove redundant code Clean up and remove lots of code that is now no longer needed due to the move to the new state machine. Reviewed-by: Tim Hudson Reviewed-by: Richard Levitte --- apps/s_server.c | 2 +- include/openssl/ssl.h | 67 ++- ssl/d1_both.c | 150 ------- ssl/d1_srvr.c | 706 +---------------------------- ssl/record/rec_layer_d1.c | 19 +- ssl/record/rec_layer_s3.c | 6 +- ssl/s3_both.c | 161 +------ ssl/s3_lib.c | 7 +- ssl/s3_msg.c | 4 +- ssl/s3_srvr.c | 916 -------------------------------------- ssl/ssl_lib.c | 19 +- ssl/ssl_locl.h | 81 +--- ssl/ssl_stat.c | 479 ++++++-------------- ssl/statem.c | 83 +++- 14 files changed, 279 insertions(+), 2421 deletions(-) diff --git a/apps/s_server.c b/apps/s_server.c index bfc8b1fcd2..6d68fc1c32 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -2428,7 +2428,7 @@ static int init_ssl_connection(SSL *con) #ifdef CERT_CB_TEST_RETRY { while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP - && SSL_state(con) == SSL3_ST_SR_CLNT_HELLO_C) { + && SSL_state(con) == TLS_ST_SR_CLNT_HELLO) { BIO_printf(bio_err, "LOOKUP from certificate callback during accept\n"); i = SSL_accept(con); diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index de3c3beb24..99f0de65f7 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -920,6 +920,59 @@ extern "C" { # define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0)) # define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg)) + +/* + * The valid handshake states (one for each type message sent and one for each + * type of message received). There are also two "special" states: + * TLS = TLS or DTLS state + * DTLS = DTLS specific state + * CR/SR = Client Read/Server Read + * CW/SW = Client Write/Server Write + * + * The "special" states are: + * TLS_ST_BEFORE = No handshake has been initiated yet + * TLS_ST_OK = A handshake has been successfully completed + */ +enum HANDSHAKE_STATE { + TLS_ST_BEFORE, + TLS_ST_OK, + DTLS_ST_CR_HELLO_VERIFY_REQUEST, + TLS_ST_CR_SRVR_HELLO, + TLS_ST_CR_CERT, + TLS_ST_CR_CERT_STATUS, + TLS_ST_CR_KEY_EXCH, + TLS_ST_CR_CERT_REQ, + TLS_ST_CR_SRVR_DONE, + TLS_ST_CR_SESSION_TICKET, + TLS_ST_CR_CHANGE, + TLS_ST_CR_FINISHED, + TLS_ST_CW_CLNT_HELLO, + TLS_ST_CW_CERT, + TLS_ST_CW_KEY_EXCH, + TLS_ST_CW_CERT_VRFY, + TLS_ST_CW_CHANGE, + TLS_ST_CW_NEXT_PROTO, + TLS_ST_CW_FINISHED, + TLS_ST_SW_HELLO_REQ, + TLS_ST_SR_CLNT_HELLO, + DTLS_ST_SW_HELLO_VERIFY_REQUEST, + TLS_ST_SW_SRVR_HELLO, + TLS_ST_SW_CERT, + TLS_ST_SW_KEY_EXCH, + TLS_ST_SW_CERT_REQ, + TLS_ST_SW_SRVR_DONE, + TLS_ST_SR_CERT, + TLS_ST_SR_KEY_EXCH, + TLS_ST_SR_CERT_VRFY, + TLS_ST_SR_NEXT_PROTO, + TLS_ST_SR_CHANGE, + TLS_ST_SR_FINISHED, + TLS_ST_SW_SESSION_TICKET, + TLS_ST_SW_CERT_STATUS, + TLS_ST_SW_CHANGE, + TLS_ST_SW_FINISHED +}; + /* * The following are the possible values for ssl->state are are used to * indicate where we are up to in the SSL connection establishment. The @@ -953,11 +1006,11 @@ extern "C" { /* Is the SSL_connection established? */ # define SSL_get_state(a) SSL_state(a) -# define SSL_is_init_finished(a) (SSL_state(a) == SSL_ST_OK) -# define SSL_in_init(a) (SSL_state(a)&SSL_ST_INIT) -# define SSL_in_before(a) (SSL_state(a)&SSL_ST_BEFORE) -# define SSL_in_connect_init(a) (SSL_state(a)&SSL_ST_CONNECT) -# define SSL_in_accept_init(a) (SSL_state(a)&SSL_ST_ACCEPT) +# define SSL_in_connect_init(a) (SSL_in_init(a) && !a->server) +# define SSL_in_accept_init(a) (SSL_in_init(a) && a->server) +int SSL_in_init(SSL *s); +int SSL_in_before(SSL *s); +int SSL_is_init_finished(SSL *s); /* * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you @@ -1646,8 +1699,8 @@ void SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val)); void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type, int val); -__owur int SSL_state(const SSL *ssl); -void SSL_set_state(SSL *ssl, int state); +__owur enum HANDSHAKE_STATE SSL_state(const SSL *ssl); +void SSL_set_state(SSL *ssl, enum HANDSHAKE_STATE state); void SSL_set_verify_result(SSL *ssl, long v); __owur long SSL_get_verify_result(const SSL *ssl); diff --git a/ssl/d1_both.c b/ssl/d1_both.c index a9690380c8..e20278b1ce 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -160,8 +160,6 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned short seq_num, unsigned long frag_off, unsigned long frag_len); -static long dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, - int *ok); static int dtls_get_reassembled_message(SSL *s, long *len); static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len, @@ -438,117 +436,6 @@ int dtls1_do_write(SSL *s, int type) return (0); } -/* - * Obtain handshake message of message type 'mt' (any if mt == -1), maximum - * acceptable body length 'max'. Read an entire handshake message. Handshake - * messages arrive in fragments. - */ -long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) -{ - int i, al; - struct hm_header_st *msg_hdr; - unsigned char *p; - unsigned long msg_len; - - /* - * s3->tmp is used to store messages that are unexpected, caused by the - * absence of an optional handshake message - */ - if (s->s3->tmp.reuse_message) { - if ((mt >= 0) && (s->s3->tmp.message_type != mt)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - *ok = 1; - - - /* - * Messages reused from dtls1_listen also have the record header in - * the buffer which we need to skip over. - */ - if (s->s3->tmp.reuse_message == DTLS1_SKIP_RECORD_HEADER) { - s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH - + DTLS1_RT_HEADER_LENGTH; - } else { - s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; - } - s->init_num = (int)s->s3->tmp.message_size; - s->s3->tmp.reuse_message = 0; - return s->init_num; - } - - msg_hdr = &s->d1->r_msg_hdr; - memset(msg_hdr, 0, sizeof(*msg_hdr)); - - again: - i = dtls1_get_message_fragment(s, st1, stn, mt, ok); - if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) { - /* bad fragment received */ - goto again; - } else if (i <= 0 && !*ok) { - return i; - } - - if (mt >= 0 && s->s3->tmp.message_type != mt) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - - p = (unsigned char *)s->init_buf->data; - - if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { - if (s->msg_callback) { - s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, - p, 1, s, s->msg_callback_arg); - } - /* - * This isn't a real handshake message so skip the processing below. - * dtls1_get_message_fragment() will never return a CCS if mt == -1, - * so we are ok to continue in that case. - */ - return i; - } - - msg_len = msg_hdr->msg_len; - - /* reconstruct message header */ - *(p++) = msg_hdr->type; - l2n3(msg_len, p); - s2n(msg_hdr->seq, p); - l2n3(0, p); - l2n3(msg_len, p); - if (s->version != DTLS1_BAD_VER) { - p -= DTLS1_HM_HEADER_LENGTH; - msg_len += DTLS1_HM_HEADER_LENGTH; - } - - if (msg_len > (unsigned long)max) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - - ssl3_finish_mac(s, p, msg_len); - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, - p, msg_len, s, s->msg_callback_arg); - - memset(msg_hdr, 0, sizeof(*msg_hdr)); - - s->d1->handshake_read_seq++; - - - s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; - return s->init_num; - - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - *ok = 0; - return -1; -} - int dtls_get_message(SSL *s, int *mt, unsigned long *len) { struct hm_header_st *msg_hdr; @@ -925,30 +812,6 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr, return i; } -static long -dtls1_get_message_fragment(SSL *s, int st1, int stn, int mt, int *ok) -{ - long len; - - do { - *ok = dtls_get_reassembled_message(s, &len); - /* A CCS isn't a real handshake message, so if we get one there is no - * message sequence number to give us confidence that this was really - * intended to be at this point in the handshake sequence. Therefore we - * only allow this if we were explicitly looking for it (i.e. if |mt| - * is -1 we still don't allow it). If we get one when we're not - * expecting it then probably something got re-ordered or this is a - * retransmit. We should drop this and try again. - */ - } while (*ok && mt != SSL3_MT_CHANGE_CIPHER_SPEC - && s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC); - - if (*ok) - s->state = stn; - - return len; -} - static int dtls_get_reassembled_message(SSL *s, long *len) { unsigned char wire[DTLS1_HM_HEADER_LENGTH]; @@ -1103,19 +966,6 @@ static int dtls_get_reassembled_message(SSL *s, long *len) return 0; } - -int dtls1_send_change_cipher_spec(SSL *s, int a, int b) -{ - if (s->state == a) { - if (dtls_construct_change_cipher_spec(s) == 0) - return -1; - } - - /* SSL3_ST_CW_CHANGE_B */ - return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); -} - - /*- * for these 2 messages, we need to * ssl->enc_read_ctx re-init diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 02a944d86e..47c6203799 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -144,720 +144,18 @@ IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, ssl_undefined_function, dtls1_get_server_method, DTLSv1_enc_data) - IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, DTLSv1_2_server_method, dtls1_accept, ssl_undefined_function, dtls1_get_server_method, DTLSv1_2_enc_data) - IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, DTLS_server_method, dtls1_accept, ssl_undefined_function, dtls1_get_server_method, DTLSv1_2_enc_data) -#if 0 -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 (!s->d1->cookie_verified - && (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 (s->no_cert_verify) { - /* - * 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); -} -#endif unsigned int dtls1_raw_hello_verify_request(unsigned char *buf, unsigned char *cookie, diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c index d91de4d4a0..64e1f7441d 100644 --- a/ssl/record/rec_layer_d1.c +++ b/ssl/record/rec_layer_d1.c @@ -283,8 +283,8 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) #ifndef OPENSSL_NO_SCTP /* Store bio_dgram_sctp_rcvinfo struct */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - (s->state == SSL3_ST_SR_FINISHED_A - || s->state == SSL3_ST_CR_FINISHED_A)) { + (SSL_state(s) == TLS_ST_SR_FINISHED + || SSL_state(s) == TLS_ST_CR_FINISHED)) { BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo); } @@ -472,7 +472,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, * We are not handshaking and have no data yet, so process data buffered * during the last handshake in advance, if any. */ - if (s->state == SSL_ST_OK && SSL3_RECORD_get_length(rr) == 0) { + 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) { @@ -901,9 +901,9 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, goto start; } - if (((s->state & SSL_ST_MASK) == SSL_ST_OK) && + if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; + statem_set_in_init(s, 1); s->renegotiate = 1; s->new_session = 1; } @@ -966,14 +966,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, */ if (s->s3->in_read_app_data && (s->s3->total_renegotiations != 0) && - (((s->state & SSL_ST_CONNECT) && - (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && - (s->state <= SSL3_ST_CR_SRVR_HELLO_A) - ) || ((s->state & SSL_ST_ACCEPT) && - (s->state <= SSL3_ST_SW_HELLO_REQ_A) && - (s->state >= SSL3_ST_SR_CLNT_HELLO_A) - ) - )) { + statem_app_data_allowed(s)) { s->s3->in_read_app_data = 2; return (-1); } else { diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 78e355a5d9..c224fe5e04 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -779,7 +779,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, * Some servers hang if iniatial client hello is larger than 256 bytes * and record version number > TLS 1.0 */ - if (s->state == SSL3_ST_CW_CLNT_HELLO_B + if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO && !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION) *(p++) = 0x1; else @@ -1384,9 +1384,9 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, * Unexpected handshake message (Client Hello, or protocol violation) */ if ((s->rlayer.handshake_fragment_len >= 4) && !s->in_handshake) { - if (((s->state & SSL_ST_MASK) == SSL_ST_OK) && + if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; + statem_set_in_init(s, 1); s->renegotiate = 1; s->new_session = 1; } diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 2afde72a63..db0197d60b 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -156,20 +156,6 @@ int ssl3_do_write(SSL *s, int type) return (0); } -int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) -{ - if (s->state == a) { - if (tls_construct_finished(s, sender, slen) == 0) { - statem_set_error(s); - return -1; - } - s->state = b; - } - - /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return ssl_do_write(s); -} - int tls_construct_finished(SSL *s, const char *sender, int slen) { unsigned char *p; @@ -223,7 +209,7 @@ static void ssl3_take_mac(SSL *s) */ if (s->s3->tmp.new_cipher == NULL) return; - if (s->state & SSL_ST_CONNECT) { + if (!s->server) { sender = s->method->ssl3_enc->server_finished_label; slen = s->method->ssl3_enc->server_finished_label_len; } else { @@ -238,24 +224,6 @@ static void ssl3_take_mac(SSL *s) } #endif -int ssl3_get_change_cipher_spec(SSL *s, int a, int b) -{ - int ok; - long n; - - n = s->method->ssl_get_message(s, a, b, SSL3_MT_CHANGE_CIPHER_SPEC, 1, &ok); - - if (!ok) - return ((int)n); - - if (tls_process_change_cipher_spec(s, n) == 0) { - statem_set_error(s); - return -1; - } - - return 1; -} - enum MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, long n) { int al; @@ -320,28 +288,6 @@ enum MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, long n) return MSG_PROCESS_ERROR; } - -int ssl3_get_finished(SSL *s, int a, int b) -{ - int ok; - long n; - -#ifdef OPENSSL_NO_NEXTPROTONEG - /* - * the mac has already been generated when we received the change cipher - * spec message and is in s->s3->tmp.peer_finish_md - */ -#endif - - /* 64 argument should actually be 36+4 :-) */ - n = s->method->ssl_get_message(s, a, b, SSL3_MT_FINISHED, 64, &ok); - - if (!ok) - return ((int)n); - - return tls_process_finished(s, (unsigned long)n); -} - enum MSG_PROCESS_RETURN tls_process_finished(SSL *s, unsigned long n) { int al, i; @@ -390,30 +336,6 @@ enum MSG_PROCESS_RETURN tls_process_finished(SSL *s, unsigned long n) return MSG_PROCESS_ERROR; } -/*- - * for these 2 messages, we need to - * ssl->enc_read_ctx re-init - * ssl->rlayer.read_sequence zero - * ssl->s3->read_mac_secret re-init - * ssl->session->read_sym_enc assign - * ssl->session->read_compression assign - * ssl->session->read_hash assign - */ -int ssl3_send_change_cipher_spec(SSL *s, int a, int b) -{ - if (s->state == a) { - if(tls_construct_change_cipher_spec(s) == 0) { - statem_set_error(s); - return 0; - } - - s->state = b; - } - - /* SSL3_ST_CW_CHANGE_B */ - return (ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); -} - int tls_construct_change_cipher_spec(SSL *s) { unsigned char *p; @@ -516,87 +438,6 @@ enum WORK_STATE tls_finish_handshake(SSL *s, enum WORK_STATE wst) return WORK_FINISHED_STOP; } - -/* - * Obtain handshake message of message type 'mt' (any if mt == -1), maximum - * acceptable body length 'max'. The first four bytes (msg_type and length) - * are read in state 'st1', the body is read in state 'stn'. - */ -long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) -{ - unsigned char *p; - long n; - int al, mtin; - - if (s->s3->tmp.reuse_message) { - s->s3->tmp.reuse_message = 0; - if ((mt >= 0) && (s->s3->tmp.message_type != mt)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - *ok = 1; - s->state = stn; - s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; - s->init_num = (int)s->s3->tmp.message_size; - return s->init_num; - } - - p = (unsigned char *)s->init_buf->data; - - if (s->state == st1) { - if (tls_get_message_header(s, &mtin) == 0) { - /* Could be NBIO */ - *ok = 0; - return -1; - } - s->state = stn; - if (s->init_num == 0 - && mtin == SSL3_MT_CHANGE_CIPHER_SPEC - && (mt < 0 || mt == SSL3_MT_CHANGE_CIPHER_SPEC)) { - if (*p != SSL3_MT_CCS) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, - SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - s->init_msg = p + 1; - s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; - s->s3->tmp.message_size = s->init_num; - *ok = 1; - if (s->msg_callback) - s->msg_callback(0, s->version, - SSL3_RT_CHANGE_CIPHER_SPEC, p, 1, s, - s->msg_callback_arg); - return s->init_num; - } - if (s->s3->tmp.message_size > (unsigned long)max) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if ((mt >= 0) && (mtin != mt)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); - goto f_err; - } - } - - /* next state (stn) */ - if (tls_get_message_body(s, (unsigned long *)&n) == 0) { - *ok = 0; - return n; - } - - *ok = 1; - return n; - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - statem_set_error(s); - *ok = 0; - return 0; -} - int tls_get_message_header(SSL *s, int *mt) { /* s->init_num < SSL3_HM_HEADER_LENGTH */ diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 292fb1b3cc..2111d18aee 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -5014,7 +5014,7 @@ int ssl3_shutdown(SSL *s) * Don't do anything much if we have not done the handshake or we don't * want to send messages :-) */ - if ((s->quiet_shutdown) || (s->state == SSL_ST_BEFORE)) { + if ((s->quiet_shutdown) || (SSL_in_before(s))) { s->shutdown = (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); return (1); } @@ -5128,10 +5128,9 @@ int ssl3_renegotiate_check(SSL *s) && !SSL_in_init(s)) { /* * if we are the server, and we have sent a 'RENEGOTIATE' - * message, we need to go to SSL_ST_ACCEPT. + * message, we need to set the state machine into the renegotiate + * state. */ - /* SSL_ST_ACCEPT */ - s->state = SSL_ST_RENEGOTIATE; statem_set_renegotiate(s); s->s3->renegotiate = 0; s->s3->num_renegotiations++; diff --git a/ssl/s3_msg.c b/ssl/s3_msg.c index fcf4744190..8d7f042f83 100644 --- a/ssl/s3_msg.c +++ b/ssl/s3_msg.c @@ -118,7 +118,7 @@ int ssl3_do_change_cipher_spec(SSL *s) const char *sender; int slen; - if (s->state & SSL_ST_ACCEPT) + if (s->server) i = SSL3_CHANGE_CIPHER_SERVER_READ; else i = SSL3_CHANGE_CIPHER_CLIENT_READ; @@ -143,7 +143,7 @@ int ssl3_do_change_cipher_spec(SSL *s) * we have to record the message digest at this point so we can get it * before we read the finished message */ - if (s->state & SSL_ST_CONNECT) { + if (!s->server) { sender = s->method->ssl3_enc->server_finished_label; slen = s->method->ssl3_enc->server_finished_label_len; } else { diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index d390f149a2..85601b09f6 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -193,641 +193,6 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) } #endif -#if 0 -int ssl3_accept(SSL *s) -{ - BUF_MEM *buf; - unsigned long alg_k, Time = (unsigned long)time(NULL); - void (*cb) (const SSL *ssl, int type, int val) = NULL; - int ret = -1; - int new_state, state, skip = 0; - - 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_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) { - 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 >> 8 != 3) && s->version != TLS_ANY_VERSION) { - SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); - s->state = SSL_ST_ERR; - return -1; - } - - if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { - SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_VERSION_TOO_LOW); - 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; - s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY; - /* - * 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 :-) - */ - 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 if (!s->s3->send_connection_binding && - !(s->options & - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { - /* - * Server attempting to renegotiate with client that doesn't - * support secure renegotiation. - */ - SSLerr(SSL_F_SSL3_ACCEPT, - SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } 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; - ret = ssl3_send_hello_request(s); - if (ret <= 0) - goto end; - s->s3->tmp.next_state = SSL3_ST_SW_HELLO_REQ_C; - 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: - - ret = ssl3_get_client_hello(s); - if (ret <= 0) - goto end; - - s->state = SSL3_ST_SW_SRVR_HELLO_A; - s->init_num = 0; - break; - -#ifndef OPENSSL_NO_SRP - case SSL3_ST_SR_CLNT_HELLO_D: - { - enum WORK_STATE wst_ret; - - wst_ret = tls_post_process_client_hello(s, WORK_MORE_B); - if (wst_ret == WORK_MORE_B) - goto end; - if (wst_ret == WORK_ERROR) { - ret = -1; - goto end; - } - } - - s->state = SSL3_ST_SW_SRVR_HELLO_A; - s->init_num = 0; - break; -#endif - - case SSL3_ST_SW_SRVR_HELLO_A: - case SSL3_ST_SW_SRVR_HELLO_B: - ret = ssl3_send_server_hello(s); - if (ret <= 0) - goto end; - - if (s->hit) { - if (s->tlsext_ticket_expected) - s->state = SSL3_ST_SW_SESSION_TICKET_A; - else - s->state = SSL3_ST_SW_CHANGE_A; - } else { - s->state = SSL3_ST_SW_CERT_A; - } - s->init_num = 0; - break; - - case SSL3_ST_SW_CERT_A: - case SSL3_ST_SW_CERT_B: - /* Check if it is anon DH or anon ECDH, */ - /* normal PSK or SRP */ - if (!(s->s3->tmp.new_cipher->algorithm_auth & - (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { - 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, fortezza or RSA but we have a - * sign only certificate PSK: may send PSK identity hints For - * ECC ciphersuites, we send a serverKeyExchange message only if - * the cipher suite is either ECDH-anon or ECDHE. In other cases, - * the server certificate contains the server's public key for - * key exchange. - */ - if (0 - /* - * PSK: send ServerKeyExchange if PSK identity hint if - * provided - */ -#ifndef OPENSSL_NO_PSK - /* Only send SKE if we have identity hint for plain PSK */ - || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->cert->psk_identity_hint) - /* For other PSK always send SKE */ - || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) -#endif -#ifndef OPENSSL_NO_SRP - /* SRP: send ServerKeyExchange */ - || (alg_k & SSL_kSRP) -#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) - ) - ) - ) - ) { - 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)) || - /* don't request certificate for SRP auth */ - (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) - /* - * With normal PSK Certificates and Certificate Requests - * are omitted - */ - || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) { - /* no cert request */ - skip = 1; - s->s3->tmp.cert_request = 0; - s->state = SSL3_ST_SW_SRVR_DONE_A; - if (!ssl3_digest_cached_records(s, 0)) { - s->state = SSL_ST_ERR; - return -1; - } - } else { - s->s3->tmp.cert_request = 1; - ret = ssl3_send_certificate_request(s); - if (ret <= 0) - goto end; - s->state = SSL3_ST_SW_SRVR_DONE_A; - s->init_num = 0; - } - break; - - case SSL3_ST_SW_SRVR_DONE_A: - case SSL3_ST_SW_SRVR_DONE_B: - 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: - - /* - * This code originally checked to see if any data was pending - * using BIO_CTRL_INFO and then flushed. This caused problems as - * documented in PR#1939. The proposed fix doesn't completely - * resolve this issue as buggy implementations of - * BIO_CTRL_PENDING still exist. So instead we just flush - * unconditionally. - */ - - s->rwstate = SSL_WRITING; - if (BIO_flush(s->wbio) <= 0) { - ret = -1; - goto end; - } - s->rwstate = SSL_NOTHING; - - s->state = s->s3->tmp.next_state; - break; - - case SSL3_ST_SR_CERT_A: - case SSL3_ST_SR_CERT_B: - if (s->s3->tmp.cert_request) { - ret = ssl3_get_client_certificate(s); - if (ret <= 0) - goto end; - } - s->init_num = 0; - s->state = SSL3_ST_SR_KEY_EXCH_A; - break; - - case SSL3_ST_SR_KEY_EXCH_A: - case SSL3_ST_SR_KEY_EXCH_B: - ret = ssl3_get_client_key_exchange(s); - if (ret <= 0) - goto end; - if (s->no_cert_verify) { - /* - * For the ECDH ciphersuites when the client sends its ECDH - * pub key in a certificate, the CertificateVerify message is - * not sent. Also for GOST ciphersuites when the client uses - * its key from the certificate for key exchange. - */ - 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_SSL3_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 so this is a no-op - */ - if (!ssl3_digest_cached_records(s, 1)) { - s->state = SSL_ST_ERR; - return -1; - } - } else { - int offset = 0; - int dgst_num; - - 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 FIXME - digest processing for - * CertificateVerify should be generalized. But it is next - * step - */ - if (!ssl3_digest_cached_records(s, 0)) { - s->state = SSL_ST_ERR; - return -1; - } - for (dgst_num = 0; dgst_num < SSL_MAX_DIGEST; dgst_num++) - if (s->s3->handshake_dgst[dgst_num]) { - int dgst_size; - - s->method->ssl3_enc->cert_verify_mac(s, - EVP_MD_CTX_type - (s-> - s3->handshake_dgst - [dgst_num]), - &(s->s3-> - tmp.cert_verify_md - [offset])); - dgst_size = - EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]); - if (dgst_size < 0) { - s->state = SSL_ST_ERR; - ret = -1; - goto end; - } - offset += dgst_size; - } - } - break; - - case SSL3_ST_SR_CERT_VRFY_A: - case SSL3_ST_SR_CERT_VRFY_B: - ret = ssl3_get_cert_verify(s); - if (ret <= 0) - goto end; - - s->state = SSL3_ST_SR_CHANGE_A; - s->init_num = 0; - break; - -#if !defined(OPENSSL_NO_NEXTPROTONEG) - case SSL3_ST_SR_NEXT_PROTO_A: - case SSL3_ST_SR_NEXT_PROTO_B: - ret = ssl3_get_next_proto(s); - if (ret <= 0) - goto end; - s->init_num = 0; - s->state = SSL3_ST_SR_FINISHED_A; - break; -#endif - - - 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; - -#if defined(OPENSSL_NO_NEXTPROTONEG) - s->state = SSL3_ST_SR_FINISHED_A; -#else - if (s->s3->next_proto_neg_seen) - s->state = SSL3_ST_SR_NEXT_PROTO_A; - else - s->state = SSL3_ST_SR_FINISHED_A; -#endif - 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; - 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 = ssl3_send_change_cipher_spec(s, - SSL3_ST_SW_CHANGE_A, - SSL3_ST_SW_CHANGE_B); - - if (ret <= 0) - goto end; - s->state = SSL3_ST_SW_FINISHED_A; - s->init_num = 0; - - if (!s->method->ssl3_enc->change_cipher_state(s, - SSL3_CHANGE_CIPHER_SERVER_WRITE)) - { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - break; - - case SSL3_ST_SW_FINISHED_A: - case SSL3_ST_SW_FINISHED_B: - ret = ssl3_send_finished(s, - SSL3_ST_SW_FINISHED_A, - SSL3_ST_SW_FINISHED_B, - s->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; - } else - s->s3->tmp.next_state = SSL_ST_OK; - s->init_num = 0; - break; - - case SSL_ST_OK: - /* clean a few things up */ - ssl3_cleanup_key_block(s); - - BUF_MEM_free(s->init_buf); - s->init_buf = NULL; - - /* 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 = ssl3_accept; - - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_DONE, 1); - } - - ret = 1; - goto end; - /* break; */ - - case SSL_ST_ERR: - default: - SSLerr(SSL_F_SSL3_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--; - if (cb != NULL) - cb(s, SSL_CB_ACCEPT_EXIT, ret); - return (ret); -} -#endif - -int ssl3_send_hello_request(SSL *s) -{ - - if (s->state == SSL3_ST_SW_HELLO_REQ_A) { - if (tls_construct_hello_request(s) == 0) { - return -1; - } - s->state = SSL3_ST_SW_HELLO_REQ_B; - } - - /* SSL3_ST_SW_HELLO_REQ_B */ - return ssl_do_write(s); -} - int tls_construct_hello_request(SSL *s) { if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) { @@ -839,49 +204,6 @@ int tls_construct_hello_request(SSL *s) return 1; } -int ssl3_get_client_hello(SSL *s) -{ - int ok; - long n; - enum WORK_STATE wst_ret; - - if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) - goto retry_cert; - - /* - * We do this so that we will respond with our native type. If we are - * TLSv1 and we get SSLv3, we will respond with TLSv1, This down - * switching should be handled by a different method. If we are SSLv3, we - * will respond with SSLv3, even if prompted with TLSv1. - */ - if (s->state == SSL3_ST_SR_CLNT_HELLO_A) { - s->state = SSL3_ST_SR_CLNT_HELLO_B; - } - s->first_packet = 1; - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CLNT_HELLO_B, - SSL3_ST_SR_CLNT_HELLO_C, - SSL3_MT_CLIENT_HELLO, - SSL3_RT_MAX_PLAIN_LENGTH, &ok); - - if (!ok) - return ((int)n); - s->first_packet = 0; - - if (tls_process_client_hello(s, n) == 0) - return -1; - - retry_cert: - wst_ret = tls_post_process_client_hello(s, WORK_MORE_A); - if (wst_ret == WORK_MORE_A || wst_ret == WORK_ERROR) - return -1; - if (wst_ret == WORK_MORE_B) { - s->state = SSL3_ST_SR_CLNT_HELLO_D; - return -1; - } - return n; -} - enum MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, long n) { int i, al = SSL_AD_INTERNAL_ERROR; @@ -1526,18 +848,6 @@ enum WORK_STATE tls_post_process_client_hello(SSL *s, enum WORK_STATE wst) return WORK_ERROR; } -int ssl3_send_server_hello(SSL *s) -{ - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { - if (tls_construct_server_hello(s) != 1) - return -1; - s->state = SSL3_ST_SW_SRVR_HELLO_B; - } - - /* SSL3_ST_SW_SRVR_HELLO_B */ - return ssl_do_write(s); -} - int tls_construct_server_hello(SSL *s) { unsigned char *buf; @@ -1631,19 +941,6 @@ int tls_construct_server_hello(SSL *s) return 1; } -int ssl3_send_server_done(SSL *s) -{ - - if (s->state == SSL3_ST_SW_SRVR_DONE_A) { - if (tls_construct_server_done(s) == 0) - return -1; - s->state = SSL3_ST_SW_SRVR_DONE_B; - } - - /* SSL3_ST_SW_SRVR_DONE_B */ - return ssl_do_write(s); -} - int tls_construct_server_done(SSL *s) { if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) { @@ -1661,17 +958,6 @@ int tls_construct_server_done(SSL *s) return 1; } -int ssl3_send_server_key_exchange(SSL *s) -{ - if (s->state == SSL3_ST_SW_KEY_EXCH_A) { - if (tls_construct_server_key_exchange(s) == 0) - return -1; - } - - s->state = SSL3_ST_SW_KEY_EXCH_B; - return ssl_do_write(s); -} - int tls_construct_server_key_exchange(SSL *s) { #ifndef OPENSSL_NO_RSA @@ -2139,18 +1425,6 @@ int tls_construct_server_key_exchange(SSL *s) return 0; } -int ssl3_send_certificate_request(SSL *s) -{ - if (s->state == SSL3_ST_SW_CERT_REQ_A) { - if (tls_construct_certificate_request(s) == 0) - return -1; - s->state = SSL3_ST_SW_CERT_REQ_B; - } - - /* SSL3_ST_SW_CERT_REQ_B */ - return ssl_do_write(s); -} - int tls_construct_certificate_request(SSL *s) { unsigned char *p, *d; @@ -2223,25 +1497,6 @@ int tls_construct_certificate_request(SSL *s) return 0; } -int ssl3_get_client_key_exchange(SSL *s) -{ - int ok; - long n; - - n = s->method->ssl_get_message(s, - SSL3_ST_SR_KEY_EXCH_A, - SSL3_ST_SR_KEY_EXCH_B, - SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, &ok); - - if (!ok) - return ((int)n); - - if (tls_process_client_key_exchange(s, n) == 0) - return -1; - - return n; -} - enum MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, long n) { int al; @@ -2984,42 +2239,6 @@ enum WORK_STATE tls_post_process_client_key_exchange(SSL *s, return WORK_FINISHED_CONTINUE; } -int ssl3_get_cert_verify(SSL *s) -{ - int ok, ret = 1; - long n; - - /* - * We should only process a CertificateVerify message if we have received - * a Certificate from the client. If so then |s->session->peer| will be non - * NULL. In some instances a CertificateVerify message is not required even - * if the peer has sent a Certificate (e.g. such as in the case of static - * DH). In that case the ClientKeyExchange processing will skip the - * CertificateVerify state so we should not arrive here. - */ - if (s->session->peer == NULL) { - goto end; - } - - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_VRFY_A, - SSL3_ST_SR_CERT_VRFY_B, - SSL3_MT_CERTIFICATE_VERIFY, - SSL3_RT_MAX_PLAIN_LENGTH, &ok); - - if (!ok) - return ((int)n); - - if (tls_process_cert_verify(s, n) == 0) - ret = -1; - - end: - BIO_free(s->s3->handshake_buffer); - s->s3->handshake_buffer = NULL; - return ret; -} - - enum MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, long n) { EVP_PKEY *pkey = NULL; @@ -3202,56 +2421,6 @@ enum MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, long n) return ret; } -int ssl3_get_client_certificate(SSL *s) -{ - int ok, al; - long n; - - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_A, - SSL3_ST_SR_CERT_B, - -1, s->max_cert_list, &ok); - - if (!ok) - return ((int)n); - - if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { - if ((s->verify_mode & SSL_VERIFY_PEER) && - (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, - SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); - al = SSL_AD_HANDSHAKE_FAILURE; - goto f_err; - } - /* - * If tls asked for a client cert, the client must return a 0 list - */ - if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) { - SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, - SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); - al = SSL_AD_UNEXPECTED_MESSAGE; - goto f_err; - } - s->s3->tmp.reuse_message = 1; - return 1; - } - - if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, SSL_R_WRONG_MESSAGE_TYPE); - goto f_err; - } - - if (tls_process_client_certificate(s, n) == 0) - goto f_err; - - return 1; - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - s->state = SSL_ST_ERR; - return -1; -} - enum MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, long n) { int i, al, ret = MSG_PROCESS_ERROR; @@ -3377,18 +2546,6 @@ enum MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, long n) return ret; } -int ssl3_send_server_certificate(SSL *s) -{ - if (s->state == SSL3_ST_SW_CERT_A) { - if (tls_construct_server_certificate(s) == 0) - return 0; - s->state = SSL3_ST_SW_CERT_B; - } - - /* SSL3_ST_SW_CERT_B */ - return ssl_do_write(s); -} - int tls_construct_server_certificate(SSL *s) { CERT_PKEY *cpk; @@ -3409,20 +2566,6 @@ int tls_construct_server_certificate(SSL *s) return 1; } -/* send a new session ticket (not necessarily for a new session) */ -int ssl3_send_newsession_ticket(SSL *s) -{ - if (s->state == SSL3_ST_SW_SESSION_TICKET_A) { - if (tls_construct_new_session_ticket(s) == 0) - return -1; - - s->state = SSL3_ST_SW_SESSION_TICKET_B; - } - - /* SSL3_ST_SW_SESSION_TICKET_B */ - return ssl_do_write(s); -} - int tls_construct_new_session_ticket(SSL *s) { unsigned char *senc = NULL; @@ -3567,19 +2710,6 @@ int tls_construct_new_session_ticket(SSL *s) return 0; } -int ssl3_send_cert_status(SSL *s) -{ - if (s->state == SSL3_ST_SW_CERT_STATUS_A) { - if (tls_construct_cert_status(s) == 0) - return -1; - - s->state = SSL3_ST_SW_CERT_STATUS_B; - } - - /* SSL3_ST_SW_CERT_STATUS_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); -} - int tls_construct_cert_status(SSL *s) { unsigned char *p; @@ -3614,52 +2744,6 @@ int tls_construct_cert_status(SSL *s) } #ifndef OPENSSL_NO_NEXTPROTONEG -/* - * ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. - * It sets the next_proto member in s if found - */ -int ssl3_get_next_proto(SSL *s) -{ - int ok; - long n; - - /* - * Clients cannot send a NextProtocol message if we didn't see the - * extension in their ClientHello - */ - if (!s->s3->next_proto_neg_seen) { - SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, - SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); - s->state = SSL_ST_ERR; - return -1; - } - - /* See the payload format below */ - n = s->method->ssl_get_message(s, - SSL3_ST_SR_NEXT_PROTO_A, - SSL3_ST_SR_NEXT_PROTO_B, - SSL3_MT_NEXT_PROTO, 514, &ok); - - if (!ok) - return ((int)n); - - /* - * s->state doesn't reflect whether ChangeCipherSpec has been received in - * this handshake, but s->s3->change_cipher_spec does (will be reset by - * ssl3_get_finished). - */ - if (!s->s3->change_cipher_spec) { - SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); - statem_set_error(s); - return -1; - } - - if (tls_process_next_proto(s, n) == 0) - return -1; - - return n; -} - /* * tls_process_next_proto reads a Next Protocol Negotiation handshake message. * It sets the next_proto member in s if found diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 9ef3bf780e..0aef51f361 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -217,7 +217,6 @@ int SSL_clear(SSL *s) s->type = 0; - s->state = SSL_ST_BEFORE | ((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT); statem_clear(s); s->version = s->method->version; @@ -2399,7 +2398,7 @@ void SSL_set_accept_state(SSL *s) { s->server = 1; s->shutdown = 0; - s->state = SSL_ST_ACCEPT | SSL_ST_BEFORE; + statem_clear(s); s->handshake_func = s->method->ssl_accept; clear_ciphers(s); } @@ -2408,7 +2407,7 @@ void SSL_set_connect_state(SSL *s) { s->server = 0; s->shutdown = 0; - s->state = SSL_ST_CONNECT | SSL_ST_BEFORE; + statem_clear(s); s->handshake_func = s->method->ssl_connect; clear_ciphers(s); } @@ -2538,8 +2537,8 @@ SSL *SSL_dup(SSL *s) ret->new_session = s->new_session; ret->quiet_shutdown = s->quiet_shutdown; ret->shutdown = s->shutdown; - ret->state = s->state; /* SSL_dup does not really work at any state, - * though */ + ret->statem = s->statem; /* SSL_dup does not really work at any state, + * though */ RECORD_LAYER_dup(&ret->rlayer, &s->rlayer); ret->init_num = 0; /* would have to copy ret->init_buf, * ret->init_msg, ret->init_num, @@ -2841,16 +2840,6 @@ void (*SSL_get_info_callback(const SSL *ssl)) (const SSL * /* ssl */ , return ssl->info_callback; } -int SSL_state(const SSL *ssl) -{ - return (ssl->state); -} - -void SSL_set_state(SSL *ssl, int state) -{ - ssl->state = state; -} - void SSL_set_verify_result(SSL *ssl, long arg) { ssl->verify_result = arg; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 891030c7c3..aebd3af8dd 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -717,58 +717,6 @@ struct ssl_comp_st { DECLARE_STACK_OF(SSL_COMP) DECLARE_LHASH_OF(SSL_SESSION); -/* - * The valid handshake states (one for each type message sent and one for each - * type of message received). There are also two "special" states: - * TLS = TLS or DTLS state - * DTLS = DTLS specific state - * CR/SR = Client Read/Server Read - * CW/SW = Client Write/Server Write - * - * The "special" states are: - * TLS_ST_BEFORE = No handshake has been initiated yet - * TLS_ST_OK = A handshake has been successfully completed - */ -enum HANDSHAKE_STATE { - TLS_ST_BEFORE, - TLS_ST_OK, - DTLS_ST_CR_HELLO_VERIFY_REQUEST, - TLS_ST_CR_SRVR_HELLO, - TLS_ST_CR_CERT, - TLS_ST_CR_CERT_STATUS, - TLS_ST_CR_KEY_EXCH, - TLS_ST_CR_CERT_REQ, - TLS_ST_CR_SRVR_DONE, - TLS_ST_CR_SESSION_TICKET, - TLS_ST_CR_CHANGE, - TLS_ST_CR_FINISHED, - TLS_ST_CW_CLNT_HELLO, - TLS_ST_CW_CERT, - TLS_ST_CW_KEY_EXCH, - TLS_ST_CW_CERT_VRFY, - TLS_ST_CW_CHANGE, - TLS_ST_CW_NEXT_PROTO, - TLS_ST_CW_FINISHED, - TLS_ST_SW_HELLO_REQ, - TLS_ST_SR_CLNT_HELLO, - DTLS_ST_SW_HELLO_VERIFY_REQUEST, - TLS_ST_SW_SRVR_HELLO, - TLS_ST_SW_CERT, - TLS_ST_SW_KEY_EXCH, - TLS_ST_SW_CERT_REQ, - TLS_ST_SW_SRVR_DONE, - TLS_ST_SR_CERT, - TLS_ST_SR_KEY_EXCH, - TLS_ST_SR_CERT_VRFY, - TLS_ST_SR_NEXT_PROTO, - TLS_ST_SR_CHANGE, - TLS_ST_SR_FINISHED, - TLS_ST_SW_SESSION_TICKET, - TLS_ST_SW_CERT_STATUS, - TLS_ST_SW_CHANGE, - TLS_ST_SW_FINISHED -}; - /* * Valid return codes used for functions performing work prior to or after * sending or receiving a message @@ -842,6 +790,7 @@ struct statem_st { enum READ_STATE read_state; enum WORK_STATE read_state_work; enum HANDSHAKE_STATE hand_state; + int in_init; int read_state_first_init; int use_timer; #ifndef OPENSSL_NO_SCTP @@ -1398,7 +1347,6 @@ typedef struct ssl3_state_st { # endif /* used when SSL_ST_FLUSH_DATA is entered */ int next_state; - int reuse_message; /* used for certificate requests */ int cert_req; int ctype_num; @@ -1885,7 +1833,7 @@ const SSL_METHOD *func_name(void) \ ssl3_shutdown, \ ssl3_renegotiate, \ ssl3_renegotiate_check, \ - ssl3_get_message, \ + NULL /*TODO: Fix this */, \ ssl3_read_bytes, \ ssl3_write_bytes, \ ssl3_dispatch_alert, \ @@ -1922,7 +1870,7 @@ const SSL_METHOD *func_name(void) \ ssl3_shutdown, \ ssl3_renegotiate, \ ssl3_renegotiate_check, \ - ssl3_get_message, \ + NULL /*TODO: Fix this */, \ ssl3_read_bytes, \ ssl3_write_bytes, \ ssl3_dispatch_alert, \ @@ -1960,7 +1908,7 @@ const SSL_METHOD *func_name(void) \ dtls1_shutdown, \ ssl3_renegotiate, \ ssl3_renegotiate_check, \ - dtls1_get_message, \ + NULL /*TODO: fix this */, \ dtls1_read_bytes, \ dtls1_write_app_data_bytes, \ dtls1_dispatch_alert, \ @@ -2054,18 +2002,12 @@ __owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, __owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); __owur int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p); void ssl3_init_finished_mac(SSL *s); -__owur int ssl3_send_server_certificate(SSL *s); __owur int tls_construct_server_certificate(SSL *s); -__owur int ssl3_send_newsession_ticket(SSL *s); __owur int tls_construct_new_session_ticket(SSL *s); -__owur int ssl3_send_cert_status(SSL *s); -__owur int ssl3_get_change_cipher_spec(SSL *s, int a, int b); -__owur int ssl3_get_finished(SSL *s, int state_a, int state_b); __owur int tls_construct_cert_status(SSL *s); __owur enum MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, long n); __owur enum MSG_PROCESS_RETURN tls_process_finished(SSL *s, unsigned long n); __owur int ssl3_setup_key_block(SSL *s); -__owur int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b); __owur int tls_construct_change_cipher_spec(SSL *s); __owur int dtls_construct_change_cipher_spec(SSL *s); __owur int ssl3_change_cipher_state(SSL *s, int which); @@ -2078,7 +2020,6 @@ __owur int ssl3_get_req_cert_type(SSL *s, unsigned char *p); __owur long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); __owur int tls_get_message_header(SSL *s, int *mt); __owur int tls_get_message_body(SSL *s, unsigned long *len); -__owur int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen); __owur int tls_construct_finished(SSL *s, const char *sender, int slen); __owur enum WORK_STATE tls_finish_handshake(SSL *s, enum WORK_STATE wst); __owur enum WORK_STATE dtls_wait_for_dry(SSL *s); @@ -2103,6 +2044,8 @@ __owur int ssl3_connect(SSL *s); void statem_clear(SSL *s); void statem_set_renegotiate(SSL *s); void statem_set_error(SSL *s); +int statem_in_error(const SSL *s); +void statem_set_in_init(SSL *s, int init); __owur int statem_app_data_allowed(SSL *s); #ifndef OPENSSL_NO_SCTP void statem_set_sctp_read_sock(SSL *s, int read_sock); @@ -2136,7 +2079,6 @@ void dtls1_set_message_header(SSL *s, __owur int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len); -__owur int dtls1_send_change_cipher_spec(SSL *s, int a, int b); __owur int dtls1_read_failed(SSL *s, int code); __owur int dtls1_buffer_message(SSL *s, int ccs); __owur int dtls1_retransmit_message(SSL *s, unsigned short seq, @@ -2192,31 +2134,21 @@ __owur enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, unsigned long n); /* some server-only functions */ -__owur int ssl3_get_client_hello(SSL *s); -__owur int ssl3_send_server_hello(SSL *s); __owur enum MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, long n); __owur enum WORK_STATE tls_post_process_client_hello(SSL *s, enum WORK_STATE wst); __owur int tls_construct_server_hello(SSL *s); -__owur int ssl3_send_hello_request(SSL *s); __owur int tls_construct_hello_request(SSL *s); -__owur int ssl3_send_server_key_exchange(SSL *s); __owur int dtls_construct_hello_verify_request(SSL *s); __owur int tls_construct_server_key_exchange(SSL *s); -__owur int ssl3_send_certificate_request(SSL *s); __owur int tls_construct_certificate_request(SSL *s); -__owur int ssl3_send_server_done(SSL *s); __owur int tls_construct_server_done(SSL *s); -__owur int ssl3_get_client_certificate(SSL *s); -__owur int ssl3_get_client_key_exchange(SSL *s); -__owur int ssl3_get_cert_verify(SSL *s); __owur enum MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, long n); __owur enum MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, long n); __owur enum WORK_STATE tls_post_process_client_key_exchange(SSL *s, enum WORK_STATE wst); __owur enum MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, long n); # ifndef OPENSSL_NO_NEXTPROTONEG -__owur int ssl3_get_next_proto(SSL *s); __owur enum MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, long n); # endif @@ -2234,7 +2166,6 @@ void dtls1_clear(SSL *s); long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); __owur int dtls1_shutdown(SSL *s); -__owur long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); __owur int dtls_get_message(SSL *s, int *mt, unsigned long *len); __owur int dtls1_dispatch_alert(SSL *s); diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c index f59553bad0..d64ea1866c 100644 --- a/ssl/ssl_stat.c +++ b/ssl/ssl_stat.c @@ -89,231 +89,107 @@ const char *SSL_state_string_long(const SSL *s) { const char *str; - switch (s->state) { - case SSL_ST_BEFORE: + if (statem_in_error(s)) { + return "error"; + } + + switch (SSL_state(s)) { + case TLS_ST_BEFORE: str = "before SSL initialization"; break; - case SSL_ST_ACCEPT: - str = "before accept initialization"; - break; - case SSL_ST_CONNECT: - str = "before connect initialization"; - break; - case SSL_ST_OK: + case TLS_ST_OK: str = "SSL negotiation finished successfully"; break; - case SSL_ST_RENEGOTIATE: - str = "SSL renegotiate ciphers"; - break; - case SSL_ST_BEFORE | SSL_ST_CONNECT: - str = "before/connect initialization"; - break; - case SSL_ST_OK | SSL_ST_CONNECT: - str = "ok/connect SSL initialization"; - break; - case SSL_ST_BEFORE | SSL_ST_ACCEPT: - str = "before/accept initialization"; - break; - case SSL_ST_OK | SSL_ST_ACCEPT: - str = "ok/accept SSL initialization"; - break; - case SSL_ST_ERR: - str = "error"; - break; -#ifndef OPENSSL_NO_SSL3 /* SSLv3 additions */ - case SSL3_ST_CW_CLNT_HELLO_A: - str = "SSLv3 write client hello A"; - break; - case SSL3_ST_CW_CLNT_HELLO_B: - str = "SSLv3 write client hello B"; - break; - case SSL3_ST_CR_SRVR_HELLO_A: - str = "SSLv3 read server hello A"; - break; - case SSL3_ST_CR_SRVR_HELLO_B: - str = "SSLv3 read server hello B"; - break; - case SSL3_ST_CR_CERT_A: - str = "SSLv3 read server certificate A"; - break; - case SSL3_ST_CR_CERT_B: - str = "SSLv3 read server certificate B"; - break; - case SSL3_ST_CR_KEY_EXCH_A: - str = "SSLv3 read server key exchange A"; - break; - case SSL3_ST_CR_KEY_EXCH_B: - str = "SSLv3 read server key exchange B"; - break; - case SSL3_ST_CR_CERT_REQ_A: - str = "SSLv3 read server certificate request A"; - break; - case SSL3_ST_CR_CERT_REQ_B: - str = "SSLv3 read server certificate request B"; - break; - case SSL3_ST_CR_SESSION_TICKET_A: - str = "SSLv3 read server session ticket A"; + case TLS_ST_CW_CLNT_HELLO: + str = "SSLv3/TLS write client hello"; break; - case SSL3_ST_CR_SESSION_TICKET_B: - str = "SSLv3 read server session ticket B"; + case TLS_ST_CR_SRVR_HELLO: + str = "SSLv3/TLS read server hello"; break; - case SSL3_ST_CR_SRVR_DONE_A: - str = "SSLv3 read server done A"; + case TLS_ST_CR_CERT: + str = "SSLv3/TLS read server certificate"; break; - case SSL3_ST_CR_SRVR_DONE_B: - str = "SSLv3 read server done B"; + case TLS_ST_CR_KEY_EXCH: + str = "SSLv3/TLS read server key exchange"; break; - case SSL3_ST_CW_CERT_A: - str = "SSLv3 write client certificate A"; + case TLS_ST_CR_CERT_REQ: + str = "SSLv3/TLS read server certificate request"; break; - case SSL3_ST_CW_CERT_B: - str = "SSLv3 write client certificate B"; + case TLS_ST_CR_SESSION_TICKET: + str = "SSLv3/TLS read server session ticket"; break; - case SSL3_ST_CW_CERT_C: - str = "SSLv3 write client certificate C"; + case TLS_ST_CR_SRVR_DONE: + str = "SSLv3/TLS read server done"; break; - case SSL3_ST_CW_CERT_D: - str = "SSLv3 write client certificate D"; + case TLS_ST_CW_CERT: + str = "SSLv3/TLS write client certificate"; break; - case SSL3_ST_CW_KEY_EXCH_A: - str = "SSLv3 write client key exchange A"; + case TLS_ST_CW_KEY_EXCH: + str = "SSLv3/TLS write client key exchange"; break; - case SSL3_ST_CW_KEY_EXCH_B: - str = "SSLv3 write client key exchange B"; - break; - case SSL3_ST_CW_CERT_VRFY_A: - str = "SSLv3 write certificate verify A"; - break; - case SSL3_ST_CW_CERT_VRFY_B: - str = "SSLv3 write certificate verify B"; + case TLS_ST_CW_CERT_VRFY: + str = "SSLv3/TLS write certificate verify"; break; - case SSL3_ST_CW_CHANGE_A: - case SSL3_ST_SW_CHANGE_A: - str = "SSLv3 write change cipher spec A"; - break; - case SSL3_ST_CW_CHANGE_B: - case SSL3_ST_SW_CHANGE_B: - str = "SSLv3 write change cipher spec B"; - break; - case SSL3_ST_CW_FINISHED_A: - case SSL3_ST_SW_FINISHED_A: - str = "SSLv3 write finished A"; - break; - case SSL3_ST_CW_FINISHED_B: - case SSL3_ST_SW_FINISHED_B: - str = "SSLv3 write finished B"; + case TLS_ST_CW_CHANGE: + case TLS_ST_SW_CHANGE: + str = "SSLv3/TLS write change cipher spec"; break; - case SSL3_ST_CR_CHANGE_A: - case SSL3_ST_SR_CHANGE_A: - str = "SSLv3 read change cipher spec A"; + case TLS_ST_CW_FINISHED: + case TLS_ST_SW_FINISHED: + str = "SSLv3/TLS write finished"; break; - case SSL3_ST_CR_CHANGE_B: - case SSL3_ST_SR_CHANGE_B: - str = "SSLv3 read change cipher spec B"; + case TLS_ST_CR_CHANGE: + case TLS_ST_SR_CHANGE: + str = "SSLv3/TLS read change cipher spec"; break; - case SSL3_ST_CR_FINISHED_A: - case SSL3_ST_SR_FINISHED_A: - str = "SSLv3 read finished A"; - break; - case SSL3_ST_CR_FINISHED_B: - case SSL3_ST_SR_FINISHED_B: - str = "SSLv3 read finished B"; - break; - - case SSL3_ST_CW_FLUSH: - case SSL3_ST_SW_FLUSH: - str = "SSLv3 flush data"; + case TLS_ST_CR_FINISHED: + case TLS_ST_SR_FINISHED: + str = "SSLv3/TLS read finished"; break; - case SSL3_ST_SR_CLNT_HELLO_A: - str = "SSLv3 read client hello A"; - break; - case SSL3_ST_SR_CLNT_HELLO_B: - str = "SSLv3 read client hello B"; - break; - case SSL3_ST_SR_CLNT_HELLO_C: - str = "SSLv3 read client hello C"; - break; - case SSL3_ST_SW_HELLO_REQ_A: - str = "SSLv3 write hello request A"; - break; - case SSL3_ST_SW_HELLO_REQ_B: - str = "SSLv3 write hello request B"; - break; - case SSL3_ST_SW_HELLO_REQ_C: - str = "SSLv3 write hello request C"; - break; - case SSL3_ST_SW_SRVR_HELLO_A: - str = "SSLv3 write server hello A"; - break; - case SSL3_ST_SW_SRVR_HELLO_B: - str = "SSLv3 write server hello B"; - break; - case SSL3_ST_SW_CERT_A: - str = "SSLv3 write certificate A"; - break; - case SSL3_ST_SW_CERT_B: - str = "SSLv3 write certificate B"; - break; - case SSL3_ST_SW_KEY_EXCH_A: - str = "SSLv3 write key exchange A"; - break; - case SSL3_ST_SW_KEY_EXCH_B: - str = "SSLv3 write key exchange B"; - break; - case SSL3_ST_SW_CERT_REQ_A: - str = "SSLv3 write certificate request A"; + case TLS_ST_SR_CLNT_HELLO: + str = "SSLv3/TLS read client hello"; break; - case SSL3_ST_SW_CERT_REQ_B: - str = "SSLv3 write certificate request B"; + case TLS_ST_SW_HELLO_REQ: + str = "SSLv3/TLS write hello request"; break; - case SSL3_ST_SW_SESSION_TICKET_A: - str = "SSLv3 write session ticket A"; + case TLS_ST_SW_SRVR_HELLO: + str = "SSLv3/TLS write server hello"; break; - case SSL3_ST_SW_SESSION_TICKET_B: - str = "SSLv3 write session ticket B"; + case TLS_ST_SW_CERT: + str = "SSLv3/TLS write certificate"; break; - case SSL3_ST_SW_SRVR_DONE_A: - str = "SSLv3 write server done A"; + case TLS_ST_SW_KEY_EXCH: + str = "SSLv3/TLS write key exchange"; break; - case SSL3_ST_SW_SRVR_DONE_B: - str = "SSLv3 write server done B"; + case TLS_ST_SW_CERT_REQ: + str = "SSLv3/TLS write certificate request"; break; - case SSL3_ST_SR_CERT_A: - str = "SSLv3 read client certificate A"; + case TLS_ST_SW_SESSION_TICKET: + str = "SSLv3/TLS write session ticket"; break; - case SSL3_ST_SR_CERT_B: - str = "SSLv3 read client certificate B"; + case TLS_ST_SW_SRVR_DONE: + str = "SSLv3/TLS write server done"; break; - case SSL3_ST_SR_KEY_EXCH_A: - str = "SSLv3 read client key exchange A"; + case TLS_ST_SR_CERT: + str = "SSLv3/TLS read client certificate"; break; - case SSL3_ST_SR_KEY_EXCH_B: - str = "SSLv3 read client key exchange B"; + case TLS_ST_SR_KEY_EXCH: + str = "SSLv3/TLS read client key exchange"; break; - case SSL3_ST_SR_CERT_VRFY_A: - str = "SSLv3 read certificate verify A"; + case TLS_ST_SR_CERT_VRFY: + str = "SSLv3/TLS read certificate verify"; break; - case SSL3_ST_SR_CERT_VRFY_B: - str = "SSLv3 read certificate verify B"; - break; -#endif /* DTLS */ - case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: - str = "DTLS1 read hello verify request A"; - break; - case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: - str = "DTLS1 read hello verify request B"; - break; - case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: - str = "DTLS1 write hello verify request A"; + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + str = "DTLS1 read hello verify request"; break; - case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: - str = "DTLS1 write hello verify request B"; + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + str = "DTLS1 write hello verify request"; break; default: @@ -328,203 +204,100 @@ const char *SSL_state_string(const SSL *s) { const char *str; - switch (s->state) { - case SSL_ST_BEFORE: + if (statem_in_error(s)) { + return "SSLERR"; + } + + switch (SSL_state(s)) { + case TLS_ST_BEFORE: str = "PINIT "; break; - case SSL_ST_ACCEPT: - str = "AINIT "; - break; - case SSL_ST_CONNECT: - str = "CINIT "; - break; - case SSL_ST_OK: + case TLS_ST_OK: str = "SSLOK "; break; - case SSL_ST_ERR: - str = "SSLERR"; - break; -#ifndef OPENSSL_NO_SSL3 -/* SSLv3 additions */ - case SSL3_ST_SW_FLUSH: - case SSL3_ST_CW_FLUSH: - str = "3FLUSH"; - break; - case SSL3_ST_CW_CLNT_HELLO_A: - str = "3WCH_A"; - break; - case SSL3_ST_CW_CLNT_HELLO_B: - str = "3WCH_B"; - break; - case SSL3_ST_CR_SRVR_HELLO_A: - str = "3RSH_A"; - break; - case SSL3_ST_CR_SRVR_HELLO_B: - str = "3RSH_B"; - break; - case SSL3_ST_CR_CERT_A: - str = "3RSC_A"; - break; - case SSL3_ST_CR_CERT_B: - str = "3RSC_B"; - break; - case SSL3_ST_CR_KEY_EXCH_A: - str = "3RSKEA"; - break; - case SSL3_ST_CR_KEY_EXCH_B: - str = "3RSKEB"; - break; - case SSL3_ST_CR_CERT_REQ_A: - str = "3RCR_A"; - break; - case SSL3_ST_CR_CERT_REQ_B: - str = "3RCR_B"; - break; - case SSL3_ST_CR_SRVR_DONE_A: - str = "3RSD_A"; + case TLS_ST_CW_CLNT_HELLO: + str = "3WCH"; break; - case SSL3_ST_CR_SRVR_DONE_B: - str = "3RSD_B"; + case TLS_ST_CR_SRVR_HELLO: + str = "3RSH"; break; - case SSL3_ST_CW_CERT_A: - str = "3WCC_A"; + case TLS_ST_CR_CERT: + str = "3RSC"; break; - case SSL3_ST_CW_CERT_B: - str = "3WCC_B"; + case TLS_ST_CR_KEY_EXCH: + str = "3RSKE"; break; - case SSL3_ST_CW_CERT_C: - str = "3WCC_C"; + case TLS_ST_CR_CERT_REQ: + str = "3RCR"; break; - case SSL3_ST_CW_CERT_D: - str = "3WCC_D"; + case TLS_ST_CR_SRVR_DONE: + str = "3RSD"; break; - case SSL3_ST_CW_KEY_EXCH_A: - str = "3WCKEA"; + case TLS_ST_CW_CERT: + str = "3WCC"; break; - case SSL3_ST_CW_KEY_EXCH_B: - str = "3WCKEB"; + case TLS_ST_CW_KEY_EXCH: + str = "3WCKE"; break; - case SSL3_ST_CW_CERT_VRFY_A: - str = "3WCV_A"; - break; - case SSL3_ST_CW_CERT_VRFY_B: - str = "3WCV_B"; + case TLS_ST_CW_CERT_VRFY: + str = "3WCV"; break; - case SSL3_ST_SW_CHANGE_A: - case SSL3_ST_CW_CHANGE_A: - str = "3WCCSA"; - break; - case SSL3_ST_SW_CHANGE_B: - case SSL3_ST_CW_CHANGE_B: - str = "3WCCSB"; - break; - case SSL3_ST_SW_FINISHED_A: - case SSL3_ST_CW_FINISHED_A: - str = "3WFINA"; - break; - case SSL3_ST_SW_FINISHED_B: - case SSL3_ST_CW_FINISHED_B: - str = "3WFINB"; - break; - case SSL3_ST_SR_CHANGE_A: - case SSL3_ST_CR_CHANGE_A: - str = "3RCCSA"; + case TLS_ST_SW_CHANGE: + case TLS_ST_CW_CHANGE: + str = "3WCCS"; break; - case SSL3_ST_SR_CHANGE_B: - case SSL3_ST_CR_CHANGE_B: - str = "3RCCSB"; + case TLS_ST_SW_FINISHED: + case TLS_ST_CW_FINISHED: + str = "3WFIN"; break; - case SSL3_ST_SR_FINISHED_A: - case SSL3_ST_CR_FINISHED_A: - str = "3RFINA"; + case TLS_ST_SR_CHANGE: + case TLS_ST_CR_CHANGE: + str = "3RCCS"; break; - case SSL3_ST_SR_FINISHED_B: - case SSL3_ST_CR_FINISHED_B: - str = "3RFINB"; + case TLS_ST_SR_FINISHED: + case TLS_ST_CR_FINISHED: + str = "3RFIN"; break; - case SSL3_ST_SW_HELLO_REQ_A: - str = "3WHR_A"; - break; - case SSL3_ST_SW_HELLO_REQ_B: - str = "3WHR_B"; - break; - case SSL3_ST_SW_HELLO_REQ_C: - str = "3WHR_C"; - break; - case SSL3_ST_SR_CLNT_HELLO_A: - str = "3RCH_A"; - break; - case SSL3_ST_SR_CLNT_HELLO_B: - str = "3RCH_B"; - break; - case SSL3_ST_SR_CLNT_HELLO_C: - str = "3RCH_C"; + case TLS_ST_SW_HELLO_REQ: + str = "3WHR"; break; - case SSL3_ST_SW_SRVR_HELLO_A: - str = "3WSH_A"; + case TLS_ST_SR_CLNT_HELLO: + str = "3RCH"; break; - case SSL3_ST_SW_SRVR_HELLO_B: - str = "3WSH_B"; + case TLS_ST_SW_SRVR_HELLO: + str = "3WSH"; break; - case SSL3_ST_SW_CERT_A: - str = "3WSC_A"; + case TLS_ST_SW_CERT: + str = "3WSC"; break; - case SSL3_ST_SW_CERT_B: - str = "3WSC_B"; + case TLS_ST_SW_KEY_EXCH: + str = "3WSKE"; break; - case SSL3_ST_SW_KEY_EXCH_A: - str = "3WSKEA"; + case TLS_ST_SW_CERT_REQ: + str = "3WCR"; break; - case SSL3_ST_SW_KEY_EXCH_B: - str = "3WSKEB"; + case TLS_ST_SW_SRVR_DONE: + str = "3WSD"; break; - case SSL3_ST_SW_CERT_REQ_A: - str = "3WCR_A"; + case TLS_ST_SR_CERT: + str = "3RCC"; break; - case SSL3_ST_SW_CERT_REQ_B: - str = "3WCR_B"; + case TLS_ST_SR_KEY_EXCH: + str = "3RCKE"; break; - case SSL3_ST_SW_SRVR_DONE_A: - str = "3WSD_A"; + case TLS_ST_SR_CERT_VRFY: + str = "3RCV"; break; - case SSL3_ST_SW_SRVR_DONE_B: - str = "3WSD_B"; - break; - case SSL3_ST_SR_CERT_A: - str = "3RCC_A"; - break; - case SSL3_ST_SR_CERT_B: - str = "3RCC_B"; - break; - case SSL3_ST_SR_KEY_EXCH_A: - str = "3RCKEA"; - break; - case SSL3_ST_SR_KEY_EXCH_B: - str = "3RCKEB"; - break; - case SSL3_ST_SR_CERT_VRFY_A: - str = "3RCV_A"; - break; - case SSL3_ST_SR_CERT_VRFY_B: - str = "3RCV_B"; - break; -#endif /* DTLS */ - case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: - str = "DRCHVA"; - break; - case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: - str = "DRCHVB"; - break; - case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: - str = "DWCHVA"; + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + str = "DRCHV"; break; - case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: - str = "DWCHVB"; + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + str = "DWCHV"; break; default: diff --git a/ssl/statem.c b/ssl/statem.c index 2fe3df4b7e..e30eda9844 100644 --- a/ssl/statem.c +++ b/ssl/statem.c @@ -130,12 +130,52 @@ static unsigned long server_max_message_size(SSL *s); static enum MSG_PROCESS_RETURN server_process_message(SSL *s, unsigned long len); static enum WORK_STATE server_post_process_message(SSL *s, enum WORK_STATE wst); + +enum HANDSHAKE_STATE SSL_state(const SSL *ssl) +{ + return ssl->statem.hand_state; +} + +void SSL_set_state(SSL *ssl, enum HANDSHAKE_STATE state) +{ + /* + * This function seems like a really bad idea. Should we remove it + * completely? + */ + ssl->statem.hand_state = state; +} + +int SSL_in_init(SSL *s) +{ + return s->statem.in_init; +} + +int SSL_is_init_finished(SSL *s) +{ + return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK); +} + +int SSL_in_before(SSL *s) +{ + /* + * Historically being "in before" meant before anything had happened. In the + * current code though we remain in the "before" state for a while after we + * have started the handshake process (e.g. as a server waiting for the + * first message to arrive). There "in before" is taken to mean "in before" + * and not started any handshake process yet. + */ + return (s->statem.hand_state == TLS_ST_BEFORE) + && (s->statem.state == MSG_FLOW_UNINITED); +} + /* * Clear the state machine state and reset back to MSG_FLOW_UNINITED */ void statem_clear(SSL *s) { s->statem.state = MSG_FLOW_UNINITED; + s->statem.hand_state = TLS_ST_BEFORE; + s->statem.in_init = 1; } /* @@ -153,8 +193,26 @@ void statem_set_renegotiate(SSL *s) void statem_set_error(SSL *s) { s->statem.state = MSG_FLOW_ERROR; - /* TODO: This is temporary - remove me */ - s->state = SSL_ST_ERR; +} + +/* + * Discover whether the current connection is in the error state. + * + * Valid return values are: + * 1: Yes + * 0: No + */ +int statem_in_error(const SSL *s) +{ + if (s->statem.state == MSG_FLOW_ERROR) + return 1; + + return 0; +} + +void statem_set_in_init(SSL *s, int init) +{ + s->statem.in_init = init; } int ssl3_connect(SSL *s) { @@ -266,12 +324,6 @@ static int state_machine(SSL *s, int server) { } if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE) { - /* TODO: Temporary - fix this */ - if (server) - s->state = SSL_ST_ACCEPT; - else - s->state = SSL_ST_CONNECT; - if (st->state == MSG_FLOW_UNINITED) { st->hand_state = TLS_ST_BEFORE; } @@ -1123,8 +1175,7 @@ static enum WRITE_TRAN client_write_transition(SSL *s) case TLS_ST_CW_FINISHED: if (s->hit) { st->hand_state = TLS_ST_OK; - /* TODO: This needs removing */ - s->state = SSL_ST_OK; + statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; } else { return WRITE_TRAN_FINISHED; @@ -1136,8 +1187,7 @@ static enum WRITE_TRAN client_write_transition(SSL *s) return WRITE_TRAN_CONTINUE; } else { st->hand_state = TLS_ST_OK; - /* TODO: This needs removing */ - s->state = SSL_ST_OK; + statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; } @@ -1727,8 +1777,7 @@ static enum WRITE_TRAN server_write_transition(SSL *s) case TLS_ST_SW_HELLO_REQ: st->hand_state = TLS_ST_OK; - /* TODO: This needs removing */ - s->state = SSL_ST_OK; + statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; case TLS_ST_SR_CLNT_HELLO: @@ -1795,8 +1844,7 @@ static enum WRITE_TRAN server_write_transition(SSL *s) case TLS_ST_SR_FINISHED: if (s->hit) { st->hand_state = TLS_ST_OK; - /* TODO: This needs removing */ - s->state = SSL_ST_OK; + statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; } else if (s->tlsext_ticket_expected) { st->hand_state = TLS_ST_SW_SESSION_TICKET; @@ -1818,8 +1866,7 @@ static enum WRITE_TRAN server_write_transition(SSL *s) return WRITE_TRAN_FINISHED; } st->hand_state = TLS_ST_OK; - /* TODO: This needs removing */ - s->state = SSL_ST_OK; + statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; default: -- GitLab