Provide a function to send a KeyUpdate message
authorMatt Caswell <matt@openssl.org>
Wed, 8 Feb 2017 09:15:22 +0000 (09:15 +0000)
committerMatt Caswell <matt@openssl.org>
Fri, 17 Feb 2017 10:28:00 +0000 (10:28 +0000)
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)

include/openssl/ssl.h
include/openssl/ssl3.h
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/statem/statem_lib.c
ssl/statem/statem_locl.h
ssl/statem/statem_srvr.c
util/libssl.num

index 89b4514cfba67af1b7135cf0da51bda6ae3f852c..88d7736d3231968998d2234ddf01f29ee18bdd8b 100644 (file)
@@ -825,6 +825,14 @@ DEFINE_STACK_OF(SSL_COMP)
 # define SSL_CTX_set_app_data(ctx,arg)   (SSL_CTX_set_ex_data(ctx,0,(char *)arg))
 DEPRECATEDIN_1_1_0(void SSL_set_debug(SSL *s, int debug))
 
+/* TLSv1.3 KeyUpdate message types */
+typedef enum {
+    /* -1 used so that this is an invalid value for the on-the-wire protocol */
+    SSL_KEY_UPDATE_NONE = -1,
+    /* Values as defined for the on-the-wire protocol */
+    SSL_KEY_UPDATE_NOT_REQUESTED = 0,
+    SSL_KEY_UPDATE_REQUESTED = 1
+} SSL_KEY_UPDATE;
 
 /*
  * The valid handshake states (one for each type message sent and one for each
@@ -882,7 +890,9 @@ typedef enum {
     TLS_ST_SW_CERT_VRFY,
     TLS_ST_CR_HELLO_REQ,
     TLS_ST_SW_HELLO_RETRY_REQUEST,
-    TLS_ST_CR_HELLO_RETRY_REQUEST
+    TLS_ST_CR_HELLO_RETRY_REQUEST,
+    TLS_ST_SW_KEY_UPDATE,
+    TLS_ST_CW_KEY_UPDATE
 } OSSL_HANDSHAKE_STATE;
 
 /*
@@ -1650,6 +1660,7 @@ __owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
 __owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);
 
 __owur int SSL_do_handshake(SSL *s);
+int SSL_key_update(SSL *s, SSL_KEY_UPDATE updatetype);
 int SSL_renegotiate(SSL *s);
 int SSL_renegotiate_abbreviated(SSL *s);
 __owur int SSL_renegotiate_pending(SSL *s);
@@ -2195,6 +2206,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_GET_SERVER_CERT_INDEX                  322
 # define SSL_F_SSL_GET_SIGN_PKEY                          183
 # define SSL_F_SSL_INIT_WBIO_BUFFER                       184
+# define SSL_F_SSL_KEY_UPDATE                             515
 # define SSL_F_SSL_LOAD_CLIENT_CA_FILE                    185
 # define SSL_F_SSL_LOG_MASTER_SECRET                      498
 # define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE            499
@@ -2210,6 +2222,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_PEEK_EX                                432
 # define SSL_F_SSL_READ                                   223
 # define SSL_F_SSL_READ_EX                                434
+# define SSL_F_SSL_RENEGOTIATE                            516
 # define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT                320
 # define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT                321
 # define SSL_F_SSL_SESSION_DUP                            348
@@ -2305,6 +2318,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_FINISHED                     359
 # define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST                373
 # define SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST          510
+# define SSL_F_TLS_CONSTRUCT_KEY_UPDATE                   517
 # define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET           428
 # define SSL_F_TLS_CONSTRUCT_NEXT_PROTO                   426
 # define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE           490
@@ -2472,6 +2486,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_INVALID_COMPRESSION_ALGORITHM              341
 # define SSL_R_INVALID_CONFIGURATION_NAME                 113
 # define SSL_R_INVALID_CT_VALIDATION_TYPE                 212
+# define SSL_R_INVALID_KEY_UPDATE_TYPE                    120
 # define SSL_R_INVALID_NULL_CMD_NAME                      385
 # define SSL_R_INVALID_SEQUENCE_NUMBER                    402
 # define SSL_R_INVALID_SERVERINFO_DATA                    388
@@ -2578,6 +2593,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH              303
 # define SSL_R_SSL_SESSION_ID_TOO_LONG                    408
 # define SSL_R_SSL_SESSION_VERSION_MISMATCH               210
+# define SSL_R_STILL_IN_INIT                              121
 # define SSL_R_TLSV1_ALERT_ACCESS_DENIED                  1049
 # define SSL_R_TLSV1_ALERT_DECODE_ERROR                   1050
 # define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              1021
index f2f62b4f1abc39bafbc0588206236460e6a1cded..5948dfbf77bb3602caa91c0ac0056910426c7785 100644 (file)
@@ -287,6 +287,7 @@ extern "C" {
 # define SSL3_MT_CLIENT_KEY_EXCHANGE             16
 # define SSL3_MT_FINISHED                        20
 # define SSL3_MT_CERTIFICATE_STATUS              22
+# define SSL3_MT_KEY_UPDATE                      24
 # ifndef OPENSSL_NO_NEXTPROTONEG
 #  define SSL3_MT_NEXT_PROTO                      67
 # endif
index cea604072a28f2029535d21bbe9ec20aa07ad517..2d9efbb06ab388318c950d9db20ababa9e1db3a1 100644 (file)
@@ -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"},
index 1642215ce4ba7a663daba183dd7f027f88228b93..0ca04bd96efe8e81ea778b4ee91169fa3ee6c0cb 100644 (file)
@@ -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;
 
index 6f838778a6dd984b991a2b90598c905784782244..8a3f573bf97a8160e11cf6e93487fc99e97e1303 100644 (file)
@@ -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;
index ed07266c01beab217d2a4cf13f32fcd20f9996ef..fa7387a5ada1cec5207c0b15015290f05abd331a 100644 (file)
@@ -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
index fa13a26126a7da877dcb0cf7f264cdb26303718d..96ddac2cb6eb3b460da893353bd49358818dddc3 100644 (file)
@@ -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);
 
index 2330bde360cf61cb6ee3215d81d9ed558d854039..4cdd6c949209fb71e00ef4336652cac3444cbbf1 100644 (file)
@@ -393,11 +393,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;
index 199c17a214c2fa76b0ac6307767b0d5787e91d5b..d137c93e3d3e7a6705a10018c01386deb004f7c3 100644 (file)
@@ -413,3 +413,4 @@ SSL_COMP_get0_name                      413 1_1_0d  EXIST::FUNCTION:
 SSL_CTX_set_keylog_callback             414    1_1_1   EXIST::FUNCTION:
 SSL_CTX_get_keylog_callback             415    1_1_1   EXIST::FUNCTION:
 SSL_get_peer_signature_type_nid         416    1_1_1   EXIST::FUNCTION:
+SSL_key_update                          417    1_1_1   EXIST::FUNCTION: