summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-07-29 14:08:49 +0100
committerMatt Caswell <matt@openssl.org>2015-10-30 08:32:44 +0000
commitb9908bf9b8d6d609736b537f4ecda720ff5dc078 (patch)
treef5ac9e8ecccfbc2d360dd1930c2077a7aafe3945 /ssl
parentf8e0a5573820bd7318782d4954c6643ff7e58102 (diff)
Split client message reading and writing functions
The new state machine code will split up the reading and writing of hanshake messages into discrete phases. In order to facilitate that the existing "get" type functions will be split into two halves: one to get the message and one to process it. The "send" type functions will also have all work relating to constructing the message split out into a separate function just for that. For some functions there will also be separate pre and post "work" phases to prepare or update state. Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s3_both.c143
-rw-r--r--ssl/s3_clnt.c2075
-rw-r--r--ssl/ssl_err.c25
-rw-r--r--ssl/ssl_locl.h38
4 files changed, 1279 insertions, 1002 deletions
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index d8a2da1362..e9ab4a6392 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -158,44 +158,54 @@ int ssl3_do_write(SSL *s, int type)
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;
int i;
unsigned long l;
- if (s->state == a) {
- p = ssl_handshake_start(s);
+ p = ssl_handshake_start(s);
- i = s->method->ssl3_enc->final_finish_mac(s,
- sender, slen,
- s->s3->tmp.finish_md);
- if (i <= 0)
- return 0;
- s->s3->tmp.finish_md_len = i;
- memcpy(p, s->s3->tmp.finish_md, i);
- l = i;
+ i = s->method->ssl3_enc->final_finish_mac(s,
+ sender, slen,
+ s->s3->tmp.finish_md);
+ if (i <= 0)
+ return 0;
+ s->s3->tmp.finish_md_len = i;
+ memcpy(p, s->s3->tmp.finish_md, i);
+ l = i;
- /*
- * Copy the finished so we can use it for renegotiation checks
- */
- if (s->type == SSL_ST_CONNECT) {
- OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
- memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
- s->s3->previous_client_finished_len = i;
- } else {
- OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
- memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
- s->s3->previous_server_finished_len = i;
- }
+ /*
+ * Copy the finished so we can use it for renegotiation checks
+ */
+ if (s->type == SSL_ST_CONNECT) {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
+ s->s3->previous_client_finished_len = i;
+ } else {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
+ s->s3->previous_server_finished_len = i;
+ }
- if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
- SSLerr(SSL_F_SSL3_SEND_FINISHED, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->state = b;
+ if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- /* SSL3_ST_SEND_xxxxxx_HELLO_B */
- return ssl_do_write(s);
+ return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
@@ -230,7 +240,7 @@ static void ssl3_take_mac(SSL *s)
int ssl3_get_change_cipher_spec(SSL *s, int a, int b)
{
- int ok, al;
+ int ok;
long n;
n = s->method->ssl_get_message(s, a, b, SSL3_MT_CHANGE_CIPHER_SPEC, 1, &ok);
@@ -238,6 +248,18 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b)
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;
+
/*
* 'Change Cipher Spec' is just a single byte, which should already have
* been consumed by ssl_get_message() so there should be no bytes left,
@@ -248,13 +270,15 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b)
|| (s->version != DTLS1_BAD_VER
&& n != DTLS1_CCS_HEADER_LENGTH - 1)) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
}
} else {
if (n != 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
}
}
@@ -262,14 +286,14 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b)
/* Check we have a cipher to change to */
if (s->s3->tmp.new_cipher == NULL) {
al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
goto f_err;
}
s->s3->change_cipher_spec = 1;
if (!ssl3_do_change_cipher_spec(s)) {
al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
goto f_err;
}
@@ -289,18 +313,18 @@ int ssl3_get_change_cipher_spec(SSL *s, int a, int b)
#endif
}
- return 1;
+ return MSG_PROCESS_CONTINUE_READING;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return 0;
+ statem_set_error(s);
+ return MSG_PROCESS_ERROR;
}
int ssl3_get_finished(SSL *s, int a, int b)
{
- int al, i, ok;
+ int ok;
long n;
- unsigned char *p;
#ifdef OPENSSL_NO_NEXTPROTONEG
/*
@@ -315,10 +339,18 @@ int ssl3_get_finished(SSL *s, int a, int b)
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;
+ unsigned char *p;
+
/* If this occurs, we have missed a message */
if (!s->s3->change_cipher_spec) {
al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
goto f_err;
}
s->s3->change_cipher_spec = 0;
@@ -326,15 +358,15 @@ int ssl3_get_finished(SSL *s, int a, int b)
p = (unsigned char *)s->init_msg;
i = s->s3->tmp.peer_finish_md_len;
- if (i != n) {
+ if (i < 0 || (unsigned long)i != n) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_BAD_DIGEST_LENGTH);
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH);
goto f_err;
}
if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) {
al = SSL_AD_DECRYPT_ERROR;
- SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_DIGEST_CHECK_FAILED);
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED);
goto f_err;
}
@@ -351,10 +383,11 @@ int ssl3_get_finished(SSL *s, int a, int b)
s->s3->previous_server_finished_len = i;
}
- return (1);
+ return MSG_PROCESS_CONTINUE_PROCESSING;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return (0);
+ statem_set_error(s);
+ return MSG_PROCESS_ERROR;
}
/*-
@@ -368,13 +401,11 @@ int ssl3_get_finished(SSL *s, int a, int b)
*/
int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
{
- unsigned char *p;
-
if (s->state == a) {
- p = (unsigned char *)s->init_buf->data;
- *p = SSL3_MT_CCS;
- s->init_num = 1;
- s->init_off = 0;
+ if(tls_construct_change_cipher_spec(s) == 0) {
+ statem_set_error(s);
+ return 0;
+ }
s->state = b;
}
@@ -383,6 +414,18 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
return (ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC));
}
+int tls_construct_change_cipher_spec(SSL *s)
+{
+ unsigned char *p;
+
+ p = (unsigned char *)s->init_buf->data;
+ *p = SSL3_MT_CCS;
+ s->init_num = 1;
+ s->init_off = 0;
+
+ return 1;
+}
+
unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
{
unsigned char *p;
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 8a89b4268c..b967b97995 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -379,16 +379,7 @@ int ssl3_connect(SSL *s)
ret = ssl3_get_server_done(s);
if (ret <= 0)
goto end;
-#ifndef OPENSSL_NO_SRP
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
- if ((ret = SRP_Calc_A_param(s)) <= 0) {
- SSLerr(SSL_F_SSL3_CONNECT, SSL_R_SRP_A_CALC);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- s->state = SSL_ST_ERR;
- goto end;
- }
- }
-#endif
+
if (s->s3->tmp.cert_req)
s->state = SSL3_ST_CW_CERT_A;
else
@@ -741,6 +732,23 @@ static int ssl_set_version(SSL *s)
int ssl3_client_hello(SSL *s)
{
+ if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
+ if(tls_construct_client_hello(s) == 0)
+ goto err;
+
+ s->state = SSL3_ST_CW_CLNT_HELLO_B;
+ }
+
+ /* SSL3_ST_CW_CLNT_HELLO_B */
+ return ssl_do_write(s);
+ err:
+ s->state = SSL_ST_ERR;
+ return -1;
+
+}
+
+int tls_construct_client_hello(SSL *s)
+{
unsigned char *buf;
unsigned char *p, *d;
int i;
@@ -750,193 +758,180 @@ int ssl3_client_hello(SSL *s)
int j;
SSL_COMP *comp;
#endif
+ SSL_SESSION *sess = s->session;
buf = (unsigned char *)s->init_buf->data;
- if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
- SSL_SESSION *sess = s->session;
- /* Work out what SSL/TLS/DTLS version to use */
- if (ssl_set_version(s) == 0)
- goto err;
-
- if ((sess == NULL) || (sess->ssl_version != s->version) ||
- /*
- * In the case of EAP-FAST, we can have a pre-shared
- * "ticket" without a session ID.
- */
- (!sess->session_id_length && !sess->tlsext_tick) ||
- (sess->not_resumable)) {
- if (!ssl_get_new_session(s, 0))
- goto err;
- }
- /* else use the pre-loaded session */
-
- p = s->s3->client_random;
+ /* Work out what SSL/TLS/DTLS version to use */
+ if (ssl_set_version(s) == 0)
+ goto err;
+ if ((sess == NULL) || (sess->ssl_version != s->version) ||
/*
- * for DTLS if client_random is initialized, reuse it, we are
- * required to use same upon reply to HelloVerify
+ * In the case of EAP-FAST, we can have a pre-shared
+ * "ticket" without a session ID.
*/
- if (SSL_IS_DTLS(s)) {
- size_t idx;
- i = 1;
- for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
- if (p[idx]) {
- i = 0;
- break;
- }
- }
- } else
- i = 1;
-
- if (i && ssl_fill_hello_random(s, 0, p,
- sizeof(s->s3->client_random)) <= 0)
+ (!sess->session_id_length && !sess->tlsext_tick) ||
+ (sess->not_resumable)) {
+ if (!ssl_get_new_session(s, 0))
goto err;
+ }
+ /* else use the pre-loaded session */
- /* Do the message type and length last */
- d = p = ssl_handshake_start(s);
-
- /*-
- * version indicates the negotiated version: for example from
- * an SSLv2/v3 compatible client hello). The client_version
- * field is the maximum version we permit and it is also
- * used in RSA encrypted premaster secrets. Some servers can
- * choke if we initially report a higher version then
- * renegotiate to a lower one in the premaster secret. This
- * didn't happen with TLS 1.0 as most servers supported it
- * but it can with TLS 1.1 or later if the server only supports
- * 1.0.
- *
- * Possible scenario with previous logic:
- * 1. Client hello indicates TLS 1.2
- * 2. Server hello says TLS 1.0
- * 3. RSA encrypted premaster secret uses 1.2.
- * 4. Handhaked proceeds using TLS 1.0.
- * 5. Server sends hello request to renegotiate.
- * 6. Client hello indicates TLS v1.0 as we now
- * know that is maximum server supports.
- * 7. Server chokes on RSA encrypted premaster secret
- * containing version 1.0.
- *
- * For interoperability it should be OK to always use the
- * maximum version we support in client hello and then rely
- * on the checking of version to ensure the servers isn't
- * being inconsistent: for example initially negotiating with
- * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
- * client_version in client hello and not resetting it to
- * the negotiated version.
- */
- *(p++) = s->client_version >> 8;
- *(p++) = s->client_version & 0xff;
-
- /* Random stuff */
- memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
- p += SSL3_RANDOM_SIZE;
+ p = s->s3->client_random;
- /* Session ID */
- if (s->new_session)
- i = 0;
- else
- i = s->session->session_id_length;
- *(p++) = i;
- if (i != 0) {
- if (i > (int)sizeof(s->session->session_id)) {
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
+ /*
+ * for DTLS if client_random is initialized, reuse it, we are
+ * required to use same upon reply to HelloVerify
+ */
+ if (SSL_IS_DTLS(s)) {
+ size_t idx;
+ i = 1;
+ for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
+ if (p[idx]) {
+ i = 0;
+ break;
}
- memcpy(p, s->session->session_id, i);
- p += i;
}
+ } else
+ i = 1;
- /* cookie stuff for DTLS */
- if (SSL_IS_DTLS(s)) {
- if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- *(p++) = s->d1->cookie_len;
- memcpy(p, s->d1->cookie, s->d1->cookie_len);
- p += s->d1->cookie_len;
+ if (i && ssl_fill_hello_random(s, 0, p,
+ sizeof(s->s3->client_random)) <= 0)
+ goto err;
+
+ /* Do the message type and length last */
+ d = p = ssl_handshake_start(s);
+
+ /*-
+ * version indicates the negotiated version: for example from
+ * an SSLv2/v3 compatible client hello). The client_version
+ * field is the maximum version we permit and it is also
+ * used in RSA encrypted premaster secrets. Some servers can
+ * choke if we initially report a higher version then
+ * renegotiate to a lower one in the premaster secret. This
+ * didn't happen with TLS 1.0 as most servers supported it
+ * but it can with TLS 1.1 or later if the server only supports
+ * 1.0.
+ *
+ * Possible scenario with previous logic:
+ * 1. Client hello indicates TLS 1.2
+ * 2. Server hello says TLS 1.0
+ * 3. RSA encrypted premaster secret uses 1.2.
+ * 4. Handhaked proceeds using TLS 1.0.
+ * 5. Server sends hello request to renegotiate.
+ * 6. Client hello indicates TLS v1.0 as we now
+ * know that is maximum server supports.
+ * 7. Server chokes on RSA encrypted premaster secret
+ * containing version 1.0.
+ *
+ * For interoperability it should be OK to always use the
+ * maximum version we support in client hello and then rely
+ * on the checking of version to ensure the servers isn't
+ * being inconsistent: for example initially negotiating with
+ * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+ * client_version in client hello and not resetting it to
+ * the negotiated version.
+ */
+ *(p++) = s->client_version >> 8;
+ *(p++) = s->client_version & 0xff;
+
+ /* Random stuff */
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ /* Session ID */
+ if (s->new_session)
+ i = 0;
+ else
+ i = s->session->session_id_length;
+ *(p++) = i;
+ if (i != 0) {
+ if (i > (int)sizeof(s->session->session_id)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
}
+ memcpy(p, s->session->session_id, i);
+ p += i;
+ }
- /* Ciphers supported */
- i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]));
- if (i == 0) {
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
+ *(p++) = s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ }
+
+ /* Ciphers supported */
+ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]));
+ if (i == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
+ goto err;
+ }
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
- /*
- * Some servers hang if client hello > 256 bytes as hack workaround
- * chop number of supported ciphers to keep it well below this if we
- * use TLS v1.2
- */
- if (TLS1_get_version(s) >= TLS1_2_VERSION
- && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
- i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
+ /*
+ * Some servers hang if client hello > 256 bytes as hack workaround
+ * chop number of supported ciphers to keep it well below this if we
+ * use TLS v1.2
+ */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION
+ && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
+ i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
#endif
- s2n(i, p);
- p += i;
+ s2n(i, p);
+ p += i;
- /* COMPRESSION */
+ /* COMPRESSION */
#ifdef OPENSSL_NO_COMP
- *(p++) = 1;
+ *(p++) = 1;
#else
- if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
- j = 0;
- else
- j = sk_SSL_COMP_num(s->ctx->comp_methods);
- *(p++) = 1 + j;
- for (i = 0; i < j; i++) {
- comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
- *(p++) = comp->id;
- }
+ if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
+ j = 0;
+ else
+ j = sk_SSL_COMP_num(s->ctx->comp_methods);
+ *(p++) = 1 + j;
+ for (i = 0; i < j; i++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
+ *(p++) = comp->id;
+ }
#endif
- *(p++) = 0; /* Add the NULL method */
+ *(p++) = 0; /* Add the NULL method */
- /* TLS extensions */
- if (ssl_prepare_clienthello_tlsext(s) <= 0) {
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
- }
- if ((p =
- ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
- &al)) == NULL) {
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
- }
+ /* TLS extensions */
+ if (ssl_prepare_clienthello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+ if ((p =
+ ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ &al)) == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- l = p - d;
- if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- s->state = SSL3_ST_CW_CLNT_HELLO_B;
+ l = p - d;
+ if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
}
- /* SSL3_ST_CW_CLNT_HELLO_B */
- return ssl_do_write(s);
+ return 1;
err:
- s->state = SSL_ST_ERR;
- return (-1);
+ statem_set_error(s);
+ return 0;
}
int ssl3_get_server_hello(SSL *s)
{
- STACK_OF(SSL_CIPHER) *sk;
- const SSL_CIPHER *c;
- PACKET pkt, session_id;
- size_t session_id_len;
- unsigned char *cipherchars;
- int i, al = SSL_AD_INTERNAL_ERROR, ok;
- unsigned int compression;
+ int ok, al;
long n;
-#ifndef OPENSSL_NO_COMP
- SSL_COMP *comp;
-#endif
/*
* Hello verify request and/or server hello version may not match so set
* first packet if we're negotiating version.
@@ -971,9 +966,29 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+ return tls_process_server_hello(s, (unsigned long)n);
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->state = SSL_ST_ERR;
+ return (-1);
+}
+
+enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, unsigned long n)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+ const SSL_CIPHER *c;
+ PACKET pkt, session_id;
+ size_t session_id_len;
+ unsigned char *cipherchars;
+ int i, al = SSL_AD_INTERNAL_ERROR;
+ unsigned int compression;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp;
+#endif
+
if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
@@ -982,7 +997,7 @@ int ssl3_get_server_hello(SSL *s)
if (!PACKET_get_net_2(&pkt, &sversion)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
@@ -992,7 +1007,7 @@ int ssl3_get_server_hello(SSL *s)
#ifndef OPENSSL_NO_SSL3
if ((sversion == SSL3_VERSION) && !(s->options & SSL_OP_NO_SSLv3)) {
if (FIPS_mode()) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
@@ -1009,14 +1024,14 @@ int ssl3_get_server_hello(SSL *s)
!(s->options & SSL_OP_NO_TLSv1_2)) {
s->method = TLSv1_2_client_method();
} else {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL);
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
s->session->ssl_version = s->version = s->method->version;
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_VERSION_TOO_LOW);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_VERSION_TOO_LOW);
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
@@ -1027,7 +1042,7 @@ int ssl3_get_server_hello(SSL *s)
if (!PACKET_get_net_2(&pkt, &hversion)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
@@ -1035,7 +1050,7 @@ int ssl3_get_server_hello(SSL *s)
if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2))
s->method = DTLSv1_2_client_method();
else if (tls1_suiteb(s)) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
s->version = hversion;
al = SSL_AD_PROTOCOL_VERSION;
@@ -1043,7 +1058,7 @@ int ssl3_get_server_hello(SSL *s)
} else if (hversion == DTLS1_VERSION && !(options & SSL_OP_NO_DTLSv1))
s->method = DTLSv1_client_method();
else {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
s->version = hversion;
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
@@ -1054,12 +1069,12 @@ int ssl3_get_server_hello(SSL *s)
if (!PACKET_get_bytes(&pkt, &vers, 2)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
if ((vers[0] != (s->version >> 8))
|| (vers[1] != (s->version & 0xff))) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
s->version = (s->version & 0xff00) | vers[1];
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
@@ -1070,7 +1085,7 @@ int ssl3_get_server_hello(SSL *s)
/* load the server random */
if (!PACKET_copy_bytes(&pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
@@ -1086,7 +1101,7 @@ int ssl3_get_server_hello(SSL *s)
if (session_id_len > sizeof s->session->session_id
|| session_id_len > SSL3_SESSION_ID_SIZE) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
goto f_err;
}
@@ -1119,7 +1134,7 @@ int ssl3_get_server_hello(SSL *s)
s->session->cipher = pref_cipher ?
pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
} else {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
@@ -1132,7 +1147,7 @@ int ssl3_get_server_hello(SSL *s)
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
/* actually a client application bug */
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto f_err;
}
@@ -1161,7 +1176,7 @@ int ssl3_get_server_hello(SSL *s)
if (c == NULL) {
/* unknown cipher */
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED);
goto f_err;
}
/* Set version disabled mask now we know version */
@@ -1175,7 +1190,7 @@ int ssl3_get_server_hello(SSL *s)
*/
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
goto f_err;
}
@@ -1184,7 +1199,7 @@ int ssl3_get_server_hello(SSL *s)
if (i < 0) {
/* we did not say we would use this cipher */
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
goto f_err;
}
@@ -1197,7 +1212,7 @@ int ssl3_get_server_hello(SSL *s)
s->session->cipher_id = s->session->cipher->id;
if (s->hit && (s->session->cipher_id != c->id)) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
goto f_err;
}
@@ -1218,7 +1233,7 @@ int ssl3_get_server_hello(SSL *s)
#ifdef OPENSSL_NO_COMP
if (compression != 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto f_err;
}
@@ -1227,13 +1242,13 @@ int ssl3_get_server_hello(SSL *s)
* using compression.
*/
if (s->session->compress_meth != 0) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
goto f_err;
}
#else
if (s->hit && compression != s->session->compress_meth) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
goto f_err;
}
@@ -1241,7 +1256,7 @@ int ssl3_get_server_hello(SSL *s)
comp = NULL;
else if (!ssl_allow_compression(s)) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
goto f_err;
} else {
comp = ssl3_comp_find(s->ctx->comp_methods, compression);
@@ -1249,7 +1264,7 @@ int ssl3_get_server_hello(SSL *s)
if (compression != 0 && comp == NULL) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto f_err;
} else {
@@ -1259,34 +1274,29 @@ int ssl3_get_server_hello(SSL *s)
/* TLS extensions */
if (!ssl_parse_serverhello_tlsext(s, &pkt)) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
goto err;
}
if (PACKET_remaining(&pkt) != 0) {
/* wrong packet length */
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
goto f_err;
}
- return (1);
+ return MSG_PROCESS_CONTINUE_READING;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
- s->state = SSL_ST_ERR;
- return (-1);
+ statem_set_error(s);
+ return MSG_PROCESS_ERROR;
}
int ssl3_get_server_certificate(SSL *s)
{
- int al, i, ok, ret = -1, exp_idx;
- unsigned long n, cert_list_len, cert_len;
- X509 *x = NULL;
- unsigned char *certstart, *certbytes;
- STACK_OF(X509) *sk = NULL;
- EVP_PKEY *pkey = NULL;
- PACKET pkt;
+ long n;
+ int ok, al;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_A,
@@ -1307,28 +1317,45 @@ int ssl3_get_server_certificate(SSL *s)
goto f_err;
}
+ return tls_process_server_certificate(s, (unsigned long)n);
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->state = SSL_ST_ERR;
+ return -1;
+}
+
+enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, unsigned long n)
+{
+ int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
+ unsigned long cert_list_len, cert_len;
+ X509 *x = NULL;
+ unsigned char *certstart, *certbytes;
+ STACK_OF(X509) *sk = NULL;
+ EVP_PKEY *pkey = NULL;
+ PACKET pkt;
+
if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
goto f_err;
}
if ((sk = sk_X509_new_null()) == NULL) {
- SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PACKET_get_net_3(&pkt, &cert_list_len)
|| PACKET_remaining(&pkt) != cert_list_len) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
while (PACKET_remaining(&pkt)) {
if (!PACKET_get_net_3(&pkt, &cert_len)
|| !PACKET_get_bytes(&pkt, &certbytes, cert_len)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;