diff options
author | Matt Caswell <matt@openssl.org> | 2017-02-08 09:15:22 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2017-02-17 10:28:00 +0000 |
commit | 44c04a2e063715abdf2db095827261456fada74a (patch) | |
tree | 0fd352dfec7c296d387cc83f4c993843fb0e2f1f /ssl | |
parent | 25b802bb855285bb3a799014f3669f73f4d11871 (diff) |
Provide a function to send a KeyUpdate message
This implements the server side KeyUpdate sending capability as well.
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2609)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/ssl_err.c | 5 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 41 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 2 | ||||
-rw-r--r-- | ssl/statem/statem_lib.c | 13 | ||||
-rw-r--r-- | ssl/statem/statem_locl.h | 1 | ||||
-rw-r--r-- | ssl/statem/statem_srvr.c | 19 |
6 files changed, 67 insertions, 14 deletions
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index cea604072a..2d9efbb06a 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -179,6 +179,7 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL_GET_SERVER_CERT_INDEX), "ssl_get_server_cert_index"}, {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "ssl_get_sign_pkey"}, {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "ssl_init_wbio_buffer"}, + {ERR_FUNC(SSL_F_SSL_KEY_UPDATE), "SSL_key_update"}, {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"}, {ERR_FUNC(SSL_F_SSL_LOG_MASTER_SECRET), "ssl_log_master_secret"}, {ERR_FUNC(SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE), @@ -201,6 +202,7 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL_PEEK_EX), "SSL_peek_ex"}, {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"}, {ERR_FUNC(SSL_F_SSL_READ_EX), "SSL_read_ex"}, + {ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"}, {ERR_FUNC(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT), "ssl_scan_clienthello_tlsext"}, {ERR_FUNC(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT), @@ -333,6 +335,7 @@ static ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_hello_request"}, {ERR_FUNC(SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST), "tls_construct_hello_retry_request"}, + {ERR_FUNC(SSL_F_TLS_CONSTRUCT_KEY_UPDATE), "tls_construct_key_update"}, {ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET), "tls_construct_new_session_ticket"}, {ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEXT_PROTO), "tls_construct_next_proto"}, @@ -568,6 +571,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { "invalid configuration name"}, {ERR_REASON(SSL_R_INVALID_CT_VALIDATION_TYPE), "invalid ct validation type"}, + {ERR_REASON(SSL_R_INVALID_KEY_UPDATE_TYPE), "invalid key update type"}, {ERR_REASON(SSL_R_INVALID_NULL_CMD_NAME), "invalid null cmd name"}, {ERR_REASON(SSL_R_INVALID_SEQUENCE_NUMBER), "invalid sequence number"}, {ERR_REASON(SSL_R_INVALID_SERVERINFO_DATA), "invalid serverinfo data"}, @@ -715,6 +719,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_SSL_SESSION_ID_TOO_LONG), "ssl session id too long"}, {ERR_REASON(SSL_R_SSL_SESSION_VERSION_MISMATCH), "ssl session version mismatch"}, + {ERR_REASON(SSL_R_STILL_IN_INIT), "still in init"}, {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED), "tlsv1 alert access denied"}, {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR), "tlsv1 alert decode error"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 1642215ce4..0ca04bd96e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -471,6 +471,8 @@ int SSL_clear(SSL *s) clear_ciphers(s); s->first_packet = 0; + s->key_update = SSL_KEY_UPDATE_NONE; + /* Reset DANE verification result state */ s->dane.mdpth = -1; s->dane.pdpth = -1; @@ -639,6 +641,8 @@ SSL *SSL_new(SSL_CTX *ctx) s->method = ctx->method; + s->key_update = SSL_KEY_UPDATE_NONE; + if (!s->method->ssl_new(s)) goto err; @@ -1714,14 +1718,37 @@ int SSL_shutdown(SSL *s) } } +int SSL_key_update(SSL *s, SSL_KEY_UPDATE updatetype) +{ + if (!SSL_IS_TLS13(s)) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION); + return 0; + } + + if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED + && updatetype != SSL_KEY_UPDATE_REQUESTED) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE); + return 0; + } + + if (!SSL_is_init_finished(s)) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT); + return 0; + } + + ossl_statem_set_in_init(s, 1); + + s->key_update = updatetype; + + return 1; +} + int SSL_renegotiate(SSL *s) { - /* - * TODO(TLS1.3): Return an error for now. Perhaps we should do a KeyUpdate - * instead when we support that? - */ - if (SSL_IS_TLS13(s)) + if (SSL_IS_TLS13(s)) { + SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION); return 0; + } if (s->renegotiate == 0) s->renegotiate = 1; @@ -1733,10 +1760,6 @@ int SSL_renegotiate(SSL *s) int SSL_renegotiate_abbreviated(SSL *s) { - /* - * TODO(TLS1.3): Return an error for now. Perhaps we should do a KeyUpdate - * instead when we support that? - */ if (SSL_IS_TLS13(s)) return 0; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6f838778a6..8a3f573bf9 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1172,6 +1172,8 @@ struct ssl_st { * (i.e. not just sending a HelloRequest) */ int renegotiate; + /* If sending a KeyUpdate is pending */ + SSL_KEY_UPDATE key_update; # ifndef OPENSSL_NO_SRP /* ctx for SRP authentication */ SRP_CTX srp_ctx; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index ed07266c01..fa7387a5ad 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -495,6 +495,19 @@ int tls_construct_finished(SSL *s, WPACKET *pkt) return 0; } +int tls_construct_key_update(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, s->key_update)) { + SSLerr(SSL_F_TLS_CONSTRUCT_KEY_UPDATE, ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + err: + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return 0; +} + #ifndef OPENSSL_NO_NEXTPROTONEG /* * ssl3_take_mac calculates the Finished MAC for the handshakes messages seen diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h index fa13a26126..96ddac2cb6 100644 --- a/ssl/statem/statem_locl.h +++ b/ssl/statem/statem_locl.h @@ -111,6 +111,7 @@ __owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); __owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); __owur int tls_construct_finished(SSL *s, WPACKET *pkt); +__owur int tls_construct_key_update(SSL *s, WPACKET *pkt); __owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs); __owur WORK_STATE dtls_wait_for_dry(SSL *s); diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 2330bde360..4cdd6c9492 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -394,11 +394,6 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) OSSL_STATEM *st = &s->statem; /* - * TODO(TLS1.3): This is still based on the TLSv1.2 state machine. Over time - * we will update this to look more like real TLSv1.3 - */ - - /* * No case for TLS_ST_BEFORE, because at that stage we have not negotiated * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition() */ @@ -408,6 +403,13 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) /* Shouldn't happen */ return WRITE_TRAN_ERROR; + case TLS_ST_OK: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_SW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + return WRITE_TRAN_ERROR; + case TLS_ST_SR_CLNT_HELLO: if (s->hello_retry_request) st->hand_state = TLS_ST_SW_HELLO_RETRY_REQUEST; @@ -459,6 +461,7 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) st->hand_state = TLS_ST_SW_SESSION_TICKET; return WRITE_TRAN_CONTINUE; + case TLS_ST_SW_KEY_UPDATE: case TLS_ST_SW_SESSION_TICKET: st->hand_state = TLS_ST_OK; ossl_statem_set_in_init(s, 0); @@ -822,6 +825,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) } break; + case TLS_ST_SW_KEY_UPDATE: case TLS_ST_SW_SESSION_TICKET: if (SSL_IS_TLS13(s) && statem_flush(s) != 1) return WORK_MORE_A; @@ -923,6 +927,11 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt, *confunc = tls_construct_hello_retry_request; *mt = SSL3_MT_HELLO_RETRY_REQUEST; break; + + case TLS_ST_SW_KEY_UPDATE: + *confunc = tls_construct_key_update; + *mt = SSL3_MT_KEY_UPDATE; + break; } return 1; |