+/*----- Reference counting stuff ------------------------------------------*/
+
+/* --- @key_incref@ --- *
+ *
+ * Arguments: @key_data *k@ = pointer to key data
+ *
+ * Returns: ---
+ *
+ * Use: Increments the refcount on a key data block.
+ */
+
+void key_incref(key_data *k) { KEY_INCREF(k); }
+
+/* --- @key_destroy@ --- *
+ *
+ * Arguments: @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns: ---
+ *
+ * Use: Destroys a block of key data, regardless of reference count.
+ * Don't use this unless you know what you're doing.
+ */
+
+void key_destroy(key_data *k)
+{
+ switch (k->e & KF_ENCMASK) {
+ case KENC_BINARY:
+ case KENC_ENCRYPT:
+ if (k->u.k.k) {
+ if (k->e & KF_BURN)
+ memset(k->u.k.k, 0, k->u.k.sz);
+ sub_free(k->u.k.k, k->u.k.sz);
+ }
+ break;
+ case KENC_MP:
+ mp_drop(k->u.m);
+ break;
+ case KENC_STRING:
+ xfree(k->u.p);
+ break;
+ case KENC_EC:
+ EC_DESTROY(&k->u.e);
+ break;
+ case KENC_STRUCT: {
+ key_data *kd;
+ key_subkeyiter i;
+
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); )
+ KEY_DROP(kd);
+ sym_destroy(&k->u.s);
+ } break;
+ default:
+ abort();
+ }
+ DESTROY(k);
+}
+
+/* --- @key_drop@ --- *
+ *
+ * Arguments: @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns: ---
+ *
+ * Use: Drops a reference to key data, destroying it if necessary.
+ */
+
+void key_drop(key_data *k) { KEY_DROP(k); }
+
+/* --- @key_split@ --- *
+ *
+ * Arguments: @key_data **kk@ = address of pointer to key data block
+ *
+ * Returns: ---
+ *
+ * Use: Replaces @*kk@ with a pointer to the same key data, but with
+ * just one reference.
+ */
+
+void key_split(key_data **kk)
+{
+ key_data *k = *kk;
+
+ if (k->ref == 1)
+ return;
+ switch (k->e & KF_ENCMASK) {
+ case KENC_BINARY:
+ *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz);
+ break;
+ case KENC_ENCRYPT:
+ *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz);
+ break;
+ case KENC_MP:
+ *kk = key_newmp(k->e, k->u.m);
+ break;
+ case KENC_STRING:
+ *kk = key_newstring(k->e, k->u.p);
+ break;
+ case KENC_EC:
+ *kk = key_newec(k->e, &k->u.e);
+ break;
+ case KENC_STRUCT: {
+ key_subkeyiter i;
+ const char *tag;
+ key_data *kd;
+
+ *kk = key_newstruct();
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); )
+ key_structset(*kk, tag, kd);
+ } break;
+ default:
+ abort();
+ }
+}
+