]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
tls-peer: Support answering KeyUpdate requests
authorTobias Brunner <tobias@strongswan.org>
Fri, 28 Aug 2020 08:23:43 +0000 (10:23 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Feb 2021 10:45:44 +0000 (11:45 +0100)
src/libtls/tls_fragmentation.c
src/libtls/tls_peer.c

index 483613fff152e5339f983d5fd6deb9168fd48200..f2aa1b59dbbe260cce1a74c7959c79ef9dd3cca0 100644 (file)
@@ -358,6 +358,7 @@ static status_t build_handshake(private_tls_fragmentation_t *this)
                                DBG2(DBG_TLS, "sending TLS %N handshake (%u bytes)",
                                         tls_handshake_type_names, type, hs->get_buf(hs).len);
                                if (type != TLS_FINISHED &&
+                                       type != TLS_KEY_UPDATE &&
                                        !this->handshake->cipherspec_changed(this->handshake, FALSE))
                                {
                                        hs->destroy(hs);
index a63b9fc5b4378be9774947580e6d2ce72a1b8764..04c0072897dd4b51805eb0c2e8a63939b0373295 100644 (file)
@@ -47,6 +47,8 @@ typedef enum {
        STATE_ENCRYPTED_EXTENSIONS_RECEIVED,
        STATE_CERT_VERIFY_RECEIVED,
        STATE_FINISHED_SENT_KEY_SWITCHED,
+       STATE_KEY_UPDATE_REQUESTED,
+       STATE_KEY_UPDATE_SENT,
 
 } peer_state_t;
 
@@ -1054,7 +1056,8 @@ static status_t process_key_update(private_tls_peer_t *this,
 
        if (update_requested)
        {
-               DBG1(DBG_TLS, "server requested KeyUpdate, currently not supported");
+               DBG1(DBG_TLS, "server requested KeyUpdate");
+               this->state = STATE_KEY_UPDATE_REQUESTED;
        }
        return NEED_MORE;
 }
@@ -1657,6 +1660,21 @@ static status_t send_finished(private_tls_peer_t *this,
        return NEED_MORE;
 }
 
+/**
+ * Send KeyUpdate message
+ */
+static status_t send_key_update(private_tls_peer_t *this,
+                                                               tls_handshake_type_t *type, bio_writer_t *writer)
+{
+       *type = TLS_KEY_UPDATE;
+
+       /* we currently only send this as reply, so we never request an update */
+       writer->write_uint8(writer, 0);
+
+       this->state = STATE_KEY_UPDATE_SENT;
+       return NEED_MORE;
+}
+
 METHOD(tls_handshake_t, build, status_t,
        private_tls_peer_t *this, tls_handshake_type_t *type, bio_writer_t *writer)
 {
@@ -1709,6 +1727,17 @@ METHOD(tls_handshake_t, build, status_t,
                                this->crypto->change_cipher(this->crypto, FALSE);
                                this->state = STATE_FINISHED_SENT_KEY_SWITCHED;
                                return SUCCESS;
+                       case STATE_KEY_UPDATE_REQUESTED:
+                               return send_key_update(this, type, writer);
+                       case STATE_KEY_UPDATE_SENT:
+                               if (!this->crypto->update_app_keys(this->crypto, FALSE))
+                               {
+                                       this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+                                       return NEED_MORE;
+                               }
+                               this->crypto->change_cipher(this->crypto, FALSE);
+                               this->state = STATE_FINISHED_SENT_KEY_SWITCHED;
+                               return SUCCESS;
                        case STATE_FINISHED_SENT_KEY_SWITCHED:
                                return SUCCESS;
                        default: