Packing and unpacking structured keys.
authormdw <mdw>
Sat, 17 Jun 2000 10:42:41 +0000 (10:42 +0000)
committermdw <mdw>
Sat, 17 Jun 2000 10:42:41 +0000 (10:42 +0000)
key-pack.c [new file with mode: 0644]

diff --git a/key-pack.c b/key-pack.c
new file mode 100644 (file)
index 0000000..e6f2825
--- /dev/null
@@ -0,0 +1,241 @@
+/* -*-c-*-
+ *
+ * $Id: key-pack.c,v 1.1 2000/06/17 10:42:41 mdw Exp $
+ *
+ * Packing and unpacking key data
+ *
+ * (c) 1999 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: key-pack.c,v $
+ * Revision 1.1  2000/06/17 10:42:41  mdw
+ * Packing and unpacking structured keys.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key.h"
+#include "key-data.h"
+
+/*----- Generic packing and unpacking -------------------------------------*/
+
+/* --- @key_pack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data *kd@ = pointer to destination key data
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Packs a key from a data structure.
+ */
+
+int key_pack(key_packdef *kp, key_data *kd, dstr *d)
+{
+  switch (kp->kd.e & KF_ENCMASK) {
+
+    /* --- Binary and integer keys are easy --- */
+
+    case KENC_BINARY:
+      kd->u.k = *(key_bin *)kp->p;
+      return (0);
+    case KENC_MP:
+      kd->u.m = *(mp **)kp->p;
+      return (0);
+
+    /* --- Encrypted keys are a little tricky --- *
+     *
+     * This works rather differently to unpacking.
+     */
+
+    case KENC_ENCRYPT: {
+      key_data kkd;
+      int err = key_pack(kp->p, &kkd, d);
+      if (!err) {
+       if (key_plock(d->buf, &kkd, kd))
+         err = KERR_BADPASS;
+       key_destroy(&kkd);
+      }
+      return (err);
+    }
+
+    /* --- Structured keys, as ever, are a nuisance --- */
+
+    case KENC_STRUCT: {
+      int err;
+      key_packstruct *p;
+      size_t l = d->len;
+
+      key_structure(kd);
+      DPUTC(d, '.');
+      for (p = kp->p; p->name; p++) {
+       key_data *kkd;
+       d->len = l + 1;
+       DPUTS(d, p->name);
+       kkd = key_structcreate(kd, p->name);
+       if ((err = key_pack(&p->kp, kkd, d)) != 0) {
+         key_destroy(kd);
+         return (err);
+       }
+      }
+      d->len = l;
+      d->buf[l] = 0;
+      return (0);
+    }
+  }
+
+  return (KERR_BADTYPE);
+}
+
+/* --- @key_unpack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data *kd@ = pointer to source key data
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Unpacks a key into an appropriate data structure.
+ */
+
+int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
+{
+  unsigned e = kp->kd.e & KF_ENCMASK;
+  int err;
+
+  /* --- Decrypt the encrypted key --- */
+
+  while ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
+    if (key_punlock(d->buf, kd, &kp->kd)) {
+      err = KERR_BADPASS;
+      goto fail;
+    }
+    kd = &kp->kd;
+    kd->e |= KF_TEMP;
+  }
+
+  /* --- Ensure that the key has the right type --- */
+
+  if ((kd->e & KF_ENCMASK) != e) {
+    err = KERR_BADTYPE;
+    goto fail;
+  }
+
+  /* --- Unpack the key --- *
+   *
+   * Only three possibilities left now.
+   */
+
+  switch (e) {
+
+    /* --- Binary and integer keys are easy --- */
+
+    case KENC_BINARY:
+      *(key_bin *)kp->p = kd->u.k;
+      break;
+    case KENC_MP:
+      *(mp **)kp->p = kd->u.m;
+      break;
+
+    /* --- Structured keys take a little care --- */
+
+    case KENC_STRUCT: {
+      key_packstruct *p, *q;
+      size_t l = d->len;
+
+      /* --- Iterate over the requested subparts --- */
+
+      DPUTC(d, '.');
+      for (p = kp->p; p->name; p++) {
+       key_data *kkd;
+
+       /* --- Build the name --- */
+
+       d->len = l + 1;
+       DPUTS(d, p->name);
+
+       /* --- Find and unpack the subkey --- */
+
+       if ((kkd = key_structfind(kd, p->name)) == 0) {
+         if (!(p->kp.kd.e & KF_OPT)) {
+           err = KERR_NOTFOUND;
+           goto tidy;
+         }
+       } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
+         p++;
+         goto tidy;
+       }
+      }
+
+      /* --- Done --- */
+
+      d->len = l;
+      d->buf[l] = 0;
+      break;
+
+      /* --- Tidy up if something went wrong --- */
+
+    tidy:
+      for (q = kp->p; q < p; q++)
+       key_unpackdone(&q->kp);
+      goto fail;
+    }
+  }
+
+  return (0);
+
+  /* --- Something went wrong --- */
+
+fail:
+  if (kd == &kp->kd)
+    key_destroy(kd);
+  return (err);
+}
+
+/* --- @key_unpackdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing definition
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees the key components contained within a packing
+ *             definition, created during key unpacking.
+ */
+
+void key_unpackdone(key_packdef *kp)
+{
+  if (kp->kd.e & KF_TEMP)
+    key_destroy(&kp->kd);
+  if ((kp->kd.e & KF_ENCMASK) == KENC_STRUCT) {
+    key_packstruct *p;
+    for (p = kp->p; p->name; p++)
+      key_unpackdone(&p->kp);
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/