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>
This commit is contained in:
Matt Caswell 2015-07-29 14:08:49 +01:00
parent f8e0a55738
commit b9908bf9b8
5 changed files with 1350 additions and 1057 deletions

View file

@ -2101,8 +2101,24 @@ void ERR_load_SSL_strings(void);
# define SSL_F_TLS1_PROCESS_HEARTBEAT 341
# define SSL_F_TLS1_SETUP_KEY_BLOCK 211
# define SSL_F_TLS1_SET_SERVER_SIGALGS 335
# define SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK 354
# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 355
# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 356
# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 357
# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 358
# define SSL_F_TLS_CONSTRUCT_FINISHED 359
# define SSL_F_TLS_GET_MESSAGE_BODY 351
# define SSL_F_TLS_GET_MESSAGE_HEADER 350
# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360
# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 361
# define SSL_F_TLS_PROCESS_CERT_STATUS 362
# define SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC 363
# define SSL_F_TLS_PROCESS_FINISHED 364
# define SSL_F_TLS_PROCESS_KEY_EXCHANGE 365
# define SSL_F_TLS_PROCESS_NEW_SESSION_TICKET 366
# define SSL_F_TLS_PROCESS_SERVER_CERTIFICATE 367
# define SSL_F_TLS_PROCESS_SERVER_DONE 368
# define SSL_F_TLS_PROCESS_SERVER_HELLO 369
# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 220
/* Reason codes. */

View file

@ -158,37 +158,9 @@ int ssl3_do_write(SSL *s, int type)
int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
{
unsigned char *p;
int i;
unsigned long l;
if (s->state == a) {
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;
/*
* 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);
if (tls_construct_finished(s, sender, slen) == 0) {
statem_set_error(s);
return -1;
}
s->state = b;
@ -198,6 +170,44 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
return ssl_do_write(s);
}
int tls_construct_finished(SSL *s, const char *sender, int slen)
{
unsigned char *p;
int i;
unsigned long l;
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;
/*
* 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_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
@ -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;

File diff suppressed because it is too large Load diff

View file

@ -333,8 +333,33 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_TLS1_PROCESS_HEARTBEAT), "tls1_process_heartbeat"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "tls1_setup_key_block"},
{ERR_FUNC(SSL_F_TLS1_SET_SERVER_SIGALGS), "tls1_set_server_sigalgs"},
{ERR_FUNC(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK),
"tls_client_key_exchange_post_work"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE),
"tls_construct_client_certificate"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO), "tls_construct_client_hello"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE),
"tls_construct_client_key_exchange"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY),
"tls_construct_client_verify"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_FINISHED), "tls_construct_finished"},
{ERR_FUNC(SSL_F_TLS_GET_MESSAGE_BODY), "tls_get_message_body"},
{ERR_FUNC(SSL_F_TLS_GET_MESSAGE_HEADER), "tls_get_message_header"},
{ERR_FUNC(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE),
"tls_prepare_client_certificate"},
{ERR_FUNC(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST),
"tls_process_certificate_request"},
{ERR_FUNC(SSL_F_TLS_PROCESS_CERT_STATUS), "tls_process_cert_status"},
{ERR_FUNC(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC),
"tls_process_change_cipher_spec"},
{ERR_FUNC(SSL_F_TLS_PROCESS_FINISHED), "tls_process_finished"},
{ERR_FUNC(SSL_F_TLS_PROCESS_KEY_EXCHANGE), "tls_process_key_exchange"},
{ERR_FUNC(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET),
"tls_process_new_session_ticket"},
{ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE),
"tls_process_server_certificate"},
{ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_DONE), "tls_process_server_done"},
{ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_HELLO), "tls_process_server_hello"},
{ERR_FUNC(SSL_F_USE_CERTIFICATE_CHAIN_FILE), "use_certificate_chain_file"},
{0, NULL}
};

View file

@ -2053,8 +2053,12 @@ __owur int ssl3_send_newsession_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 ssl3_change_cipher_state(SSL *s, int which);
void ssl3_cleanup_key_block(SSL *s);
__owur int ssl3_do_write(SSL *s, int type);
@ -2066,6 +2070,7 @@ __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 int ssl3_num_ciphers(void);
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
int ssl3_renegotiate(SSL *ssl);
@ -2145,20 +2150,41 @@ void dtls1_hm_fragment_free(hm_fragment *frag);
/* some client-only functions */
__owur int ssl3_client_hello(SSL *s);
__owur int tls_construct_client_hello(SSL *s);
__owur int ssl3_get_server_hello(SSL *s);
__owur int ssl3_get_certificate_request(SSL *s);
__owur int ssl3_get_new_session_ticket(SSL *s);
__owur int ssl3_get_cert_status(SSL *s);
__owur int ssl3_get_server_done(SSL *s);
__owur enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s,
unsigned long n);
__owur enum MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s,
unsigned long n);
__owur enum MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s,
unsigned long n);
__owur enum MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, unsigned long n);
__owur enum MSG_PROCESS_RETURN tls_process_server_done(SSL *s, unsigned long n);
__owur int ssl3_send_client_verify(SSL *s);
__owur int ssl3_send_client_certificate(SSL *s);
__owur int tls_construct_client_verify(SSL *s);
__owur int tls_construct_client_verify(SSL *s);
int ssl3_send_client_certificate(SSL *s);
__owur enum WORK_STATE tls_prepare_client_certificate(SSL *s,
enum WORK_STATE wst);
__owur int tls_construct_client_certificate(SSL *s);
__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
__owur int ssl3_send_client_key_exchange(SSL *s);
__owur int tls_construct_client_key_exchange(SSL *s);
__owur int tls_client_key_exchange_post_work(SSL *s);
__owur int ssl3_get_key_exchange(SSL *s);
__owur int ssl3_get_server_certificate(SSL *s);
__owur enum MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s,
unsigned long n);
__owur enum MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s,
unsigned long n);
__owur int ssl3_check_cert_and_algorithm(SSL *s);
# ifndef OPENSSL_NO_NEXTPROTONEG
__owur int ssl3_send_next_proto(SSL *s);
__owur int tls_construct_next_proto(SSL *s);
# endif
int dtls1_client_hello(SSL *s);
@ -2166,6 +2192,10 @@ int dtls1_client_hello(SSL *s);
/* 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 ssl3_send_server_key_exchange(SSL *s);
__owur int ssl3_send_certificate_request(SSL *s);
@ -2173,8 +2203,14 @@ __owur int ssl3_send_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
__owur int tls1_new(SSL *s);