dsig.c: Allow precomputed hashes to be read from a file.
[u/mdw/catacomb] / key-data.c
index 4b43a2c..43ad901 100644 (file)
@@ -328,6 +328,7 @@ int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd)
     return (0);
   if (tag) *tag = SYM_NAME(ks);
   if (kd) *kd = ks->k;
+  return (1);
 }
 
 /* --- @key_structset@, @key_structsteal@ --- *
@@ -409,4 +410,59 @@ int key_do(key_data *k, const key_filter *kf, dstr *d,
   }
 }
 
+/* --- @key_copydata@ --- *
+ *
+ * Arguments:  @key_data *k@ = key data to copy
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Pointer to a copy of the data, or null if the root subkey
+ *             didn't match the filter.
+ *
+ * Use:                Copies a chunk of key data.  Subkeys, whether they're
+ *             structured or leaves, which don't match the filter aren't
+ *             copied.  The copy may or may not have structure in common
+ *             with the original.
+ */
+
+static int structmatchp(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+
+  if (!KEY_MATCH(k, kf)) return (0);
+  else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1);
+  else {
+    for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); )
+      if (!structmatchp(k, kf)) return (0);
+    return (1);
+  }
+}
+
+key_data *key_copydata(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+  const char *tag;
+  key_data *kd, *kkd;
+
+  /* --- Trivial cases --- */
+
+  if (!KEY_MATCH(k, kf))
+    return (0);
+  else if (structmatchp(k, kf)) {
+    key_incref(k);
+    return (k);
+  }
+
+  /* --- Copy a structured key recursively --- */
+
+  kkd = key_newstruct();
+  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
+    if ((kd = key_copydata(kd, kf)) != 0)
+      key_structsteal(kkd, tag, kd);
+  }
+
+  /* --- Done --- */
+
+  return (kkd);
+}
+
 /*----- That's all, folks -------------------------------------------------*/