aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-02-08 09:15:22 +0000
committerMatt Caswell <matt@openssl.org>2017-02-17 10:28:00 +0000
commit44c04a2e063715abdf2db095827261456fada74a (patch)
tree0fd352dfec7c296d387cc83f4c993843fb0e2f1f /ssl
parent25b802bb855285bb3a799014f3669f73f4d11871 (diff)
downloadopenssl-44c04a2e063715abdf2db095827261456fada74a.tar.gz
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.c5
-rw-r--r--ssl/ssl_lib.c41
-rw-r--r--ssl/ssl_locl.h2
-rw-r--r--ssl/statem/statem_lib.c13
-rw-r--r--ssl/statem/statem_locl.h1
-rw-r--r--ssl/statem/statem_srvr.c19
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;