Implement DTLS client move to new state machine
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>
This commit is contained in:
parent
76af303761
commit
473483d42d
@ -1928,6 +1928,7 @@ void ERR_load_SSL_strings(void);
|
|||||||
# define SSL_F_DTLS1_SEND_SERVER_HELLO 266
|
# define SSL_F_DTLS1_SEND_SERVER_HELLO 266
|
||||||
# define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267
|
# define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267
|
||||||
# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
|
# 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_DTLS_GET_REASSEMBLED_MESSAGE 370
|
||||||
# define SSL_F_READ_STATE_MACHINE 352
|
# define SSL_F_READ_STATE_MACHINE 352
|
||||||
# define SSL_F_SSL3_ACCEPT 128
|
# define SSL_F_SSL3_ACCEPT 128
|
||||||
|
@ -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.
|
* This isn't a real handshake message so skip the processing below.
|
||||||
*/
|
*/
|
||||||
|
*len = (unsigned long)tmplen;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1102,6 +1103,19 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
|||||||
return 0;
|
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
|
* for these 2 messages, we need to
|
||||||
* ssl->enc_read_ctx re-init
|
* ssl->enc_read_ctx re-init
|
||||||
@ -1111,40 +1125,56 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
|||||||
* ssl->session->read_compression assign
|
* ssl->session->read_compression assign
|
||||||
* ssl->session->read_hash 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;
|
unsigned char *p;
|
||||||
|
|
||||||
if (s->state == a) {
|
p = (unsigned char *)s->init_buf->data;
|
||||||
p = (unsigned char *)s->init_buf->data;
|
*p++ = SSL3_MT_CCS;
|
||||||
*p++ = SSL3_MT_CCS;
|
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
||||||
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
s->init_num = DTLS1_CCS_HEADER_LENGTH;
|
||||||
s->init_num = DTLS1_CCS_HEADER_LENGTH;
|
|
||||||
|
|
||||||
if (s->version == DTLS1_BAD_VER) {
|
if (s->version == DTLS1_BAD_VER) {
|
||||||
s->d1->next_handshake_write_seq++;
|
s->d1->next_handshake_write_seq++;
|
||||||
s2n(s->d1->handshake_write_seq, p);
|
s2n(s->d1->handshake_write_seq, p);
|
||||||
s->init_num += 2;
|
s->init_num += 2;
|
||||||
}
|
|
||||||
|
|
||||||
s->init_off = 0;
|
|
||||||
|
|
||||||
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
|
|
||||||
s->d1->handshake_write_seq, 0, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->state = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SSL3_ST_CW_CHANGE_B */
|
s->init_off = 0;
|
||||||
return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC));
|
|
||||||
|
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
|
||||||
|
s->d1->handshake_write_seq, 0, 0);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
int dtls1_read_failed(SSL *s, int code)
|
||||||
{
|
{
|
||||||
if (code > 0) {
|
if (code > 0) {
|
||||||
|
@ -126,7 +126,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const SSL_METHOD *dtls1_get_client_method(int ver);
|
static const SSL_METHOD *dtls1_get_client_method(int ver);
|
||||||
|
#if 0
|
||||||
static int dtls1_get_hello_verify(SSL *s);
|
static int dtls1_get_hello_verify(SSL *s);
|
||||||
|
#endif
|
||||||
|
|
||||||
static const SSL_METHOD *dtls1_get_client_method(int ver)
|
static const SSL_METHOD *dtls1_get_client_method(int ver)
|
||||||
{
|
{
|
||||||
@ -156,6 +158,7 @@ IMPLEMENT_dtls1_meth_func(DTLS1_VERSION,
|
|||||||
dtls1_connect,
|
dtls1_connect,
|
||||||
dtls1_get_client_method, DTLSv1_2_enc_data)
|
dtls1_get_client_method, DTLSv1_2_enc_data)
|
||||||
|
|
||||||
|
#if 0
|
||||||
int dtls1_connect(SSL *s)
|
int dtls1_connect(SSL *s)
|
||||||
{
|
{
|
||||||
BUF_MEM *buf = NULL;
|
BUF_MEM *buf = NULL;
|
||||||
@ -785,13 +788,16 @@ int dtls1_connect(SSL *s)
|
|||||||
cb(s, SSL_CB_CONNECT_EXIT, ret);
|
cb(s, SSL_CB_CONNECT_EXIT, ret);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int dtls1_get_hello_verify(SSL *s)
|
static int dtls1_get_hello_verify(SSL *s)
|
||||||
{
|
{
|
||||||
int n, al, ok = 0;
|
int n, al, ok = 0;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
unsigned int cookie_len;
|
unsigned int cookie_len;
|
||||||
|
|
||||||
|
/* TODO: CHECK first_packet handling!!! */
|
||||||
s->first_packet = 1;
|
s->first_packet = 1;
|
||||||
n = s->method->ssl_get_message(s,
|
n = s->method->ssl_get_message(s,
|
||||||
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
|
DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
|
||||||
@ -801,12 +807,14 @@ static int dtls1_get_hello_verify(SSL *s)
|
|||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return ((int)n);
|
return ((int)n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
|
enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, unsigned long n)
|
||||||
s->d1->send_cookie = 0;
|
{
|
||||||
s->s3->tmp.reuse_message = 1;
|
int al;
|
||||||
return (1);
|
unsigned char *data;
|
||||||
}
|
unsigned int cookie_len;
|
||||||
|
|
||||||
data = (unsigned char *)s->init_msg;
|
data = (unsigned char *)s->init_msg;
|
||||||
data += 2;
|
data += 2;
|
||||||
@ -820,11 +828,9 @@ static int dtls1_get_hello_verify(SSL *s)
|
|||||||
memcpy(s->d1->cookie, data, cookie_len);
|
memcpy(s->d1->cookie, data, cookie_len);
|
||||||
s->d1->cookie_len = cookie_len;
|
s->d1->cookie_len = cookie_len;
|
||||||
|
|
||||||
s->d1->send_cookie = 1;
|
return MSG_PROCESS_FINISHED_READING;
|
||||||
return 1;
|
|
||||||
|
|
||||||
f_err:
|
f_err:
|
||||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||||
s->state = SSL_ST_ERR;
|
statem_set_error(s);
|
||||||
return -1;
|
return MSG_PROCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -461,8 +461,15 @@ enum WORK_STATE tls_finish_handshake(SSL *s, enum WORK_STATE wst)
|
|||||||
|
|
||||||
/* clean a few things up */
|
/* clean a few things up */
|
||||||
ssl3_cleanup_key_block(s);
|
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);
|
ssl_free_wbio_buffer(s);
|
||||||
|
|
||||||
|
@ -465,6 +465,7 @@ int tls_construct_client_hello(SSL *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
int ssl3_get_server_hello(SSL *s)
|
int ssl3_get_server_hello(SSL *s)
|
||||||
{
|
{
|
||||||
int ok, al;
|
int ok, al;
|
||||||
@ -509,6 +510,7 @@ int ssl3_get_server_hello(SSL *s)
|
|||||||
s->state = SSL_ST_ERR;
|
s->state = SSL_ST_ERR;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, unsigned long n)
|
enum MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, unsigned long n)
|
||||||
{
|
{
|
||||||
@ -1921,7 +1923,14 @@ enum MSG_PROCESS_RETURN tls_process_server_done(SSL *s, unsigned long n)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
int ssl3_send_client_key_exchange(SSL *s)
|
||||||
@ -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);
|
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
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;
|
return 1;
|
||||||
err:
|
err:
|
||||||
OPENSSL_clear_free(pms, pmslen);
|
OPENSSL_clear_free(pms, pmslen);
|
||||||
|
@ -112,6 +112,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
|
|||||||
{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),
|
{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),
|
||||||
"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_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),
|
{ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
|
||||||
"DTLS_GET_REASSEMBLED_MESSAGE"},
|
"DTLS_GET_REASSEMBLED_MESSAGE"},
|
||||||
{ERR_FUNC(SSL_F_READ_STATE_MACHINE), "READ_STATE_MACHINE"},
|
{ERR_FUNC(SSL_F_READ_STATE_MACHINE), "READ_STATE_MACHINE"},
|
||||||
|
@ -1555,7 +1555,6 @@ typedef struct hm_fragment_st {
|
|||||||
} hm_fragment;
|
} hm_fragment;
|
||||||
|
|
||||||
typedef struct dtls1_state_st {
|
typedef struct dtls1_state_st {
|
||||||
unsigned int send_cookie;
|
|
||||||
unsigned char cookie[DTLS1_COOKIE_LENGTH];
|
unsigned char cookie[DTLS1_COOKIE_LENGTH];
|
||||||
unsigned int cookie_len;
|
unsigned int cookie_len;
|
||||||
|
|
||||||
@ -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_setup_key_block(SSL *s);
|
||||||
__owur int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b);
|
__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 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);
|
__owur int ssl3_change_cipher_state(SSL *s, int which);
|
||||||
void ssl3_cleanup_key_block(SSL *s);
|
void ssl3_cleanup_key_block(SSL *s);
|
||||||
__owur int ssl3_do_write(SSL *s, int type);
|
__owur int ssl3_do_write(SSL *s, int type);
|
||||||
@ -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 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 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 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 int ssl3_num_ciphers(void);
|
||||||
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
|
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
|
||||||
int ssl3_renegotiate(SSL *ssl);
|
int ssl3_renegotiate(SSL *ssl);
|
||||||
@ -2194,6 +2195,8 @@ __owur int ssl3_check_cert_and_algorithm(SSL *s);
|
|||||||
__owur int ssl3_send_next_proto(SSL *s);
|
__owur int ssl3_send_next_proto(SSL *s);
|
||||||
__owur int tls_construct_next_proto(SSL *s);
|
__owur int tls_construct_next_proto(SSL *s);
|
||||||
# endif
|
# endif
|
||||||
|
__owur enum MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s,
|
||||||
|
unsigned long n);
|
||||||
|
|
||||||
int dtls1_client_hello(SSL *s);
|
int dtls1_client_hello(SSL *s);
|
||||||
|
|
||||||
|
113
ssl/statem.c
113
ssl/statem.c
@ -151,6 +151,11 @@ int ssl3_connect(SSL *s) {
|
|||||||
return state_machine(s, 0);
|
return state_machine(s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dtls1_connect(SSL *s)
|
||||||
|
{
|
||||||
|
return state_machine(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
|
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
|
||||||
* MSG_FLOW_RENEGOTIATE state and finish in MSG_FLOW_FINISHED. Valid states and
|
* MSG_FLOW_RENEGOTIATE state and finish in MSG_FLOW_FINISHED. Valid states and
|
||||||
@ -207,6 +212,17 @@ static int state_machine(SSL *s, int server) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_SCTP
|
||||||
|
if (SSL_IS_DTLS(s)) {
|
||||||
|
/*
|
||||||
|
* 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
|
#ifndef OPENSSL_NO_HEARTBEATS
|
||||||
/*
|
/*
|
||||||
* If we're awaiting a HeartbeatResponse, pretend we already got and
|
* If we're awaiting a HeartbeatResponse, pretend we already got and
|
||||||
@ -259,10 +275,12 @@ static int state_machine(SSL *s, int server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->version != TLS_ANY_VERSION &&
|
if (!SSL_IS_DTLS(s)) {
|
||||||
!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
|
if (s->version != TLS_ANY_VERSION &&
|
||||||
SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
|
!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
|
||||||
goto end;
|
SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server)
|
if (server)
|
||||||
@ -380,6 +398,18 @@ static int state_machine(SSL *s, int server) {
|
|||||||
|
|
||||||
end:
|
end:
|
||||||
s->in_handshake--;
|
s->in_handshake--;
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_SCTP
|
||||||
|
if (SSL_IS_DTLS(s)) {
|
||||||
|
/*
|
||||||
|
* Notify SCTP BIO socket to leave handshake mode and allow 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
|
||||||
|
|
||||||
BUF_MEM_free(buf);
|
BUF_MEM_free(buf);
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
if (server)
|
if (server)
|
||||||
@ -765,14 +795,11 @@ int statem_app_data_allowed(SSL *s)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the old check for code still using the old state machine. This
|
* This is the old check for code still using the old state machine. This
|
||||||
* will be removed by later commits
|
* will be removed by a later commit
|
||||||
*/
|
*/
|
||||||
if (((s->state & SSL_ST_CONNECT) && SSL_IS_DTLS(s) &&
|
if ((s->state & SSL_ST_ACCEPT) &&
|
||||||
(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_SW_HELLO_REQ_A) &&
|
||||||
(s->state >= SSL3_ST_SR_CLNT_HELLO_A))
|
(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
|
||||||
)
|
)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -883,7 +910,10 @@ static int client_read_transition(SSL *s, int mt)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(s->s3->tmp.new_cipher->algorithm_auth
|
if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
|
||||||
|
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
|
||||||
|
return 1;
|
||||||
|
} else if (!(s->s3->tmp.new_cipher->algorithm_auth
|
||||||
& (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
|
& (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
|
||||||
if (mt == SSL3_MT_CERTIFICATE) {
|
if (mt == SSL3_MT_CERTIFICATE) {
|
||||||
st->hand_state = TLS_ST_CR_CERT;
|
st->hand_state = TLS_ST_CR_CERT;
|
||||||
@ -1015,6 +1045,10 @@ static enum WRITE_TRAN client_write_transition(SSL *s)
|
|||||||
*/
|
*/
|
||||||
return WRITE_TRAN_FINISHED;
|
return WRITE_TRAN_FINISHED;
|
||||||
|
|
||||||
|
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||||
|
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||||
|
return WRITE_TRAN_CONTINUE;
|
||||||
|
|
||||||
case TLS_ST_CR_SRVR_DONE:
|
case TLS_ST_CR_SRVR_DONE:
|
||||||
if (s->s3->tmp.cert_req)
|
if (s->s3->tmp.cert_req)
|
||||||
st->hand_state = TLS_ST_CW_CERT;
|
st->hand_state = TLS_ST_CW_CERT;
|
||||||
@ -1055,7 +1089,7 @@ static enum WRITE_TRAN client_write_transition(SSL *s)
|
|||||||
#if defined(OPENSSL_NO_NEXTPROTONEG)
|
#if defined(OPENSSL_NO_NEXTPROTONEG)
|
||||||
st->hand_state = TLS_ST_CW_FINISHED;
|
st->hand_state = TLS_ST_CW_FINISHED;
|
||||||
#else
|
#else
|
||||||
if (s->s3->next_proto_neg_seen)
|
if (!SSL_IS_DTLS(s) && s->s3->next_proto_neg_seen)
|
||||||
st->hand_state = TLS_ST_CW_NEXT_PROTO;
|
st->hand_state = TLS_ST_CW_NEXT_PROTO;
|
||||||
else
|
else
|
||||||
st->hand_state = TLS_ST_CW_FINISHED;
|
st->hand_state = TLS_ST_CW_FINISHED;
|
||||||
@ -1106,11 +1140,31 @@ static enum WORK_STATE client_pre_work(SSL *s, enum WORK_STATE wst)
|
|||||||
switch(st->hand_state) {
|
switch(st->hand_state) {
|
||||||
case TLS_ST_CW_CLNT_HELLO:
|
case TLS_ST_CW_CLNT_HELLO:
|
||||||
s->shutdown = 0;
|
s->shutdown = 0;
|
||||||
|
if (SSL_IS_DTLS(s)) {
|
||||||
|
/* every DTLS ClientHello resets Finished MAC */
|
||||||
|
ssl3_init_finished_mac(s);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLS_ST_CW_CERT:
|
case TLS_ST_CW_CERT:
|
||||||
return tls_prepare_client_certificate(s, wst);
|
return tls_prepare_client_certificate(s, wst);
|
||||||
|
|
||||||
|
case TLS_ST_CW_CHANGE:
|
||||||
|
if (SSL_IS_DTLS(s)) {
|
||||||
|
if (s->hit) {
|
||||||
|
/*
|
||||||
|
* We're into the last flight so we don't retransmit these
|
||||||
|
* messages unless we need to.
|
||||||
|
*/
|
||||||
|
st->use_timer = 0;
|
||||||
|
}
|
||||||
|
#ifndef OPENSSL_NO_SCTP
|
||||||
|
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||||
|
return dtls_wait_for_dry(s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return WORK_FINISHED_CONTINUE;
|
||||||
|
|
||||||
case TLS_ST_OK:
|
case TLS_ST_OK:
|
||||||
return tls_finish_handshake(s, wst);
|
return tls_finish_handshake(s, wst);
|
||||||
|
|
||||||
@ -1134,9 +1188,24 @@ static enum WORK_STATE client_post_work(SSL *s, enum WORK_STATE wst)
|
|||||||
|
|
||||||
switch(st->hand_state) {
|
switch(st->hand_state) {
|
||||||
case TLS_ST_CW_CLNT_HELLO:
|
case TLS_ST_CW_CLNT_HELLO:
|
||||||
/* turn on buffering for the next lot of output */
|
if (SSL_IS_DTLS(s) && s->d1->cookie_len > 0 && statem_flush(s) != 1)
|
||||||
if (s->bbio != s->wbio)
|
return WORK_MORE_A;
|
||||||
s->wbio = BIO_push(s->bbio, s->wbio);
|
#ifndef OPENSSL_NO_SCTP
|
||||||
|
/* Disable buffering for SCTP */
|
||||||
|
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* turn on buffering for the next lot of output
|
||||||
|
*/
|
||||||
|
if (s->bbio != s->wbio)
|
||||||
|
s->wbio = BIO_push(s->bbio, s->wbio);
|
||||||
|
#ifndef OPENSSL_NO_SCTP
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (SSL_IS_DTLS(s)) {
|
||||||
|
/* Treat the next message as the first packet */
|
||||||
|
s->first_packet = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLS_ST_CW_KEY_EXCH:
|
case TLS_ST_CW_KEY_EXCH:
|
||||||
@ -1179,7 +1248,7 @@ static enum WORK_STATE client_post_work(SSL *s, enum WORK_STATE wst)
|
|||||||
|
|
||||||
case TLS_ST_CW_FINISHED:
|
case TLS_ST_CW_FINISHED:
|
||||||
#ifndef OPENSSL_NO_SCTP
|
#ifndef OPENSSL_NO_SCTP
|
||||||
if (SSL_IS_DTLS(s) && s->hit == 0) {
|
if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) {
|
||||||
/*
|
/*
|
||||||
* Change to new shared key of SCTP-Auth, will be ignored if
|
* Change to new shared key of SCTP-Auth, will be ignored if
|
||||||
* no SCTP used.
|
* no SCTP used.
|
||||||
@ -1228,7 +1297,10 @@ static int client_construct_message(SSL *s)
|
|||||||
return tls_construct_client_verify(s);
|
return tls_construct_client_verify(s);
|
||||||
|
|
||||||
case TLS_ST_CW_CHANGE:
|
case TLS_ST_CW_CHANGE:
|
||||||
return tls_construct_change_cipher_spec(s);
|
if (SSL_IS_DTLS(s))
|
||||||
|
return dtls_construct_change_cipher_spec(s);
|
||||||
|
else
|
||||||
|
return tls_construct_change_cipher_spec(s);
|
||||||
|
|
||||||
#if !defined(OPENSSL_NO_NEXTPROTONEG)
|
#if !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||||
case TLS_ST_CW_NEXT_PROTO:
|
case TLS_ST_CW_NEXT_PROTO:
|
||||||
@ -1250,6 +1322,7 @@ static int client_construct_message(SSL *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The spec allows for a longer length than this, but we limit it */
|
/* The spec allows for a longer length than this, but we limit it */
|
||||||
|
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
|
||||||
#define SERVER_HELLO_MAX_LENGTH 20000
|
#define SERVER_HELLO_MAX_LENGTH 20000
|
||||||
#define SERVER_KEY_EXCH_MAX_LENGTH 102400
|
#define SERVER_KEY_EXCH_MAX_LENGTH 102400
|
||||||
#define SERVER_HELLO_DONE_MAX_LENGTH 0
|
#define SERVER_HELLO_DONE_MAX_LENGTH 0
|
||||||
@ -1269,6 +1342,9 @@ static unsigned long client_max_message_size(SSL *s)
|
|||||||
case TLS_ST_CR_SRVR_HELLO:
|
case TLS_ST_CR_SRVR_HELLO:
|
||||||
return SERVER_HELLO_MAX_LENGTH;
|
return SERVER_HELLO_MAX_LENGTH;
|
||||||
|
|
||||||
|
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||||
|
return HELLO_VERIFY_REQUEST_MAX_LENGTH;
|
||||||
|
|
||||||
case TLS_ST_CR_CERT:
|
case TLS_ST_CR_CERT:
|
||||||
return s->max_cert_list;
|
return s->max_cert_list;
|
||||||
|
|
||||||
@ -1312,6 +1388,9 @@ static enum MSG_PROCESS_RETURN client_process_message(SSL *s, unsigned long len)
|
|||||||
case TLS_ST_CR_SRVR_HELLO:
|
case TLS_ST_CR_SRVR_HELLO:
|
||||||
return tls_process_server_hello(s, len);
|
return tls_process_server_hello(s, len);
|
||||||
|
|
||||||
|
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||||
|
return dtls_process_hello_verify(s, len);
|
||||||
|
|
||||||
case TLS_ST_CR_CERT:
|
case TLS_ST_CR_CERT:
|
||||||
return tls_process_server_certificate(s, len);
|
return tls_process_server_certificate(s, len);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user