+/* Responder rekey completion callback */
+
+static void
+silc_server_rekey_resp_completion(SilcSKE ske,
+ SilcSKEStatus status,
+ const SilcSKESecurityProperties prop,
+ const SilcSKEKeyMaterial keymat,
+ SilcSKERekeyMaterial rekey,
+ void *context)
+{
+ SilcPacketStream sock = context;
+ SilcIDListData idata = silc_packet_get_context(sock);
+
+ idata->sconn->op = NULL;
+ if (status != SILC_SKE_STATUS_OK) {
+ SILC_LOG_ERROR(("Error during rekey protocol with %s",
+ idata->sconn->remote_host));
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Rekey protocol completed with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
+
+ /* Save rekey data for next rekey */
+ idata->rekey = rekey;
+}
+
+/* Start rekey as responder */
+
+static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet)
+{
+ SilcIDListData idata = silc_packet_get_context(sock);
+ SilcSKE ske;
+
+ SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
+
+ /* Allocate SKE */
+ ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
+ server->public_key, server->private_key, sock);
+ if (!ske) {
+ silc_packet_free(packet);
+ return;
+ }
+
+ /* Set SKE callbacks */
+ silc_ske_set_callbacks(ske, NULL, silc_server_rekey_resp_completion, sock);
+
+ /* Perform rekey */
+ idata->sconn->op = silc_ske_rekey_responder(ske, sock, idata->rekey,
+ packet);
+}
+