Skip to content

Commit

Permalink
Implement DTLS client move to new state machine
Browse files Browse the repository at this point in the history
Move all DTLS client side processing into the new state machine code. A
subsequent commit will clean up the old dead code.

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
  • Loading branch information
mattcaswell committed Oct 30, 2015
1 parent 76af303 commit 473483d
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 54 deletions.
1 change: 1 addition & 0 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_SEND_SERVER_HELLO 266
# define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267
# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 371
# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370
# define SSL_F_READ_STATE_MACHINE 352
# define SSL_F_SSL3_ACCEPT 128
Expand Down
76 changes: 53 additions & 23 deletions ssl/d1_both.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ int dtls_get_message(SSL *s, int *mt, unsigned long *len)
/*
* This isn't a real handshake message so skip the processing below.
*/
*len = (unsigned long)tmplen;
return 1;
}

Expand Down Expand Up @@ -1102,6 +1103,19 @@ 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
Expand All @@ -1111,39 +1125,55 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
* ssl->session->read_compression assign
* ssl->session->read_hash assign
*/
int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
int dtls_construct_change_cipher_spec(SSL *s)
{
unsigned char *p;

if (s->state == a) {
p = (unsigned char *)s->init_buf->data;
*p++ = SSL3_MT_CCS;
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
s->init_num = DTLS1_CCS_HEADER_LENGTH;

if (s->version == DTLS1_BAD_VER) {
s->d1->next_handshake_write_seq++;
s2n(s->d1->handshake_write_seq, p);
s->init_num += 2;
}
p = (unsigned char *)s->init_buf->data;
*p++ = SSL3_MT_CCS;
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
s->init_num = DTLS1_CCS_HEADER_LENGTH;

s->init_off = 0;
if (s->version == DTLS1_BAD_VER) {
s->d1->next_handshake_write_seq++;
s2n(s->d1->handshake_write_seq, p);
s->init_num += 2;
}

dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
s->d1->handshake_write_seq, 0, 0);
s->init_off = 0;

/* buffer the message to handle re-xmits */
if (!dtls1_buffer_message(s, 1)) {
SSLerr(SSL_F_DTLS1_SEND_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
return -1;
}
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
s->d1->handshake_write_seq, 0, 0);

s->state = b;
/* buffer the message to handle re-xmits */
if (!dtls1_buffer_message(s, 1)) {
SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
return 0;
}

/* SSL3_ST_CW_CHANGE_B */
return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC));
return 1;
}

#ifndef OPENSSL_NO_SCTP
enum WORK_STATE dtls_wait_for_dry(SSL *s)
{
int ret;

/* read app data until dry event */
ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
if (ret < 0)
return WORK_ERROR;

if (ret == 0) {
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));
return WORK_MORE_A;
}
return WORK_FINISHED_CONTINUE;
}
#endif

