/* new states in TLS 1.3 */
STATE_ENCRYPTED_EXTENSIONS_SENT,
STATE_CERT_VERIFY_SENT,
+ STATE_KEY_UPDATE_REQUESTED,
+ STATE_KEY_UPDATE_SENT,
} server_state_t;
/**
return NEED_MORE;
}
+/**
+ * Process KeyUpdate message
+ */
+static status_t process_key_update(private_tls_server_t *this,
+ bio_reader_t *reader)
+{
+ uint8_t update_requested;
+
+ if (!reader->read_uint8(reader, &update_requested) ||
+ update_requested > 1)
+ {
+ DBG1(DBG_TLS, "received invalid KeyUpdate");
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
+ }
+
+ if (!this->crypto->update_app_keys(this->crypto, TRUE))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
+ this->crypto->change_cipher(this->crypto, TRUE);
+
+ if (update_requested)
+ {
+ DBG1(DBG_TLS, "client requested KeyUpdate");
+ this->state = STATE_KEY_UPDATE_REQUESTED;
+ }
+ return NEED_MORE;
+}
+
METHOD(tls_handshake_t, process, status_t,
private_tls_server_t *this, tls_handshake_type_t type, bio_reader_t *reader)
{
}
return NEED_MORE;
case STATE_FINISHED_RECEIVED:
+ if (type == TLS_KEY_UPDATE)
+ {
+ return process_key_update(this, reader);
+ }
return INVALID_STATE;
default:
DBG1(DBG_TLS, "TLS %N not expected in current state",
return NEED_MORE;
}
+/**
+ * Send KeyUpdate message
+ */
+static status_t send_key_update(private_tls_server_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_server_t *this, tls_handshake_type_t *type, bio_writer_t *writer)
{
return send_finished(this, type, writer);
case STATE_FINISHED_SENT:
return INVALID_STATE;
+ 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_RECEIVED;
default:
return INVALID_STATE;
}