summaryrefslogtreecommitdiffstats
path: root/ssl/s3_srvr.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-09-08 09:38:08 +0100
committerMatt Caswell <matt@openssl.org>2015-10-30 08:38:18 +0000
commite27f234a4147a7bd621d2a439c2cc2cc9a6a8382 (patch)
treeb18fe84ebeec97d3fecef591388a4506fdaa06d7 /ssl/s3_srvr.c
parent4e3458a565da5bccf30fe598e87ad7da1ee9daa7 (diff)
Split TLS server functions
Split the TLS server ssl3_get_* and ssl3_send_* functions into two ready for the migration to the new state machine code. Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r--ssl/s3_srvr.c1976
1 files changed, 1077 insertions, 899 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 376ab7150d..98e831c58e 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -169,7 +169,6 @@ static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
STACK_OF(SSL_CIPHER) **skp,
int sslv2format, int *al);
-
#ifndef OPENSSL_NO_SRP
static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
{
@@ -350,37 +349,29 @@ int ssl3_accept(SSL *s)
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
- s->state = SSL3_ST_SR_CLNT_HELLO_D;
case SSL3_ST_SR_CLNT_HELLO_D:
{
- int al;
- if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
- /*
- * callback indicates firther work to be done
- */
- s->rwstate = SSL_X509_LOOKUP;
+ 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 (ret != SSL_ERROR_NONE) {
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- /*
- * This is not really an error but the only means to for
- * a client to detect whether srp is supported.
- */
- if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
- SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_CLIENTHELLO_TLSEXT);
+ if (wst_ret == WORK_ERROR) {
ret = -1;
- s->state = SSL_ST_ERR;
goto end;
}
}
-#endif
- s->renegotiate = 2;
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:
@@ -569,7 +560,7 @@ int ssl3_accept(SSL *s)
ret = ssl3_get_client_key_exchange(s);
if (ret <= 0)
goto end;
- if (ret == 2) {
+ if (s->no_cert_verify) {
/*
* For the ECDH ciphersuites when the client sends its ECDH
* pub key in a certificate, the CertificateVerify message is
@@ -825,8 +816,7 @@ int ssl3_send_hello_request(SSL *s)
{
if (s->state == SSL3_ST_SW_HELLO_REQ_A) {
- if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) {
- SSLerr(SSL_F_SSL3_SEND_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
+ if (tls_construct_hello_request(s) == 0) {
return -1;
}
s->state = SSL3_ST_SW_HELLO_REQ_B;
@@ -836,21 +826,22 @@ int ssl3_send_hello_request(SSL *s)
return ssl_do_write(s);
}
+int tls_construct_hello_request(SSL *s)
+{
+ if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
+ statem_set_error(s);
+ return 0;
+ }
+
+ return 1;
+}
+
int ssl3_get_client_hello(SSL *s)
{
- int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
- unsigned int j, complen = 0;
+ int ok;
long n;
- unsigned long id;
- SSL_CIPHER *c;
-#ifndef OPENSSL_NO_COMP
- SSL_COMP *comp = NULL;
-#endif
- STACK_OF(SSL_CIPHER) *ciphers = NULL;
- int protverr = 1;
- /* |cookie| will only be initialized for DTLS. */
- PACKET pkt, session_id, cipher_suites, compression, extensions, cookie;
- int is_v2_record;
+ enum WORK_STATE wst_ret;
if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
goto retry_cert;
@@ -874,8 +865,38 @@ int ssl3_get_client_hello(SSL *s)
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;
+ unsigned int j, complen = 0;
+ unsigned long id;
+ SSL_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp = NULL;
+#endif
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ int protverr = 1;
+ /* |cookie| will only be initialized for DTLS. */
+ PACKET pkt, session_id, cipher_suites, compression, extensions, cookie;
+ int is_v2_record;
+
if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
@@ -909,25 +930,25 @@ int ssl3_get_client_hello(SSL *s)
* layer in order to have determined that this is a SSLv2 record
* in the first place
*/
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!PACKET_get_net_2(&pkt, &version)) {
/* No protocol version supplied! */
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
goto err;
}
if (version == 0x0002) {
/* This is real SSLv2. We don't support it. */
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
goto err;
} else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
/* SSLv3/TLS */
s->client_version = version;
} else {
/* No idea what protocol this is */
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
goto err;
}
} else {
@@ -937,7 +958,7 @@ int ssl3_get_client_hello(SSL *s)
*/
if(!PACKET_get_net_2(&pkt, (unsigned int *)&s->client_version)) {
al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
}
@@ -998,7 +1019,7 @@ int ssl3_get_client_hello(SSL *s)
}
if (protverr) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
if ((!s->enc_write_ctx && !s->write_hash)) {
/*
* similar to ssl3_get_record, send alert using remote version
@@ -1023,7 +1044,8 @@ int ssl3_get_client_hello(SSL *s)
if (!PACKET_get_net_2(&pkt, &cipher_len)
|| !PACKET_get_net_2(&pkt, &session_id_len)
|| !PACKET_get_net_2(&pkt, &challenge_len)) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_RECORD_LENGTH_MISMATCH);
al = SSL_AD_DECODE_ERROR;
goto f_err;
}
@@ -1135,7 +1157,7 @@ int ssl3_get_client_hello(SSL *s)
}
if (SSL_IS_DTLS(s)) {
- /* Empty cookie was already handled above by returning early. */
+ /* Empty cookie was already handled above by returning early. */
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
if (s->ctx->app_verify_cookie_cb != NULL) {
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie),
@@ -1153,8 +1175,7 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
goto f_err;
}
- /* Set to -2 so if successful we return 2 */
- ret = -2;
+ s->d1->cookie_verified = 1;
}
if (s->method->version == DTLS_ANY_VERSION) {
/* Select version to use */
@@ -1278,7 +1299,7 @@ int ssl3_get_client_hello(SSL *s)
(s));
if (pref_cipher == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
goto f_err;
}
@@ -1304,7 +1325,7 @@ int ssl3_get_client_hello(SSL *s)
/* Perform sanity checks on resumed compression algorithm */
/* Can't disable compression */
if (!ssl_allow_compression(s)) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_INCONSISTENT_COMPRESSION);
goto f_err;
}
@@ -1317,7 +1338,7 @@ int ssl3_get_client_hello(SSL *s)
}
}
if (s->s3->tmp.new_compression == NULL) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto f_err;
}
@@ -1328,7 +1349,7 @@ int ssl3_get_client_hello(SSL *s)
}
if (k >= complen) {
al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
goto f_err;
}
@@ -1363,7 +1384,7 @@ int ssl3_get_client_hello(SSL *s)
* using compression.
*/
if (s->session->compress_meth != 0) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
goto f_err;
}
#endif
@@ -1382,89 +1403,140 @@ int ssl3_get_client_hello(SSL *s)
s->session->ciphers = ciphers;
if (ciphers == NULL) {
al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
ciphers = NULL;
if (!tls1_set_server_sigalgs(s)) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
- /* Let cert callback update server certificates if required */
- retry_cert:
- if (s->cert->cert_cb) {
- int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
- if (rv == 0) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CERT_CB_ERROR);
- goto f_err;
+ }
+
+ sk_SSL_CIPHER_free(ciphers);
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ statem_set_error(s);
+
+ sk_SSL_CIPHER_free(ciphers);
+ return MSG_PROCESS_ERROR;
+
+}
+
+enum WORK_STATE tls_post_process_client_hello(SSL *s, enum WORK_STATE wst)
+{
+ int al;
+ SSL_CIPHER *cipher;
+
+ if (wst == WORK_MORE_A) {
+ if (!s->hit) {
+ /* Let cert callback update server certificates if required */
+ if (s->cert->cert_cb) {
+ int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (rv == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_A;
+ }
+ s->rwstate = SSL_NOTHING;
}
- if (rv < 0) {
- s->rwstate = SSL_X509_LOOKUP;
- return -1;
+ cipher = ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+
+ if (cipher == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
}
- s->rwstate = SSL_NOTHING;
+ s->s3->tmp.new_cipher = cipher;
+ /* check whether we should disable session resumption */
+ if (s->not_resumable_session_cb != NULL)
+ s->session->not_resumable = s->not_resumable_session_cb(s,
+ ((cipher->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
+ if (s->session->not_resumable)
+ /* do not send a session ticket */
+ s->tlsext_ticket_expected = 0;
+ } else {
+ /* Session-id reuse */
+ s->s3->tmp.new_cipher = s->session->cipher;
}
- c = ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
- if (c == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
- goto f_err;
+ if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) {
+ if (!ssl3_digest_cached_records(s, 0))
+ goto f_err;
}
- s->s3->tmp.new_cipher = c;
- /* check whether we should disable session resumption */
- if (s->not_resumable_session_cb != NULL)
- s->session->not_resumable = s->not_resumable_session_cb(s,
- ((c->algorithm_mkey & (SSL_kDHE | SSL_kECDHE))
- != 0));
- if (s->session->not_resumable)
- /* do not send a session ticket */
- s->tlsext_ticket_expected = 0;
- } else {
- /* Session-id reuse */
- s->s3->tmp.new_cipher = s->session->cipher;
- }
- if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) {
- if (!ssl3_digest_cached_records(s, 0))
- goto f_err;
- }
+ /*-
+ * we now have the following setup.
+ * client_random
+ * cipher_list - our prefered list of ciphers
+ * ciphers - the clients prefered list of ciphers
+ * compression - basically ignored right now
+ * ssl version is set - sslv3
+ * s->session - The ssl session has been setup.
+ * s->hit - session reuse flag
+ * s->s3->tmp.new_cipher- the new cipher to use.
+ */
- /*-
- * we now have the following setup.
- * client_random
- * cipher_list - our prefered list of ciphers
- * ciphers - the clients prefered list of ciphers
- * compression - basically ignored right now
- * ssl version is set - sslv3
- * s->session - The ssl session has been setup.
- * s->hit - session reuse flag
- * s->s3->tmp.new_cipher- the new cipher to use.
- */
+ /* Handles TLS extensions that we couldn't check earlier */
+ if (s->version >= SSL3_VERSION) {
+ if (ssl_check_clienthello_tlsext_late(s) <= 0) {
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto f_err;
+ }
+ }
- /* Handles TLS extensions that we couldn't check earlier */
- if (s->version >= SSL3_VERSION) {
- if (ssl_check_clienthello_tlsext_late(s) <= 0) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
+ wst = WORK_MORE_B;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (wst == WORK_MORE_B) {
+ int ret;
+ if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
+ /*
+ * callback indicates further work to be done
+ */
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_B;
+ }
+ if (ret != SSL_ERROR_NONE) {
+ /*
+ * This is not really an error but the only means to for
+ * a client to detect whether srp is supported.
+ */
+ if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ goto f_err;
}
}
+#endif
+ s->renegotiate = 2;
- if (ret < 0)
- ret = -ret;
- if (0) {
+ return WORK_FINISHED_STOP;
f_err:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
- s->state = SSL_ST_ERR;
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ statem_set_error(s);
+ 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;
}
- sk_SSL_CIPHER_free(ciphers);
- return ret < 0 ? -1 : ret;
+ /* SSL3_ST_SW_SRVR_HELLO_B */
+ return ssl_do_write(s);
}
-int ssl3_send_server_hello(SSL *s)
+int tls_construct_server_hello(SSL *s)
{
unsigned char *buf;
unsigned char *p, *d;
@@ -1472,102 +1544,97 @@ int ssl3_send_server_hello(SSL *s)
int al = 0;
unsigned long l;
- if (s->state == SSL3_ST_SW_SRVR_HELLO_A) {
- buf = (unsigned char *)s->init_buf->data;
+ buf = (unsigned char *)s->init_buf->data;
- /* Do the message type and length last */
- d = p = ssl_handshake_start(s);
+ /* Do the message type and length last */
+ d = p = ssl_handshake_start(s);
- *(p++) = s->version >> 8;
- *(p++) = s->version & 0xff;
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
- /*
- * Random stuff. Filling of the server_random takes place in
- * ssl3_get_client_hello()
- */
- memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
- p += SSL3_RANDOM_SIZE;
+ /*
+ * Random stuff. Filling of the server_random takes place in
+ * tls_process_client_hello()
+ */
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
- /*-
- * There are several cases for the session ID to send
- * back in the server hello:
- * - For session reuse from the session cache,
- * we send back the old session ID.
- * - If stateless session reuse (using a session ticket)
- * is successful, we send back the client's "session ID"
- * (which doesn't actually identify the session).
- * - If it is a new session, we send back the new
- * session ID.
- * - However, if we want the new session to be single-use,
- * we send back a 0-length session ID.
- * s->hit is non-zero in either case of session reuse,
- * so the following won't overwrite an ID that we're supposed
- * to send back.
- */
- if (s->session->not_resumable ||
- (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
- && !s->hit))
- s->session->session_id_length = 0;
-
- sl = s->session->session_id_length;
- if (sl > (int)sizeof(s->session->session_id)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- s->state = SSL_ST_ERR;
- return -1;
- }
- *(p++) = sl;
- memcpy(p, s->session->session_id, sl);
- p += sl;
+ /*-
+ * There are several cases for the session ID to send
+ * back in the server hello:
+ * - For session reuse from the session cache,
+ * we send back the old session ID.
+ * - If stateless session reuse (using a session ticket)
+ * is successful, we send back the client's "session ID"
+ * (which doesn't actually identify the session).
+ * - If it is a new session, we send back the new
+ * session ID.
+ * - However, if we want the new session to be single-use,
+ * we send back a 0-length session ID.
+ * s->hit is non-zero in either case of session reuse,
+ * so the following won't overwrite an ID that we're supposed
+ * to send back.
+ */
+ if (s->session->not_resumable ||
+ (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+ && !s->hit))
+ s->session->session_id_length = 0;
+
+ sl = s->session->session_id_length;
+ if (sl > (int)sizeof(s->session->session_id)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ statem_set_error(s);
+ return 0;
+ }
+ *(p++) = sl;
+ memcpy(p, s->session->session_id, sl);
+ p += sl;
- /* put the cipher */
- i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p);
- p += i;
+ /* put the cipher */
+ i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p);
+ p += i;
- /* put the compression method */
+ /* put the compression method */
#ifdef OPENSSL_NO_COMP
- *(p++) = 0;
+ *(p++) = 0;
#else
- if (s->s3->tmp.new_compression == NULL)
- *(p++) = 0;
- else
- *(p++) = s->s3->tmp.new_compression->id;
+ if (s->s3->tmp.new_compression == NULL)
+ *(p++) = 0;
+ else
+ *(p++) = s->s3->tmp.new_compression->id;
#endif
- if (ssl_prepare_serverhello_tlsext(s) <= 0) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
- s->state = SSL_ST_ERR;
- return -1;
- }
- if ((p =
- ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
- &al)) == NULL) {
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- s->state = SSL_ST_ERR;
- return -1;
- }
+ if (ssl_prepare_serverhello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
+ statem_set_error(s);
+ return 0;
+ }
+ if ((p =
+ ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ &al)) == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ statem_set_error(s);
+ return 0;
+ }
- /* do the header */
- l = (p - d);
- if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->state = SSL3_ST_SW_SRVR_HELLO_B;
+ /* do the header */
+ l = (p - d);
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ statem_set_error(s);
+ return 0;
}
- /* SSL3_ST_SW_SRVR_HELLO_B */
- return ssl_do_write(s);
+ return 1;
}
int ssl3_send_server_done(SSL *s)
{
if (s->state == SSL3_ST_SW_SRVR_DONE_A) {
- if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_DONE, ERR_R_INTERNAL_ERROR);
+ if (tls_construct_server_done(s) == 0)
return -1;
- }
s->state = SSL3_ST_SW_SRVR_DONE_B;
}
@@ -1575,8 +1642,36 @@ int ssl3_send_server_done(SSL *s)
return ssl_do_write(s);
}
+int tls_construct_server_done(SSL *s)
+{
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_DONE, ERR_R_INTERNAL_ERROR);
+ statem_set_error(s);
+ return 0;
+ }
+
+ if (!s->s3->tmp.cert_request) {
+ if (!ssl3_digest_cached_records(s, 0)) {
+ statem_set_error(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
unsigned char *q;
int j, num;
@@ -1607,431 +1702,429 @@ int ssl3_send_server_key_exchange(SSL *s)
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
- if (s->state == SSL3_ST_SW_KEY_EXCH_A) {
- type = s->s3->tmp.new_cipher->algorithm_mkey;
- cert = s->cert;
- buf = s->init_buf;
+ type = s->s3->tmp.new_cipher->algorithm_mkey;
+ cert = s->cert;
+
+ buf = s->init_buf;
- r[0] = r[1] = r[2] = r[3] = NULL;
- n = 0;
+ r[0] = r[1] = r[2] = r[3] = NULL;
+ n = 0;
#ifndef OPENSSL_NO_PSK
- if (type & SSL_PSK) {
- /*
- * reserve size for record length and PSK identity hint
- */
- n += 2;
- if (s->cert->psk_identity_hint)
- n += strlen(s->cert->psk_identity_hint);
- }
- /* Plain PSK or RSAPSK nothing to do */
- if (type & (SSL_kPSK | SSL_kRSAPSK)) {
- } else
+ if (type & SSL_PSK) {
+ /*
+ * reserve size for record length and PSK identity hint
+ */
+ n += 2;
+ if (s->cert->psk_identity_hint)
+ n += strlen(s->cert->psk_identity_hint);
+ }
+ /* Plain PSK or RSAPSK nothing to do */
+ if (type & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else
#endif /* !OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_RSA
- if (type & SSL_kRSA) {
- rsa = cert->rsa_tmp;
- if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) {
- rsa = s->cert->rsa_tmp_cb(s,
- SSL_C_IS_EXPORT(s->s3->
- tmp.new_cipher),
- SSL_C_EXPORT_PKEYLENGTH(s->s3->
- tmp.new_cipher));
- if (rsa == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
- goto f_err;
- }
- RSA_up_ref(rsa);
- cert->rsa_tmp = rsa;
- }
+ if (type & SSL_kRSA) {
+ rsa = cert->rsa_tmp;
+ if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) {
+ rsa = s->cert->rsa_tmp_cb(s,
+ SSL_C_IS_EXPORT(s->s3->
+ tmp.new_cipher),
+ SSL_C_EXPORT_PKEYLENGTH(s->s3->
+ tmp.new_cipher));
if (rsa == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_TMP_RSA_KEY);
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
goto f_err;
}
- r[0] = rsa->n;
- r[1] = rsa->e;
- s->s3->tmp.use_rsa_tmp = 1;
- } else
+ RSA_up_ref(rsa);
+ cert->rsa_tmp = rsa;
+ }
+ if (rsa == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_TMP_RSA_KEY);
+ goto f_err;
+ }
+ r[0] = rsa->n;
+ r[1] = rsa->e;
+ s->s3->tmp.use_rsa_tmp = 1;
+ } else
#endif
#ifndef OPENSSL_NO_DH
- if (type & (SSL_kDHE | SSL_kDHEPSK)) {
- if (s->cert->dh_tmp_auto) {
- dhp = ssl_get_auto_dh(s);
- if (dhp == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto f_err;
- }
- } else
- dhp = cert->dh_tmp;
- if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
- dhp = s->cert->dh_tmp_cb(s,
- SSL_C_IS_EXPORT(s->s3->
- tmp.new_cipher),
- SSL_C_EXPORT_PKEYLENGTH(s->s3->
- tmp.new_cipher));
+ if (type & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (s->cert->dh_tmp_auto) {
+ dhp = ssl_get_auto_dh(s);
if (dhp == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_TMP_DH_KEY);
- goto f_err;
- }
- if (!ssl_security(s, SSL_SECOP_TMP_DH,
- DH_security_bits(dhp), 0, dhp)) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- SSL_R_DH_KEY_TOO_SMALL);
- goto f_err;
- }
- if (s->s3->tmp.dh != NULL) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
- goto err;
+ goto f_err;
}
+ } else
+ dhp = cert->dh_tmp;
+ if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
+ dhp = s->cert->dh_tmp_cb(s,
+ SSL_C_IS_EXPORT(s->s3->
+ tmp.new_cipher),
+ SSL_C_EXPORT_PKEYLENGTH(s->s3->
+ tmp.new_cipher));
+ if (dhp == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto f_err;
+ }
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ DH_security_bits(dhp), 0, dhp)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_DH_KEY_TOO_SMALL);
+ goto f_err;
+ }
+ if (s->s3->tmp.dh != NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- if (s->cert->dh_tmp_auto)
- dh = dhp;
- else if ((dh = DHparams_dup(dhp)) == NULL) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
+ if (s->cert->dh_tmp_auto)
+ dh = dhp;
+ else if ((dh = DHparams_dup(dhp)) == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
+ goto err;
+ }
+
+ s->s3->tmp.dh = dh;
+ if ((dhp->pub_key == NULL ||
+ dhp->priv_key == NULL ||
+ (s->options & SSL_OP_SINGLE_DH_USE))) {
+ if (!DH_generate_key(dh)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
goto err;
}
-
- s->s3->tmp.dh = dh;
- if ((dhp->pub_key == NULL ||
- dhp->priv_key == NULL ||
- (s->options & SSL_OP_SINGLE_DH_USE))) {
- if (!DH_generate_key(dh)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
- } else {
- dh->pub_key = BN_dup(dhp->pub_key);
- dh->priv_key = BN_dup(dhp->priv_key);
- if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
+ } else {
+ dh->pub_key = BN_dup(dhp->pub_key);
+ dh->priv_key = BN_dup(dhp->priv_key);
+ if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
+ goto err;
}
- r[0] = dh->p;
- r[1] = dh->g;
- r[2] = dh->pub_key;
- } else
+ }
+ r[0] = dh->p;
+ r[1] = dh->g;
+ r[2] = dh->pub_key;
+ } else
#endif
#ifndef OPENSSL_NO_EC
- if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
- const EC_GROUP *group;
-
- ecdhp = cert->ecdh_tmp;
- if (s->cert->ecdh_tmp_auto) {
- /* Get NID of appropriate shared curve */
- int nid = tls1_shared_curve(s, -2);
- if (nid != NID_undef)
- ecdhp = EC_KEY_new_by_curve_name(nid);
- } else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) {
- ecdhp = s->cert->ecdh_tmp_cb(s,
- SSL_C_IS_EXPORT(s->s3->
- tmp.new_cipher),
- SSL_C_EXPORT_PKEYLENGTH(s->
- s3->tmp.new_cipher));
- }
- if (ecdhp == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_TMP_ECDH_KEY);
- goto f_err;
- }
+ if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ const EC_GROUP *group;
- if (s->s3->tmp.ecdh != NULL) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
+ ecdhp = cert->ecdh_tmp;
+ if (s->cert->ecdh_tmp_auto) {
+ /* Get NID of appropriate shared curve */
+ int nid = tls1_shared_curve(s, -2);
+ if (nid != NID_undef)
+ ecdhp = EC_KEY_new_by_curve_name(nid);
+ } else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) {
+ ecdhp = s-