int dtls1_read_failed(SSL *s, int code)
{
Expand Down
26 changes: 16 additions & 10 deletions ssl/d1_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@
#endif

static const SSL_METHOD *dtls1_get_client_method(int ver);
#if 0
static int dtls1_get_hello_verify(SSL *s);
#endif

static const SSL_METHOD *dtls1_get_client_method(int ver)
{
Expand Down Expand Up @@ -156,6 +158,7 @@ IMPLEMENT_dtls1_meth_func(DTLS1_VERSION,
dtls1_connect,
dtls1_get_client_method, DTLSv1_2_enc_data)

#if 0
int dtls1_connect(SSL *s)
{
BUF_MEM *buf = NULL;
Expand Down Expand Up @@ -785,13 +788,16 @@ int dtls1_connect(SSL *s)
cb(s, SSL_CB_CONNECT_EXIT, ret);
return (ret);
}
#endif

#if 0
static int dtls1_get_hello_verify(SSL *s)
{
int n, al, ok = 0;
unsigned char *data;
unsigned int cookie_len;

/* TODO: CHECK first_packet handling!!! */
s->first_packet = 1;
n = s->method->ssl_get_message(s,
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
Expand All @@ -801,12 +807,14 @@ static int dtls1_get_hello_verify(SSL *s)

if (!ok)
return ((int)n);
}
#endif

if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
s->d1->send_cookie = 0;
s->s3->tmp.reuse_message = 1;
return (1);
}
enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, unsigned long n)
{
int al;
unsigned char *data;
unsigned int cookie_len;

data = (unsigned char *)s->init_msg;
data += 2;
Expand All @@ -820,11 +828,9 @@ static int dtls1_get_hello_verify(SSL *s)
memcpy(s->d1->cookie, data, cookie_len);
s->d1->cookie_len = cookie_len;

s->d1->send_cookie = 1;
return 1;

return MSG_PROCESS_FINISHED_READING;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
s->state = SSL_ST_ERR;
return -1;
statem_set_error(s);
return MSG_PROCESS_ERROR;
}
11 changes: 9 additions & 2 deletions ssl/s3_both.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,15 @@ enum WORK_STATE tls_finish_handshake(SSL *s, enum WORK_STATE wst)

/* clean a few things up */
ssl3_cleanup_key_block(s);
BUF_MEM_free(s->init_buf);
s->init_buf = NULL;

if (!SSL_IS_DTLS(s)) {
/*
* We don't do this in DTLS because we may still need the init_buf
* in case there are any unexpected retransmits
*/
BUF_MEM_free(s->init_buf);
s->init_buf = NULL;
}

ssl_free_wbio_buffer(s);

Expand Down
34 changes: 33 additions & 1 deletion ssl/s3_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ int tls_construct_client_hello(SSL *s)
return 0;
}

#if 0
int ssl3_get_server_hello(SSL *s)
{
int ok, al;
Expand Down Expand Up @@ -509,6 +510,7 @@ int ssl3_get_server_hello(SSL *s)
s->state = SSL_ST_ERR;
return (-1);
}
#endif

enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, unsigned long n)
{
Expand Down Expand Up @@ -1921,7 +1923,14 @@ enum MSG_PROCESS_RETURN tls_process_server_done(SSL *s, unsigned long n)
}
#endif

return MSG_PROCESS_FINISHED_READING;
#ifndef OPENSSL_NO_SCTP
/* Only applies to renegotiation */
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))
&& s->renegotiate != 0)
return MSG_PROCESS_CONTINUE_PROCESSING;
else
#endif
return MSG_PROCESS_FINISHED_READING;
}

int ssl3_send_client_key_exchange(SSL *s)
Expand Down Expand Up @@ -2554,6 +2563,29 @@ int tls_client_key_exchange_post_work(SSL *s)
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
goto err;
}

#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s)) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];

/*
* 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)
goto err;

BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
#endif

return 1;
err:
OPENSSL_clear_free(pms, pmslen);
Expand Down
2 changes: 2 additions & 0 deletions ssl/ssl_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),
"dtls1_send_server_key_exchange"},
{ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES), "dtls1_write_app_data_bytes"},
{ERR_FUNC(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC),
"dtls_construct_change_cipher_spec"},
{ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
"DTLS_GET_REASSEMBLED_MESSAGE"},
{ERR_FUNC(SSL_F_READ_STATE_MACHINE), "READ_STATE_MACHINE"},
Expand Down
5 changes: 4 additions & 1 deletion ssl/ssl_locl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1555,7 +1555,6 @@ typedef struct hm_fragment_st {
} hm_fragment;

typedef struct dtls1_state_st {
unsigned int send_cookie;
unsigned char cookie[DTLS1_COOKIE_LENGTH];
unsigned int cookie_len;

Expand Down Expand Up @@ -2062,6 +2061,7 @@ __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);
void ssl3_cleanup_key_block(SSL *s);
__owur int ssl3_do_write(SSL *s, int type);
Expand All @@ -2075,6 +2075,7 @@ __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);
__owur int ssl3_num_ciphers(void);
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
int ssl3_renegotiate(SSL *ssl);
Expand Down Expand Up @@ -2194,6 +2195,8 @@ __owur int ssl3_check_cert_and_algorithm(SSL *s);
__owur int ssl3_send_next_proto(SSL *s);
__owur int tls_construct_next_proto(SSL *s);
# endif
__owur enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s,
unsigned long n);

int dtls1_client_hello(SSL *s);

Expand Down

0 comments on commit 473483d

Please sign in to comment.