+/*----- Key data and key nodes --------------------------------------------*/
+
+typedef struct keyhalf {
+ const char *kind;
+ int (*load)(const kgops *, key_data *, kdata *, dstr *, dstr *);
+ const char *kr;
+ key_file *kf;
+ fwatch w;
+ sym_table tab;
+} keyhalf;
+
+/* --- @kh_loadpub@, @kh_loadpriv@ --- *
+ *
+ * Arguments: @const kgops *ko@ = key-group operations for key type
+ * @key_data *d@ = key data object as stored in keyring
+ * @kdata *kd@ = our key-data object to fill in
+ * @dstr *t@ = the key tag name
+ * @dstr *e@ = a string to write error tokens to
+ *
+ * Returns: Zero on success, @-1@ on error.
+ *
+ * Use: These functions handle the main difference between public and
+ * private key halves. They are responsible for setting @g@,
+ * @kpriv@ and @kpub@ appropriately in all keys, handling the
+ * mismatch between the largely half-indifferent calling code
+ * and the group-specific loading functions.
+ *
+ * The function @kh_loadpriv@ is also responsible for checking
+ * the group for goodness. We don't bother checking public
+ * keys, because each public key we actually end up using must
+ * share a group with a private key which we'll already have
+ * checked.
+ */
+
+static int kh_loadpub(const kgops *ko, key_data *d, kdata *kd,
+ dstr *t, dstr *e)
+{
+ int rc;
+
+ if ((rc = ko->loadpub(d, kd, t, e)) != 0)
+ goto fail_0;
+ if (group_check(kd->g, kd->kpub)) {
+ a_format(e, "bad-public-group-element");
+ goto fail_1;
+ }
+ kd->kpriv = 0;
+ return (0);
+
+fail_1:
+ G_DESTROY(kd->g, kd->kpub);
+ G_DESTROYGROUP(kd->g);
+fail_0:
+ return (-1);
+}
+
+static int kh_loadpriv(const kgops *ko, key_data *d, kdata *kd,
+ dstr *t, dstr *e)
+{
+ int rc;
+ const char *err;
+
+ if ((rc = ko->loadpriv(d, kd, t, e)) != 0)
+ goto fail_0;
+ if ((err = G_CHECK(kd->g, &rand_global)) != 0) {
+ a_format(e, "bad-group", "%s", err, A_END);
+ goto fail_1;
+ }
+ kd->kpub = G_CREATE(kd->g);
+ G_EXP(kd->g, kd->kpub, kd->g->g, kd->kpriv);
+ return (0);
+
+fail_1:
+ mp_drop(kd->kpriv);
+ G_DESTROYGROUP(kd->g);
+fail_0:
+ return (-1);
+}
+
+static struct keyhalf
+ priv = { "private", kh_loadpriv },
+ pub = { "public", kh_loadpub };