summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/s_server.c2
-rw-r--r--include/openssl/ssl.h67
-rw-r--r--ssl/d1_both.c150
-rw-r--r--ssl/d1_srvr.c706
-rw-r--r--ssl/record/rec_layer_d1.c19
-rw-r--r--ssl/record/rec_layer_s3.c6
-rw-r--r--ssl/s3_both.c161
-rw-r--r--ssl/s3_lib.c7
-rw-r--r--ssl/s3_msg.c4
-rw-r--r--ssl/s3_srvr.c916
-rw-r--r--ssl/ssl_lib.c19
-rw-r--r--ssl/ssl_locl.h81
-rw-r--r--ssl/ssl_stat.c479
-rw-r--r--ssl/statem.c83
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;
@@ -3615,52 +2745,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
@@ -718,58 +718,6 @@ 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: