freeenc(e);
if (s) freesig(s);
freekem(km);
+ if (fp != stdin) fclose(fp);
if (of) fclose(ofp);
key_close(&kf);
dstr_destroy(&d);
key_fulltag(sk, &d);
printf("INFO good-signature %s\n", d.buf);
}
+ freesig(s);
} else if (verb)
printf("INFO no-signature\n");
printf("FAIL bad ciphertext chunk: authentication failure\n");
exit(EXIT_FAILURE);
}
+ GH_DESTROY(h);
if (!BLEFT(&b))
break;
GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b));
GC_DESTROY(cx);
GM_DESTROY(m);
freekem(km);
+ if (fp != stdin) fclose(fp);
if (of) fclose(ofp);
key_close(&kf);
dstr_destroy(&d);
G_DESTROY(ds->g.g, ds->g.p);
mp_drop(ds->g.u);
G_DESTROYGROUP(ds->g.g);
+ DESTROY(ds);
}
static const sigops dsa_sig = {
/* --- Unlock the key --- */
- kp.kd.e = KENC_BINARY;
+ kp.e = KENC_BINARY;
kp.p = &kb;
- if ((e = key_unpack(&kp, &k->k, &t)) != 0) {
+ if ((e = key_unpack(&kp, k->k, &t)) != 0) {
die(EXIT_FAILURE, "error unpacking key `%s': %s",
t.buf, key_strerror(e));
}
/* -*-c-*-
*
- * $Id: exp.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
*
* Generalized exponentiation
*
for (i = 1; i < vn; i++) \
EXP_DROP(v[i]); \
xfree(v); \
+ xfree(e.s); \
} while (0)
/*----- Functions provided ------------------------------------------------*/
return (0);
}
+/* --- @key_setkeydata@ --- *
+ *
+ * Arguments: @key_file *kf@ = pointer to key file
+ * @key *k@ = pointer to key
+ * @key_data *kd@ = new key data
+ *
+ * Returns: Zero on success, or a @KERR_@ error code on failure.
+ *
+ * Use: Sets the key data for a key.
+ */
+
+int key_setkeydata(key_file *kf, key *k, key_data *kd)
+{
+ if (!(kf->f & KF_WRITE))
+ return (KERR_READONLY);
+ key_drop(k->k);
+ key_incref(kd);
+ k->k = kd;
+ kf->f |= KF_MODIFIED;
+ return (0);
+}
+
/* --- @key_setcomment@ --- *
*
* Arguments: @key_file *f@ = pointer to key file block
*
* Arguments: @const void *p@ = pointer to buffer to read
* @size_t sz@ = size of the buffer
- * @key_data *k@ = pointer to key data block to write to
*
- * Returns: Zero if everything worked, nonzero otherwise.
+ * Returns: The newly-read key data, or null if it failed.
*
* Use: Decodes a binary representation of a key.
*/
-int key_decode(const void *p, size_t sz, key_data *k)
+key_data *key_decode(const void *p, size_t sz)
{
const octet *q = p;
size_t psz;
+ key_data *kd;
unsigned e;
/* --- Parse the header information --- *
e = LOAD16(q);
psz = LOAD16(q + 2);
if (psz + 4 > sz)
- return (-1);
- k->e = e;
+ return (0);
/* --- Now decide what to do --- */
case KENC_BINARY:
case KENC_ENCRYPT:
- k->u.k.k = sub_alloc(psz);
- memcpy(k->u.k.k, q + 4, psz);
- k->u.k.sz = psz;
+ kd = key_newbinary(e, q + 4, psz);
break;
/* --- Multiprecision integer data --- */
case KENC_MP:
- k->u.m = mp_loadb(k->e & KF_BURN ? MP_NEWSEC : MP_NEW, q + 4, psz);
+ kd = key_newmp(e, mp_loadb(e & KF_BURN ? MP_NEWSEC : MP_NEW,
+ q + 4, psz));
break;
/* --- String data --- */
case KENC_STRING:
- k->u.p = xmalloc(sz + 1);
- memcpy(k->u.p, q + 4, sz);
- k->u.p[sz] = 0;
+ kd = key_newraw(e);
+ kd->u.p = xmalloc(sz + 1);
+ memcpy(kd->u.p, q + 4, sz);
+ kd->u.p[sz] = 0;
break;
/* --- Elliptic curve point data --- */
case KENC_EC: {
size_t xsz, ysz;
- EC_CREATE(&k->u.e);
+ kd = key_newraw(e);
+ EC_CREATE(&kd->u.e);
if (!sz) break;
- if (sz < 2) return (-1);
+ if (sz < 2) return (0);
xsz = LOAD16(q + 4);
- if (sz < xsz + 4) return (-1);
+ if (sz < xsz + 4) return (0);
ysz = LOAD16(q + 6 + xsz);
- if (sz < xsz + ysz + 4) return (-1);
- k->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
- k->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz);
+ if (sz < xsz + ysz + 4) return (0);
+ kd->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
+ kd->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz);
} break;
/* --- Structured key data --- */
case KENC_STRUCT: {
dstr d = DSTR_INIT;
- key_struct *ks;
- unsigned f;
+ key_data *nkd;
- if ((k->e & ~KF_ENCMASK) || (psz & 3))
- return (-1);
+ if ((e & ~KF_ENCMASK) || (psz & 3))
+ return (0);
q += 4;
- sym_create(&k->u.s);
+ kd = key_newstruct();
while (psz) {
/* --- Read the encoding and size --- */
- e = LOAD16(q);
sz = (LOAD16(q + 2) + 7) & ~3;
if (sz > psz)
goto fail;
/* --- Create a table node and fill it in --- */
- ks = sym_find(&k->u.s, d.buf, d.len, sizeof(*ks), &f);
- if (f)
- goto fail;
- if (key_decode(q, sz, &ks->k)) {
- sym_remove(&k->u.s, ks);
+ if ((nkd = key_decode(q, sz)) == 0)
goto fail;
- }
+ key_structsteal(kd, d.buf, nkd);
psz -= sz;
q += sz;
}
fail:
dstr_destroy(&d);
- key_destroy(k);
- return (-1);
+ key_drop(kd);
+ return (0);
} break;
/* --- Everything else --- */
default:
- return (-1);
+ return (0);
}
/* --- OK, that was good --- */
- return (0);
+ kd->e = e;
+ return (kd);
}
/* --- @key_encode@ --- *
DPUTS(d, SYM_NAME(ks));
while (d->len & 3)
DPUTC(d, 0);
- if (key_encode(&ks->k, d, kf))
+ if (key_encode(ks->k, d, kf))
rc = 1;
else
d->len = o;
#include "mp.h"
#include "mptext.h"
+/*----- 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();
+ }
+}
+
/*----- Setting new values ------------------------------------------------*/
-/* --- @key_binary@ --- *
+/* --- @key_newraw@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = encoding type to set
+ *
+ * Returns: New key block, not filled in.
+ */
+
+key_data *key_newraw(unsigned e)
+{
+ key_data *k = CREATE(key_data);
+ k->e = e;
+ k->ref = 1;
+ return (k);
+}
+
+/* --- @key_newbinary@ --- *
+ *
+ * Arguments: @unsigned e@ = other encoding flags
* @const void *p@ = pointer to key data
* @size_t sz@ = size of the key data
*
- * Returns: ---
- *
- * Use: Sets a binary key in a key data block.
+ * Returns: New key data object.
*/
-void key_binary(key_data *k, const void *p, size_t sz)
+key_data *key_newbinary(unsigned e, const void *p, size_t sz)
{
- key_destroy(k);
- k->e |= KENC_BINARY;
+ key_data *k = key_newraw(KENC_BINARY | e);
k->u.k.k = sub_alloc(sz);
memcpy(k->u.k.k, p, sz);
k->u.k.sz = sz;
+ return (k);
}
-/* --- @key_encrypted@ --- *
+/* --- @key_newencrypted@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @const void *p@ = pointer to key data
* @size_t sz@ = size of the key data
*
- * Returns: ---
- *
- * Use: Sets an encrypted key in a key data block.
+ * Returns: New key data object.
*/
-void key_encrypted(key_data *k, const void *p, size_t sz)
+key_data *key_newencrypted(unsigned e, const void *p, size_t sz)
{
- key_destroy(k);
- k->e |= KENC_ENCRYPT;
+ key_data *k = key_newraw(KENC_ENCRYPT | e);
k->u.k.k = sub_alloc(sz);
memcpy(k->u.k.k, p, sz);
k->u.k.sz = sz;
+ return (k);
}
-/* --- @key_mp@ --- *
+/* --- @key_mewmp@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @mp *m@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets a multiprecision integer key in a key block.
+ * Returns: New key data object.
*/
-void key_mp(key_data *k, mp *m)
+key_data *key_newmp(unsigned e, mp *m)
{
- key_destroy(k);
- k->e |= KENC_MP;
+ key_data *k = key_newraw(KENC_MP | e);
k->u.m = MP_COPY(m);
+ return (k);
}
-/* --- @key_string@ --- *
+/* --- @key_newstring@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @const char *p@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets a plain string in a key block.
+ * Returns: New key data object.
*/
-void key_string(key_data *k, const char *p)
+key_data *key_newstring(unsigned e, const char *p)
{
- key_destroy(k);
- k->e |= KENC_STRING;
+ key_data *k = key_newraw(KENC_STRING | e);
k->u.p = xstrdup(p);
+ return (k);
}
-/* --- @key_ec@ --- *
+/* --- @key_newec@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
- * @const ec *e@ = pointer to the value to set
+ * Arguments: @unsigned e@ = other encoding flags
+ * @const ec *pt@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets an elliptic curve point in a key block.
+ * Returns: New key data object.
*/
-void key_ec(key_data *k, const ec *e)
-{
- key_destroy(k);
- k->e |= KENC_EC;
+key_data *key_newec(unsigned e, const ec *pt)
+{
+ key_data *k = key_newraw(KENC_EC | e);
EC_CREATE(&k->u.e);
- EC_COPY(&k->u.e, e);
+ EC_COPY(&k->u.e, pt);
+ return (k);
}
-/* --- @key_structure@ --- *
+/* --- @key_newstruct@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
- *
- * Returns: ---
+ * Arguments: ---
*
- * Use: Initializes a structured key type.
+ * Returns: New key data object.
*/
-void key_structure(key_data *k)
+key_data *key_newstruct(void)
{
- key_destroy(k);
- k->e |= KENC_STRUCT;
+ key_data *k = key_newraw(KENC_STRUCT);
sym_create(&k->u.s);
+ return (k);
}
/* --- @key_structfind@ --- *
ks = sym_find(&k->u.s, tag, -1, 0, 0);
if (!ks)
return (0);
- return (&ks->k);
+ return (ks->k);
}
-/* --- @key_structcreate@ --- *
+/* --- @key_mksubkeyiter@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
- * @const char *tag@ = pointer to tag string
+ * Arguments: @key_subkeyiter *i@ = pointer to iterator block
+ * @key_data *k@ = pointer to key data block
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a subkey iterator.
+ */
+
+void key_mksubkeyiter(key_subkeyiter *i, key_data *k)
+{
+ assert(((void)"Key is not structured",
+ (k->e & KF_ENCMASK) == KENC_STRUCT));
+ sym_mkiter(&i->i, &k->u.s);
+}
+
+/* --- @key_nextsubkey@ --- *
*
- * Returns: Pointer to newly created key data.
+ * Arguments: @key_structiter *i@ = pointer to iterator block
+ * @const char **tag@ = where to put the tag pointer, or null
+ * @key_data **kd@ = where to put the key data pointer, or null
*
- * Use: Creates a new uninitialized subkey.
+ * Returns: Nonzero if there was another item, zero if we hit the
+ * end-stop.
+ *
+ * Use: Collects the next subkey of a structured key.
*/
-key_data *key_structcreate(key_data *k, const char *tag)
+int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd)
{
key_struct *ks;
- unsigned f;
- assert(((void)"Key is not structured", k->e == KENC_STRUCT));
- ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f);
- if (f)
- key_destroy(&ks->k);
- ks->k.e = 0;
- ks->k.u.k.k = 0;
- ks->k.u.k.sz = 0;
- return (&ks->k);
+ if ((ks = sym_next(&i->i)) == 0)
+ return (0);
+ if (tag) *tag = SYM_NAME(ks);
+ if (kd) *kd = ks->k;
}
-/*----- Miscellaneous operations ------------------------------------------*/
-
-/* --- @key_destroy@ --- *
+/* --- @key_structset@, @key_structsteal@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data to destroy
+ * Arguments: @key_data *k@ = pointer to key data block
+ * @const char *tag@ = pointer to tag string
+ * @key_data *kd@ = new key data to store
*
* Returns: ---
*
- * Use: Destroys a lump of key data.
+ * Use: Creates a new subkey. Stealing doesn't affect @kd@'s
+ * refcount. If @kd@ is null, the subkey is deleted.
*/
-void key_destroy(key_data *k)
+static void structset(key_data *k, int stealp,
+ const char *tag, key_data *kd)
{
- 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: {
- sym_iter i;
- key_struct *ks;
+ key_struct *ks;
+ unsigned f;
- for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; )
- key_destroy(&ks->k);
- sym_destroy(&k->u.s);
- } break;
- }
- k->e = (k->e & ~KF_ENCMASK);
- k->u.k.k = 0;
- k->u.k.sz = 0;
+ assert(((void)"Key is not structured", k->e == KENC_STRUCT));
+ if (!kd) {
+ ks = sym_find(&k->u.s, tag, -1, 0, 0);
+ if (ks) sym_remove(&k->u.s, ks);
+ } else {
+ ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f);
+ if (f)
+ key_drop(ks->k);
+ if (!stealp) KEY_INCREF(kd);
+ ks->k = kd;
+ }
}
+void key_structset(key_data *k, const char *tag, key_data *kd)
+ { structset(k, 0, tag, kd); }
+void key_structsteal(key_data *k, const char *tag, key_data *kd)
+ { structset(k, 1, tag, kd); }
+
+/*----- Miscellaneous operations ------------------------------------------*/
+
/* --- @key_do@ --- *
*
* Arguments: @key_data *k@ = pointer to key data block
if ((k->e & KF_ENCMASK) != KENC_STRUCT)
return (func(k, d, p));
else {
- sym_iter i;
- key_struct *ks;
+ key_subkeyiter i;
+ const char *tag;
size_t n = 0;
int rc;
if (d)
n = d->len;
- for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
if (d) {
d->len = n;
- dstr_putf(d, ".%s", SYM_NAME(ks));
+ dstr_putf(d, ".%s", tag);
}
- if ((rc = key_do(&ks->k, kf, d, func, p)) != 0)
+ if ((rc = key_do(k, kf, d, func, p)) != 0)
return (rc);
}
return (0);
}
}
-/* --- @key_copy@ --- *
- *
- * Arguments: @key_data *kd@ = pointer to destination data block
- * @key_data *k@ = pointer to source data block
- * @const key_filter *kf@ = pointer to filter block
- *
- * Returns: Nonzero if an item was actually copied.
- *
- * Use: Copies a chunk of key data from one place to another.
- */
-
-int key_copy(key_data *kd, key_data *k, const key_filter *kf)
-{
- kd->e = k->e;
-
- if (!KEY_MATCH(kd, kf))
- return (0);
- switch (k->e & KF_ENCMASK) {
-
- /* --- Plain binary data --- */
-
- case KENC_BINARY:
- case KENC_ENCRYPT:
- if (!k->u.k.k)
- kd->u.k.k = 0;
- else {
- kd->u.k.k = sub_alloc(k->u.k.sz);
- memcpy(kd->u.k.k, k->u.k.k, k->u.k.sz);
- }
- kd->u.k.sz = k->u.k.sz;
- break;
-
- /* --- Multiprecision integers --- */
-
- case KENC_MP:
- kd->u.m = MP_COPY(k->u.m);
- break;
-
- /* --- Strings --- */
-
- case KENC_STRING:
- kd->u.p = xstrdup(k->u.p);
- break;
-
- /* --- Elliptic curve points --- */
-
- case KENC_EC:
- EC_CREATE(&kd->u.e);
- EC_COPY(&kd->u.e, &k->u.e);
- break;
-
- /* --- Structured key data --- */
-
- case KENC_STRUCT: {
- sym_iter i;
- key_struct *ks;
- int rc = 0;
-
- sym_create(&kd->u.s);
- for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
- unsigned f;
- key_struct *kks = sym_find(&kd->u.s, SYM_NAME(ks), -1,
- sizeof(*kks), &f);
- assert(((void)"Duplicate subkey tags", !f));
- if (key_copy(&kks->k, &ks->k, kf))
- rc = 1;
- else
- sym_remove(&kd->u.s, kks);
- }
- if (!rc) {
- sym_destroy(&kd->u.s);
- return (0);
- }
- } break;
- }
- return (1);
-}
-
/*----- That's all, folks -------------------------------------------------*/
typedef struct key_data {
unsigned e; /* Encoding type for key data */
+ unsigned ref; /* Reference counter */
union {
key_bin k; /* Binary key data */
mp *m; /* Multiprecision integer */
typedef struct key_struct {
sym_base _b;
- key_data k;
+ key_data *k;
} key_struct;
+typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter;
+
/* --- Packing and unpacking --- */
typedef struct key_packdef {
+ unsigned e; /* Key data encoding type */
void *p; /* Pointer to the destination */
- key_data kd; /* Key data block */
+ key_data *kd; /* Key data block */
} key_packdef;
typedef struct key_packstruct {
/* --- Other flags --- */
KF_BURN = 0x10, /* Burn key after use */
- KF_TEMP = 0x20, /* Temporary copy flag */
- KF_OPT = 0x40, /* Optional key (for @key_unpack@) */
+ KF_OPT = 0x20, /* Optional key (for @key_unpack@) */
/* --- Tag end --- */
/*----- Setting new key data ----------------------------------------------*/
-/* --- @key_binary@ --- *
+/* --- @key_newraw@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = encoding type to set
+ *
+ * Returns: New key block, not filled in.
+ */
+
+extern key_data *key_newraw(unsigned /*e*/);
+
+/* --- @key_newbinary@ --- *
+ *
+ * Arguments: @unsigned e@ = other encoding flags
* @const void *p@ = pointer to key data
* @size_t sz@ = size of the key data
*
- * Returns: ---
- *
- * Use: Sets a binary key in a key data block.
+ * Returns: New key data object.
*/
-extern void key_binary(key_data */*k*/, const void */*p*/, size_t /*sz*/);
+extern key_data *key_newbinary(unsigned /*e*/,
+ const void */*p*/, size_t /*sz*/);
-/* --- @key_encrypted@ --- *
+/* --- @key_newencrypted@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @const void *p@ = pointer to key data
* @size_t sz@ = size of the key data
*
- * Returns: ---
- *
- * Use: Sets an encrypted key in a key data block.
+ * Returns: New key data object.
*/
-extern void key_encrypted(key_data */*k*/, const void */*p*/, size_t /*sz*/);
+extern key_data *key_newencrypted(unsigned /*e*/,
+ const void */*p*/, size_t /*sz*/);
-/* --- @key_mp@ --- *
+/* --- @key_mewmp@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @mp *m@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets a multiprecision integer key in a key block.
+ * Returns: New key data object.
*/
-extern void key_mp(key_data */*k*/, mp */*m*/);
+extern key_data *key_newmp(unsigned /*e*/, mp */*m*/);
-/* --- @key_string@ --- *
+/* --- @key_newstring@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: @unsigned e@ = other encoding flags
* @const char *p@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets a plain string in a key block.
+ * Returns: New key data object.
*/
-extern void key_string(key_data */*k*/, const char */*p*/);
+extern key_data *key_newstring(unsigned /*e*/, const char */*p*/);
-/* --- @key_ec@ --- *
+/* --- @key_newec@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
- * @const ec *e@ = pointer to the value to set
+ * Arguments: @unsigned e@ = other encoding flags
+ * @const ec *pt@ = pointer to the value to set
*
- * Returns: ---
- *
- * Use: Sets an elliptic curve point in a key block.
+ * Returns: New key data object.
*/
-extern void key_ec(key_data */*k*/, const ec */*e*/);
+extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/);
-/* --- @key_structure@ --- *
+/* --- @key_newstruct@ --- *
*
- * Arguments: @key_data *k@ = pointer to key data block
+ * Arguments: ---
*
- * Returns: ---
- *
- * Use: Initializes a structured key type.
+ * Returns: New key data object.
*/
-extern void key_structure(key_data */*k*/);
+extern key_data *key_newstruct(void);
/* --- @key_structfind@ --- *
*
extern key_data *key_structfind(key_data */*k*/, const char */*tag*/);
-/* --- @key_structcreate@ --- *
+/* --- @key_mksubkeyiter@ --- *
+ *
+ * Arguments: @key_subkeyiter *i@ = pointer to iterator block
+ * @key_data *k@ = pointer to key data block
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a subkey iterator.
+ */
+
+extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/);
+
+/* --- @key_nextsubkey@ --- *
+ *
+ * Arguments: @key_structiter *i@ = pointer to iterator block
+ * @const char **tag@ = where to put the tag pointer, or null
+ * @key_data **kd@ = where to put the key data pointer, or null
+ *
+ * Returns: Nonzero if there was another item, zero if we hit the
+ * end-stop.
+ *
+ * Use: Collects the next subkey of a structured key.
+ */
+
+extern int key_nextsubkey(key_subkeyiter */*i*/,
+ const char **/*tag*/, key_data **/*kd*/);
+
+/* --- @key_structset@, @key_structsteal@ --- *
*
* Arguments: @key_data *k@ = pointer to key data block
* @const char *tag@ = pointer to tag string
+ * @key_data *kd@ = new key data to store
*
- * Returns: Pointer to newly created key data.
+ * Returns: ---
*
- * Use: Creates a new uninitialized subkey.
+ * Use: Creates a new subkey. Stealing doesn't affect @kd@'s
+ * refcount. If @kd@ is null, the subkey is deleted.
*/
-extern key_data *key_structcreate(key_data */*k*/, const char */*tag*/);
+extern void key_structset(key_data */*k*/,
+ const char */*tag*/, key_data */*kd*/);
+extern void key_structsteal(key_data */*k*/,
+ const char */*tag*/, key_data */*kd*/);
+
+/* --- @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.
+ */
+
+extern void key_split(key_data **/*kk*/);
/*----- Miscellaneous operations ------------------------------------------*/
+/* --- @key_incref@ --- *
+ *
+ * Arguments: @key_data *k@ = pointer to key data
+ *
+ * Returns: ---
+ *
+ * Use: Increments the refcount on a key data block.
+ */
+
+#define KEY_INCREF(k) ((k)->ref++)
+extern void key_incref(key_data */*k*/);
+
/* --- @key_destroy@ --- *
*
* Arguments: @key_data *k@ = pointer to key data to destroy
*
* Returns: ---
*
- * Use: Destroys a lump of key data.
+ * Use: Destroys a block of key data, regardless of reference count.
+ * Don't use this unless you know what you're doing.
*/
extern void key_destroy(key_data */*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.
+ */
+
+#define KEY_DROP(k) do { \
+ key_data *_k = k; \
+ _k->ref--; \
+ if (_k->ref == 0) \
+ key_destroy(_k); \
+} while (0)
+
+extern void key_drop(key_data */*k*/);
+
/* --- @key_do@ --- *
*
* Arguments: @key_data *k@ = pointer to key data block
dstr */*d*/, void */*p*/),
void */*p*/);
-/* --- @key_copy@ --- *
- *
- * Arguments: @key_data *kd@ = pointer to destination data block
- * @key_data *k@ = pointer to source data block
- * @const key_filter *kf@ = pointer to filter block
- *
- * Returns: Nonzero if an item was actually copied.
- *
- * Use: Copies a chunk of key data from one place to another.
- */
-
-extern int key_copy(key_data */*kd*/, key_data */*k*/,
- const key_filter */*kf*/);
-
/*----- Textual encoding --------------------------------------------------*/
/* --- @key_read@ --- *
*
* Arguments: @const char *p@ = pointer to textual key representation
- * @key_data *k@ = pointer to output block for key data
* @char **pp@ = where to store the end pointer
*
- * Returns: Zero if all went well, nonzero if there was a problem.
+ * Returns: The newly-read key data, or null if it failed.
*
* Use: Parses a textual key description.
*/
-extern int key_read(const char */*p*/, key_data */*k*/, char **/*pp*/);
+extern key_data *key_read(const char */*p*/, char **/*pp*/);
/* --- @key_write@ --- *
*
* Use: Writes a key in a textual encoding.
*/
-extern int key_write(key_data */*k*/, dstr */*d*/,
- const key_filter */*kf*/);
+extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/);
/*----- Key binary encoding -----------------------------------------------*/
*
* Arguments: @const void *p@ = pointer to buffer to read
* @size_t sz@ = size of the buffer
- * @key_data *k@ = pointer to key data block to write to
*
- * Returns: Zero if everything worked, nonzero otherwise.
+ * Returns: The newly-read key data, or null if it failed.
*
* Use: Decodes a binary representation of a key.
*/
-extern int key_decode(const void */*p*/, size_t /*sz*/, key_data */*k*/);
+extern key_data *key_decode(const void */*p*/, size_t /*sz*/);
/* --- @key_encode@ --- *
*
/* --- @key_pack@ --- *
*
* Arguments: @key_packdef *kp@ = pointer to packing structure
- * @key_data *kd@ = pointer to destination key data
+ * @key_data **kd@ = where to put the key data pointer
* @dstr *d@ = pointer to tag string for the key data
*
* Returns: Error code, or zero.
* Use: Packs a key from a data structure.
*/
-extern int key_pack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/);
+extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/);
/* --- @key_unpack@ --- *
*
/* --- @key_lock@ --- *
*
- * Arguments: @key_data *kt@ = destination block
- * @key_data *k@ = source key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
* @const void *e@ = secret to encrypt key with
* @size_t esz@ = size of the secret
*
* Use: Encrypts a key data block using a secret.
*/
-extern void key_lock(key_data */*kt*/, key_data */*k*/,
+extern void key_lock(key_data **/*kt*/, key_data */*k*/,
const void */*e*/, size_t /*esz*/);
/* --- @key_unlock@ --- *
*
- * Arguments: @key_data *kt@ = target block
- * @key_data *k@ = source key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
* @const void *e@ = secret to decrypt the block with
* @size_t esz@ = size of the secret
*
* Use: Unlocks a key using a secret.
*/
-extern int key_unlock(key_data */*kt*/, key_data */*k*/,
+extern int key_unlock(key_data **/*kt*/, key_data */*k*/,
const void */*e*/, size_t /*esz*/);
/* --- @key_plock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
- * @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
+ * @const char *tag@ = tag to use for passphrase
*
* Returns: Zero if successful, a @KERR@ error code on failure.
*
* Use: Locks a key by encrypting it with a passphrase.
*/
-extern int key_plock(const char */*tag*/, key_data */*k*/, key_data */*kt*/);
+extern int key_plock(key_data **/*kt*/, key_data */*k*/,
+ const char */*tag*/);
/* --- @key_punlock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
- * @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
+ * @const char *tag@ = tag to use for passphrase
*
* Returns: Zero if successful, a @KERR@ error code on failure.
*
* Use: Unlocks a passphrase-locked key.
*/
-extern int key_punlock(const char */*tag*/,
- key_data */*k*/, key_data */*kt*/);
+extern int key_punlock(key_data **/*kt*/, key_data */*k*/,
+ const char */*tag*/);
/*----- That's all, folks -------------------------------------------------*/
/* --- Fill in the top part --- */
- kp->kp.kd.e = KENC_STRUCT;
+ kp->kp.e = KENC_STRUCT;
kp->kp.p = &kp[1];
+ kp->kp.kd = 0;
kpd = &kp->kp;
/* --- Initialize for the main loop --- */
while (kf->name) {
kp->name = kf->name;
- kp->kp.kd.e = kf->e;
+ kp->kp.e = kf->e;
+ kp->kp.kd = 0;
if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
kp->kp.p = cp + kf->off;
else {
int e;
key_fulltag(k, &d);
- e = key_unpack(kp, &k->k, &d);
+ e = key_unpack(kp, k->k, &d);
dstr_destroy(&d);
return (e);
}
int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
{
dstr d = DSTR_INIT;
- key_data *kd;
+ key_data **kd;
int e;
if (key_qtag(kf, tag, &d, 0, &kd))
e = KERR_NOTFOUND;
else
- e = key_unpack(kp, kd, &d);
+ e = key_unpack(kp, *kd, &d);
dstr_destroy(&d);
return (e);
}
void key_fetchdone(key_packdef *kp)
{
- key_packstruct *kps = (key_packstruct *)(((char *)kp) -
- offsetof(key_packstruct, kp));
+ key_packstruct *kps =
+ (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp));
key_unpackdone(kp);
if (kps->name)
xfree(kps);
unlink(n_new.buf);
unlink(n_older.buf);
+ dstr_destroy(&n_new);
+ dstr_destroy(&n_old);
+ dstr_destroy(&n_older);
return (KWRITE_OK);
/* --- Failure while writing the new key file --- *
dstr_destroy(&n_older);
return (rc);
-/* --- Failure during write of new data --- *
- *
- * Clean up the new file and return. These errors can never cause
- * breakage.
- */
+ /* --- Failure during write of new data --- *
+ *
+ * Clean up the new file and return. These errors can never cause
+ * breakage.
+ */
fail_write:
unlink(n_new.buf);
- fail_open:
+fail_open:
dstr_destroy(&n_new);
return (rc);
}
/* --- Extract the key data into the block --- */
- if (key_read(vf[1], &k->k, 0)) {
+ if ((k->k = key_read(vf[1], 0)) == 0) {
if (rep)
rep(file, line, "bad key data", arg);
goto skip_1;
char *qq;
if (!q) {
- if (k->k.e != KENC_BINARY) {
+ if (k->k->e != KENC_BINARY) {
if (rep)
rep(file, line, "new-style key encoding but no keyid", arg);
goto skip_2;
}
- k->id = crc32(0, k->k.u.k.k, k->k.u.k.sz);
+ k->id = crc32(0, k->k->u.k.k, k->k->u.k.sz);
k->type = xstrdup(vf[0]);
k->tag = 0;
} else {
xfree(k->tag);
xfree(k->type);
skip_2:
- key_destroy(&k->k);
+ key_drop(k->k);
skip_1:
DESTROY(k);
skip_0:;
/* --- Skip the key if it's deleted or unselected--- */
- if (KEY_EXPIRED(t, k->del) || !key_match(&k->k, kf))
+ if (KEY_EXPIRED(t, k->del) || !key_match(k->k, kf))
return (0);
/* --- Encode the key and write the easy stuff --- */
key_fulltag(k, &d);
DPUTC(&d, ' ');
- key_write(&k->k, &d, kf);
+ key_write(k->k, &d, kf);
DPUTC(&d, ' ');
dstr_write(&d, fp);
DRESET(&d);
key_attr *a;
key *k = (key *)b;
- key_destroy(&k->k);
+ if (k->k) key_drop(k->k);
xfree(k->type);
xfree(k->tag);
if (k->c)
* @uint32 id@ = keyid to set
* @const char *type@ = the type of this key
* @time_t exp@ = when the key expires
- * @int *err@ = where to store the error condition
+ * @key *kk@ = where to put the key pointer
*
- * Returns: Key block containing new data, or null if it couldn't be
- * done.
+ * Returns: Error code (one of the @KERR@ constants).
*
* Use: Attaches a new key to a key file. You must have a writable
* key file for this to work.
* key'. Be careful with `forever' keys. If I were you, I'd
* use a more sophisticated key management system than this for
* them.
- *
- * You have to set the actual key yourself.
*/
-key *key_new(key_file *f, uint32 id, const char *type, time_t exp, int *err)
+int key_new(key_file *f, uint32 id, const char *type, time_t exp, key **kk)
{
key *k = 0;
time_t t = time(0);
k = CREATE(key);
k->id = id;
k->tag = 0;
- k->type = xstrdup(type);
k->exp = k->del = exp;
k->c = 0;
- k->k.e = 0;
+ k->type = type; /* temporarily */
sym_create(&k->a);
- if ((e = insert(f, k)) == 0)
- f->f |= KF_MODIFIED;
- else {
- xfree(k->type);
+ if ((e = insert(f, k)) != 0)
DESTROY(k);
- k = 0;
+ else {
+ k->k = key_newstring(KCAT_SHARE, "<unset>");
+ k->type = xstrdup(type);
+ *kk = k;
+ f->f |= KF_MODIFIED;
}
}
- *err = e;
- return (k);
+
+ return (e);
}
/*----- That's all, folks -------------------------------------------------*/
* @const char *tag@ = pointer to tag string
* @dstr *d@ = pointer to string for full tag name
* @key **k@ = where to store the key pointer
- * @key_data **kd@ = where to store the key data pointer
+ * @key_data ***kd@ = where to store the key data pointer
*
* Returns: Zero if OK, nonzero if it failed.
*
* qualified by the names of subkeys, separated by dots. Hence,
* a qualified tag is ID|TAG[.TAG...]. The various result
* pointers can be null to indicate that the result isn't
- * interesting.
+ * interesting.
*/
-int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data **kd)
+int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data ***kd)
{
dstr dd = DSTR_INIT;
const char *q;
key *kk;
- key_data *kkd;
+ key_data **kkd;
/* --- Find the end of the base tag --- */
/* --- Now dig through the rest of the tag --- */
- while (q && *q) {
-
- /* --- Stick on the next bit of the fullqtag --- */
-
- DRESET(&dd);
- while (*q && *q != '.') {
- DPUTC(&dd, *q);
- q++;
+ if (q) {
+ while (*q) {
+ key_struct *ks;
+
+ /* --- Stick on the next bit of the fullqtag --- */
+
+ DRESET(&dd);
+ while (*q && *q != '.') {
+ DPUTC(&dd, *q);
+ q++;
+ }
+ DPUTZ(&dd);
+ if (d) {
+ DPUTC(d, '.');
+ DPUTD(d, &dd);
+ }
+
+ /* --- Look up the subkey --- */
+
+ if ((*kkd)->e != KENC_STRUCT) {
+ kkd = 0;
+ break;
+ }
+ if ((ks = sym_find(&(*kkd)->u.s, dd.buf, -1, 0, 0)) == 0) {
+ kkd = 0;
+ break;
+ }
+ kkd = &ks->k;
}
- DPUTZ(&dd);
- if (d) {
- DPUTC(d, '.');
- DPUTD(d, &dd);
- }
-
- /* --- Look up the subkey --- */
-
- if (kkd->e != KENC_STRUCT) {
- kkd = 0;
- break;
- }
- if ((kkd = key_structfind(kkd, dd.buf)) == 0)
- break;
}
/* --- Return the results --- */
+ dstr_destroy(&dd);
if (!kkd)
return (-1);
- dstr_destroy(&dd);
if (kd)
*kd = kkd;
return (0);
size_t n, i;
sym_iter ai;
- if (!key_encode(&k->k, &d, kf))
+ if (!key_encode(k->k, &d, kf))
goto done;
rc = 1;
GH_HASHSTR(h, "catacomb-key-fingerprint:");
/* -*-c-*-
*
- * $Id: key-pack.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
*
* Packing and unpacking key data
*
/* --- @key_pack@ --- *
*
* Arguments: @key_packdef *kp@ = pointer to packing structure
- * @key_data *kd@ = pointer to destination key data
+ * @key_data **kd@ = where to put the key data pointer
* @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)
+int key_pack(key_packdef *kp, key_data **kd, dstr *d)
{
- switch (kp->kd.e & KF_ENCMASK) {
+ switch (kp->e & KF_ENCMASK) {
/* --- Binary and integer keys are easy --- */
- case KENC_BINARY:
- kd->u.k = *(key_bin *)kp->p;
+ case KENC_BINARY: {
+ key_bin *b = kp->p;
+ *kd = key_newbinary(kp->e, b->k, b->sz);
return (0);
+ }
case KENC_MP:
- kd->u.m = *(mp **)kp->p;
+ *kd = key_newmp(kp->e, *(mp **)kp->p);
return (0);
case KENC_STRING:
- kd->u.p = *(char **)kp->p;
+ *kd = key_newstring(kp->e, *(char **)kp->p);
return (0);
case KENC_EC:
- kd->u.e = *(ec *)kp->p;
+ *kd = key_newec(kp->e, (ec *)kp->p);
return (0);
/* --- Encrypted keys are a little tricky --- *
*/
case KENC_ENCRYPT: {
- key_data kkd;
+ 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);
+ err = key_plock(kd, kkd, d->buf);
+ key_drop(kkd);
}
return (err);
}
key_packstruct *p;
size_t l = d->len;
- key_structure(kd);
+ *kd = key_newstruct();
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);
+ if ((err = key_pack(&p->kp, &kkd, d)) != 0) {
+ key_drop(*kd);
return (err);
}
+ key_structsteal(*kd, p->name, kkd);
}
d->len = l;
d->buf[l] = 0;
return (0);
}
+ default:
+ abort();
}
-
- return (KERR_BADTYPE);
}
/* --- @key_unpack@ --- *
int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
{
- unsigned e = kp->kd.e & KF_ENCMASK;
+ unsigned e = kp->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;
+ if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
+ if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0)
goto fail;
- }
- kd = &kp->kd;
- kd->e |= KF_TEMP;
+ kd = kp->kd;
}
/* --- Ensure that the key has the right type --- */
/* --- Find and unpack the subkey --- */
if ((kkd = key_structfind(kd, p->name)) == 0) {
- if (!(p->kp.kd.e & KF_OPT)) {
+ if (!(p->kp.e & KF_OPT)) {
err = KERR_NOTFOUND;
goto tidy;
}
key_unpackdone(&q->kp);
goto fail;
}
+
+ default:
+ abort();
}
return (0);
/* --- Something went wrong --- */
fail:
- if (kd == &kp->kd)
- key_destroy(kd);
+ if (kp->kd) {
+ key_drop(kp->kd);
+ kp->kd = 0;
+ }
return (err);
}
void key_unpackdone(key_packdef *kp)
{
- if (kp->kd.e & KF_TEMP)
- key_destroy(&kp->kd);
- if ((kp->kd.e & KF_ENCMASK) == KENC_STRUCT) {
+ if (kp->kd) {
+ key_drop(kp->kd);
+ kp->kd = 0;
+ }
+ if ((kp->e & KF_ENCMASK) == KENC_STRUCT) {
key_packstruct *p;
for (p = kp->p; p->name; p++)
key_unpackdone(&p->kp);
/* --- @key_lock@ --- *
*
- * Arguments: @key_data *kt@ = destination block
- * @key_data *k@ = source key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
* @const void *e@ = secret to encrypt key with
* @size_t esz@ = size of the secret
*
* Use: Encrypts a key data block using a secret.
*/
-void key_lock(key_data *kt, key_data *k, const void *e, size_t esz)
+void key_lock(key_data **kt, key_data *k, const void *e, size_t esz)
{
dstr d = DSTR_INIT;
octet b[RMD160_HASHSZ * 2];
/* --- Sanity check --- */
+ if (k) key_incref(k); else k = *kt;
assert(((void)"Key data is already encrypted",
(k->e & KF_ENCMASK) != KENC_ENCRYPT));
rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ);
d.len += RMD160_HASHSZ * 2;
key_encode(k, &d, 0);
- if (k == kt)
- key_destroy(k);
m = (octet *)d.buf + RMD160_HASHSZ * 2;
msz = d.len - RMD160_HASHSZ * 2;
/* --- Done --- */
BURN(b);
- key_encrypted(kt, d.buf, d.len);
+ *kt = key_newencrypted(0, d.buf, d.len);
+ key_drop(k);
dstr_destroy(&d);
}
/* --- @key_unlock@ --- *
*
- * Arguments: @key_data *kt@ = target block
- * @key_data *k@ = source key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
* @const void *e@ = secret to decrypt the block with
* @size_t esz@ = size of the secret
*
* Use: Unlocks a key using a secret.
*/
-int key_unlock(key_data *kt, key_data *k, const void *e, size_t esz)
+int key_unlock(key_data **kt, key_data *k, const void *e, size_t esz)
{
octet b[RMD160_HASHSZ * 2];
octet *p = 0;
int rc;
+ int drop = 0;
+ key_data *kd;
rmd160_mgfctx r;
blowfish_cbcctx c;
rmd160_mackey mk;
/* --- Sanity check --- */
+ if (!k) { k = *kt; drop = 1; }
assert(((void)"Key data isn't encrypted",
(k->e & KF_ENCMASK) == KENC_ENCRYPT));
/* --- Decode the key data into the destination buffer --- */
- if (k == kt)
- key_destroy(k);
- if (key_decode(p, sz, kt)) {
+ if ((kd = key_decode(p, sz)) == 0) {
rc = KERR_MALFORMED;
goto fail;
}
+ *kt = kd;
/* --- Done --- */
xfree(p);
+ if (drop) key_drop(k);
return (0);
/* --- Tidy up if things went wrong --- */
/* --- @key_plock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
- * @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
+ * @const char *tag@ = tag to use for passphrase
*
* Returns: Zero if successful, a @KERR@ error code on failure.
*
* Use: Locks a key by encrypting it with a passphrase.
*/
-int key_plock(const char *tag, key_data *k, key_data *kt)
+int key_plock(key_data **kt, key_data *k, const char *tag)
{
char buf[256];
/* --- @key_punlock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
- * @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * Arguments: @key_data **kt@ = where to store the destination pointer
+ * @key_data *k@ = source key data block or null to use @*kt@
+ * @const char *tag@ = tag to use for passphrase
*
* Returns: Zero if it worked, a @KERR_@ error code on failure.
*
* Use: Unlocks a passphrase-locked key.
*/
-int key_punlock(const char *tag, key_data *k, key_data *kt)
+int key_punlock(key_data **kt, key_data *k, const char *tag)
{
char buf[256];
int rc;
return (KERR_IO);
rc = key_unlock(kt, k, buf, strlen(buf));
BURN(buf);
- if (rc == KERR_BADPASS || k == kt)
+ if (rc == KERR_BADPASS || !k)
passphrase_cancel(tag);
return (rc);
}
/* -*-c-*-
*
- * $Id: key-text.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
*
* Key textual encoding
*
/* --- @key_read@ --- *
*
* Arguments: @const char *p@ = pointer to textual key representation
- * @key_data *k@ = pointer to output block for key data
* @char **pp@ = where to store the end pointer
*
- * Returns: Zero if all went well, nonzero if there was a problem.
+ * Returns: The newly-read key data, or null if it failed.
*
* Use: Parses a textual key description.
*/
-int key_read(const char *p, key_data *k, char **pp)
+key_data *key_read(const char *p, char **pp)
{
unsigned e;
+ key_data *kd;
/* --- Read the encoding type --- *
*
else {
char *q;
if (key_readflags(p, &q, &e, 0))
- return (-1);
+ return (0);
p = q + 1;
}
/* --- Now scan the data based on the encoding type --- */
- k->e = e;
switch (e & KF_ENCMASK) {
/* --- Binary encoding --- *
base64_init(&b);
base64_decode(&b, p, sz, &d);
base64_decode(&b, 0, 0, &d);
- k->u.k.k = sub_alloc(d.len);
- k->u.k.sz = d.len;
- memcpy(k->u.k.k, d.buf, d.len);
+ kd = key_newbinary(e, d.buf, d.len);
dstr_destroy(&d);
p += sz;
} break;
case KENC_MP: {
char *q;
- mp *m = mp_readstring(k->e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0);
+ mp *m = mp_readstring(e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0);
if (!m)
- return (-1);
- k->u.m = m;
+ return (0);
+ kd = key_newmp(e, m);
+ MP_DROP(m);
p = q;
} break;
p++;
}
DPUTZ(&d);
- k->u.p = xstrdup(d.buf);
+ kd = key_newstring(e, d.buf);
dstr_destroy(&d);
} break;
*/
case KENC_EC: {
+ ec pt = EC_INIT;
qd_parse qd;
qd.p = p;
qd.e = 0;
- EC_CREATE(&k->u.e);
- if (!ec_ptparse(&qd, &k->u.e))
- return (-1);
+ if (!ec_ptparse(&qd, &pt))
+ return (0);
+ kd = key_newec(e, &pt);
+ EC_DESTROY(&pt);
p = qd.p;
} break;
case KENC_STRUCT: {
dstr d = DSTR_INIT;
+ key_data *nkd;
char *q;
/* --- Read the opening bracket --- */
- k->e &= KF_ENCMASK;
+ kd = key_newstruct();
if (*p != '[')
- return (-1);
+ return (0);
p++;
- sym_create(&k->u.s);
/* --- Read named key subparts --- */
for (;;) {
size_t sz;
- key_struct *ks;
/* --- Stop if there's a close-bracket --- *
*
DPUTM(&d, p, sz);
DPUTZ(&d);
- /* --- Add an appropriate block to the key table --- *
- *
- * Simply destroy old data if there's already a match.
- */
-
- {
- unsigned f;
- ks = sym_find(&k->u.s, d.buf, d.len, sizeof(*ks), &f);
- if (f)
- key_destroy(&ks->k);
- }
-
/* --- Read the key data for the subkey --- */
- if (key_read(q + 1, &ks->k, &q)) {
- sym_remove(&k->u.s, ks);
+ if ((nkd = key_read(q + 1, &q)) == 0)
goto fail;
- }
+ key_structsteal(kd, d.buf, nkd);
p = q;
/* --- Read the comma or close-bracket --- */
fail:
dstr_destroy(&d);
- key_destroy(k);
- return (-1);
+ return (0);
} break;
/* --- Anything else is unknown --- */
default:
- return (-1);
+ return (0);
}
/* --- Return the end pointer --- */
+ kd->e = e;
if (pp)
*pp = (char *)p;
- return (0);
+ return (kd);
}
/* --- @key_write@ --- *
rc = 1;
break;
case KENC_STRUCT: {
- sym_iter i;
- key_struct *ks;
+ key_subkeyiter i;
+ const char *tag;
char del = 0;
size_t n = d->len;
DPUTS(d, "struct:[");
- for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
size_t o = d->len;
if (del)
DPUTC(d, del);
- DPUTS(d, SYM_NAME(ks));
+ DPUTS(d, tag);
DPUTC(d, '=');
- if (!key_write(&ks->k, d, kf))
+ if (!key_write(k, d, kf))
d->len = o;
else {
del = ',';
/* --- The key data itself --- */
- key_data k; /* The actual key data */
+ key_data *k; /* The actual key data */
/* --- Other attributes and commentary --- */
* @uint32 id@ = keyid to set
* @const char *type@ = the type of this key
* @time_t exp@ = when the key expires
- * @int *err@ = where to store the error condition
+ * @key *kk@ = where to put the key pointer
*
- * Returns: Key block containing new data, or null if it couldn't be
- * done.
+ * Returns: Error code (one of the @KERR@ constants).
*
* Use: Attaches a new key to a key file. You must have a writable
* key file for this to work.
* You have to set the actual key yourself.
*/
-extern key *key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/,
- time_t /*exp*/, int */*err*/);
+extern int key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/,
+ time_t /*exp*/, key **/*kk*/);
/* --- @key_delete@ --- *
*
extern int key_settag(key_file */*f*/, key */*k*/, const char */*tag*/);
+/* --- @key_setkeydata@ --- *
+ *
+ * Arguments: @key_file *kf@ = pointer to key file
+ * @key *k@ = pointer to key
+ * @key_data *kd@ = new key data
+ *
+ * Returns: Zero on success, or a @KERR_@ error code on failure.
+ *
+ * Use: Sets the key data for a key.
+ */
+
+extern int key_setkeydata(key_file */*kf*/, key */*k*/, key_data */*kd*/);
+
/* --- @key_fulltag@ --- *
*
* Arguments: @key *k@ = pointer to key
* @const char *tag@ = pointer to tag string
* @dstr *d@ = pointer to string for full tag name
* @key **k@ = where to store the key pointer
- * @key_data **kd@ = where to store the key data pointer
+ * @key_data ***kd@ = where to store the key data pointer
*
* Returns: Zero if OK, nonzero if it failed.
*
*/
extern int key_qtag(key_file */*f*/, const char */*tag*/,
- dstr */*d*/, key **/*k*/, key_data **/*kd*/);
+ dstr */*d*/, key **/*k*/, key_data ***/*kd*/);
/* --- @key_getattr@ --- *
*
/* --- @dolock@ --- *
*
* Arguments: @keyopts *k@ = key generation options
- * @key_data *kd@ = pointer to key data to lock
+ * @key_data **kd@ = pointer to key data to lock
* @const char *t@ = tag suffix or null
*
* Returns: ---
* Use: Does passphrase locking on new keys.
*/
-static void dolock(keyopts *k, key_data *kd, const char *t)
+static void dolock(keyopts *k, key_data **kd, const char *t)
{
if (!(k->f & f_lock))
return;
if (t)
dstr_putf(&k->tag, ".%s", t);
- if (key_plock(k->tag.buf, kd, kd))
+ if (key_plock(kd, 0, k->tag.buf))
die(EXIT_FAILURE, "couldn't lock key");
}
-/* --- @mpkey@ --- *
- *
- * Arguments: @key_data *kd@ = pointer to parent key block
- * @const char *tag@ = pointer to tag string
- * @mp *m@ = integer to store
- * @unsigned f@ = flags to set
- *
- * Returns: ---
- *
- * Use: Sets a multiprecision integer subkey.
- */
-
-static void mpkey(key_data *kd, const char *tag, mp *m, unsigned f)
-{
- key_data *kkd = key_structcreate(kd, tag);
- key_mp(kkd, m);
- kkd->e |= f;
-}
-
/* --- @copyparam@ --- *
*
* Arguments: @keyopts *k@ = pointer to key options
/* --- Run through the checklist --- */
while (*pp) {
- key_data *kd = key_structfind(&k->p->k, *pp);
+ key_data *kd = key_structfind(k->p->k, *pp);
if (!kd)
die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp);
if ((kd->e & KF_CATMASK) != KCAT_SHARE)
kf.f = KCAT_SHARE;
kf.m = KF_CATMASK;
- if (!key_copy(&k->k->k, &k->p->k, &kf))
- die(EXIT_FAILURE, "unexpected failure while copying parameters");
+ key_setkeydata(k->kf, k->k, k->p->k);
/* --- Copy over attributes --- */
k = key_bytype(kf, "catacomb-rand");
if (k) {
- key_data *kd = &k->k, kkd;
+ key_data *kd = k->k, *kkd;
+ key_incref(kd);
again:
switch (kd->e & KF_ENCMASK) {
case KENC_ENCRYPT: {
dstr d = DSTR_INIT;
key_fulltag(k, &d);
- if (key_punlock(d.buf, kd, &kkd))
+ if (key_punlock(&kkd, kd, d.buf))
die(EXIT_FAILURE, "error unlocking key `%s'", d.buf);
dstr_destroy(&d);
- kd = &kkd;
+ key_drop(kd);
+ kd = kkd;
} goto again;
default: {
dstr d = DSTR_INIT;
/* --- Key the generator --- */
rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz);
- if (kd == &kkd)
- key_destroy(&kkd);
+ key_drop(kd);
}
}
{
unsigned sz;
unsigned m;
+ key_data *kd;
octet *p;
if (!k->bits)
m = (1 << (((k->bits - 1) & 7) + 1)) - 1;
k->r->ops->fill(k->r, p, sz);
*p &= m;
- key_binary(&k->k->k, p, sz);
- k->k->k.e |= KCAT_SYMM | KF_BURN;
+ kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
memset(p, 0, sz);
+ dolock(k, &kd, 0);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
sub_free(p, sz);
- dolock(k, &k->k->k, 0);
}
static void alg_des(keyopts *k)
{
unsigned sz;
octet *p;
+ key_data *kd;
int i;
if (!k->bits)
x = x ^ (x >> 1);
p[i] = (p[i] & 0xfe) | (x & 0x01);
}
- key_binary(&k->k->k, p, sz);
- k->k->k.e |= KCAT_SYMM | KF_BURN;
+ kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
memset(p, 0, sz);
+ dolock(k, &kd, 0);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
sub_free(p, sz);
- dolock(k, &k->k->k, 0);
}
static void alg_rsa(keyopts *k)
{
rsa_priv rp;
- key_data *kd;
+ key_data *kd, *kkd;
/* --- Sanity checking --- */
/* --- Allrighty then --- */
- kd = &k->k->k;
- key_structure(kd);
- mpkey(kd, "n", rp.n, KCAT_PUB);
- mpkey(kd, "e", rp.e, KCAT_PUB);
-
- kd = key_structcreate(kd, "private");
- key_structure(kd);
- mpkey(kd, "d", rp.d, KCAT_PRIV | KF_BURN);
- mpkey(kd, "p", rp.p, KCAT_PRIV | KF_BURN);
- mpkey(kd, "q", rp.q, KCAT_PRIV | KF_BURN);
- mpkey(kd, "q-inv", rp.q_inv, KCAT_PRIV | KF_BURN);
- mpkey(kd, "d-mod-p", rp.dp, KCAT_PRIV | KF_BURN);
- mpkey(kd, "d-mod-q", rp.dq, KCAT_PRIV | KF_BURN);
- dolock(k, kd, "private");
-
+ kd = key_newstruct();
+ key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n));
+ key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e));
+
+ kkd = key_newstruct();
+ key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d));
+ key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p));
+ key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q));
+ key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv));
+ key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp));
+ key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
rsa_privfree(&rp);
}
size_t sz;
dstr d = DSTR_INIT;
base64_ctx c;
- key_data *kd = &k->k->k;
+ key_data *kd;
dsa_seed ds;
/* --- Choose appropriate bit lengths if necessary --- */
if (!k->qbits)
k->qbits = 160;
if (!k->bits)
- k->bits = 768;
+ k->bits = 1024;
/* --- Allocate a seed block --- */
/* --- Store the parameters --- */
- key_structure(kd);
- mpkey(kd, "q", dp.q, KCAT_SHARE);
- mpkey(kd, "p", dp.p, KCAT_SHARE);
- mpkey(kd, "g", dp.g, KCAT_SHARE);
+ kd = key_newstruct();
+ key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
+ key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
+ key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
mp_drop(dp.q);
mp_drop(dp.p);
mp_drop(dp.g);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
/* --- Store the seed for future verification --- */
c.indent = "";
base64_encode(&c, ds.p, ds.sz, &d);
base64_encode(&c, 0, 0, &d);
+ DPUTZ(&d);
key_putattr(k->kf, k->k, "seed", d.buf);
DRESET(&d);
dstr_putf(&d, "%u", ds.count);
mp *q, *p, *g;
mp *x, *y;
mpmont mm;
- key_data *kd = &k->k->k;
+ key_data *kd, *kkd;
/* --- Get the shared parameters --- */
alg_dsaparam(k);
+ key_split(&k->k->k); kd = k->k->k;
q = getmp(kd, "q");
p = getmp(kd, "p");
g = getmp(kd, "g");
/* --- Store everything away --- */
- mpkey(kd, "y", y, KCAT_PUB);
+ key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
- kd = key_structcreate(kd, "private");
- key_structure(kd);
- mpkey(kd, "x", x, KCAT_PRIV | KF_BURN);
- dolock(k, kd, "private");
+ kkd = key_newstruct();
+ key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
mp_drop(x); mp_drop(y);
}
static void alg_dhparam(keyopts *k)
{
static const char *pl[] = { "p", "q", "g", 0 };
- key_data *kd = &k->k->k;
+ key_data *kd;
if (!copyparam(k, pl)) {
dh_param dp;
int rc;
die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed");
done:
- key_structure(kd);
- mpkey(kd, "p", dp.p, KCAT_SHARE);
- mpkey(kd, "q", dp.q, KCAT_SHARE);
- mpkey(kd, "g", dp.g, KCAT_SHARE);
+ kd = key_newstruct();
+ key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
+ key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
+ key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
mp_drop(dp.q);
mp_drop(dp.p);
mp_drop(dp.g);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
}
}
mp *x, *y;
mp *p, *q, *g;
mpmont mm;
- key_data *kd = &k->k->k;
+ key_data *kd, *kkd;
/* --- Get the shared parameters --- */
alg_dhparam(k);
+ key_split(&k->k->k); kd = k->k->k;
p = getmp(kd, "p");
q = getmp(kd, "q");
g = getmp(kd, "g");
/* --- Store everything away --- */
- mpkey(kd, "y", y, KCAT_PUB);
+ key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
- kd = key_structcreate(kd, "private");
- key_structure(kd);
- mpkey(kd, "x", x, KCAT_PRIV | KF_BURN);
- dolock(k, kd, "private");
+ kkd = key_newstruct();
+ key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
mp_drop(x); mp_drop(y);
}
static void alg_bbs(keyopts *k)
{
bbs_priv bp;
- key_data *kd;
+ key_data *kd, *kkd;
/* --- Sanity checking --- */
/* --- Allrighty then --- */
- kd = &k->k->k;
- key_structure(kd);
- mpkey(kd, "n", bp.n, KCAT_PUB);
+ kd = key_newstruct();
+ key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n));
- kd = key_structcreate(kd, "private");
- key_structure(kd);
- mpkey(kd, "p", bp.p, KCAT_PRIV | KF_BURN);
- mpkey(kd, "q", bp.q, KCAT_PRIV | KF_BURN);
- dolock(k, kd, "private");
+ kkd = key_newstruct();
+ key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p));
+ key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
bbs_privfree(&bp);
}
qd_parse qd;
group *g;
const char *e;
- key_data *kd = &k->k->k;
+ key_data *kd;
/* --- Decide on a field --- */
/* --- Write out the answer --- */
- key_structure(kd);
- mpkey(kd, "p", gb.p, KCAT_SHARE);
- mpkey(kd, "q", gb.q, KCAT_SHARE);
- mpkey(kd, "g", gb.g, KCAT_SHARE);
+ kd = key_newstruct();
+ key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p));
+ key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q));
+ key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g));
mp_drop(gb.q);
mp_drop(gb.p);
mp_drop(gb.g);
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
}
}
mp *x, *y;
mp *p, *q, *g;
gfreduce r;
- key_data *kd = &k->k->k;
+ key_data *kd, *kkd;
/* --- Get the shared parameters --- */
alg_binparam(k);
+ key_split(&k->k->k); kd = k->k->k;
p = getmp(kd, "p");
q = getmp(kd, "q");
g = getmp(kd, "g");
/* --- Store everything away --- */
- mpkey(kd, "y", y, KCAT_PUB);
+ key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
- kd = key_structcreate(kd, "private");
- key_structure(kd);
- mpkey(kd, "x", x, KCAT_PRIV | KF_BURN);
- dolock(k, kd, "private");
+ kkd = key_newstruct();
+ key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
mp_drop(x); mp_drop(y);
}
if (!copyparam(k, pl)) {
ec_info ei;
const char *e;
- key_data *kd = &k->k->k;
+ key_data *kd;
/* --- Decide on a curve --- */
/* --- Write out the answer --- */
- key_structure(kd);
- kd = key_structcreate(kd, "curve");
- key_string(kd, k->curve);
- kd->e |= KCAT_SHARE;
+ kd = key_newstruct();
+ key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve));
+ key_setkeydata(k->kf, k->k, kd);
+ key_drop(kd);
}
}
static void alg_ec(keyopts *k)
{
- key_data *kd = &k->k->k;
+ key_data *kd;
key_data *kkd;
mp *x = MP_NEW;
ec p = EC_INIT;
/* --- Get the curve --- */
alg_ecparam(k);
+ key_split(&k->k->k); kd = k->k->k;
if ((kkd = key_structfind(kd, "curve")) == 0)
die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')");
if ((kkd->e & KF_ENCMASK) != KENC_STRING)
/* --- Store everything away --- */
- kkd = key_structcreate(kd, "p");
- key_ec(kkd, &p);
- kkd->e |= KCAT_PUB;
- kkd = key_structcreate(kd, "private");
- key_structure(kkd);
- mpkey(kkd, "x", x, KCAT_PRIV | KF_BURN);
- dolock(k, kkd, "private");
+ key_structsteal(kd, "p", key_newec(KCAT_PUB, &p));
+
+ kkd = key_newstruct();
+ key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+ dolock(k, &kkd, "private");
+ key_structsteal(kd, "private", kkd);
/* --- Done --- */
for (;;) {
uint32 id = rand_global.ops->word(&rand_global);
int err;
- k.k = key_new(&f, id, argv[optind], exp, &err);
- if (k.k)
+ if ((err = key_new(&f, id, argv[optind], exp, &k.k)) == 0)
break;
- if (err != KERR_DUPID)
+ else if (err != KERR_DUPID)
die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err));
}
if (ptag) {
if ((k.p = key_bytag(&f, ptag)) == 0)
die(EXIT_FAILURE, "parameter key `%s' not found", ptag);
- if ((k.p->k.e & KF_ENCMASK) != KENC_STRUCT)
+ if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT)
die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag);
}
/* --- Done --- */
+ dstr_destroy(&k.tag);
doclose(&f);
return (0);
}
if (o->v <= 3)
fputs(" encrypted\n", stdout);
else {
- key_data kd;
- if (key_punlock(d->buf, k, &kd))
+ key_data *kd;
+ if (key_punlock(&kd, k, d->buf))
printf(" <failed to unlock %s>\n", d->buf);
else {
fputs(" encrypted", stdout);
- showkeydata(&kd, ind, o, d);
- key_destroy(&kd);
+ showkeydata(kd, ind, o, d);
+ key_drop(kd);
}
}
break;
*/
case KENC_STRUCT: {
- sym_iter i;
- key_struct *ks;
+ key_subkeyiter i;
+ const char *tag;
size_t n = d->len;
fputs(" {\n", stdout);
- for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
- if (!key_match(&ks->k, &o->kf))
+ for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
+ if (!key_match(k, &o->kf))
continue;
INDENT(ind + 2);
- printf("%s =", SYM_NAME(ks));
+ printf("%s =", tag);
d->len = n;
- dstr_putf(d, ".%s", SYM_NAME(ks));
- showkeydata(&ks->k, ind + 2, o, d);
+ dstr_putf(d, ".%s", tag);
+ showkeydata(k, ind + 2, o, d);
}
INDENT(ind);
fputs("}\n", stdout);
/* --- Skip the key if the filter doesn't match --- */
- if (!key_match(&k->k, &o->kf))
+ if (!key_match(k->k, &o->kf))
return;
/* --- Sort out the expiry and deletion times --- */
dstr d = DSTR_INIT;
fputs("key:", stdout);
key_fulltag(k, &d);
- showkeydata(&k->k, 0, o, &d);
+ showkeydata(k->k, 0, o, &d);
dstr_destroy(&d);
}
{
key_file f;
key *k;
- key_data *kd;
+ key_data **kd;
dstr d = DSTR_INIT;
if (argc != 2)
doopen(&f, KOPEN_WRITE);
if (key_qtag(&f, argv[1], &d, &k, &kd))
die(EXIT_FAILURE, "key `%s' not found", argv[1]);
- if (kd->e == KENC_ENCRYPT && key_punlock(d.buf, kd, kd))
+ if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf))
die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
- if (key_plock(d.buf, kd, kd))
+ if (key_plock(kd, 0, d.buf))
die(EXIT_FAILURE, "failed to lock key `%s'", d.buf);
f.f |= KF_MODIFIED;
doclose(&f);
{
key_file f;
key *k;
- key_data *kd;
+ key_data **kd;
dstr d = DSTR_INIT;
if (argc != 2)
doopen(&f, KOPEN_WRITE);
if (key_qtag(&f, argv[1], &d, &k, &kd))
die(EXIT_FAILURE, "key `%s' not found", argv[1]);
- if (kd->e != KENC_ENCRYPT)
+ if ((*kd)->e != KENC_ENCRYPT)
die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf);
- if (kd->e == KENC_ENCRYPT && key_punlock(d.buf, kd, kd))
+ if (key_punlock(kd, 0, d.buf))
die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
f.f |= KF_MODIFIED;
doclose(&f);
/* -*-c-*-
*
- * $Id: mparena.c,v 1.7 2004/04/08 01:36:15 mdw Exp $
+ * $Id$
*
* Allocation and freeing of MP buffers
*
* itself.
*/
-/* #define MPARENA_TRIVIAL */
+#define MPARENA_TRIVIAL
/* --- @MPARENA_DEBUG@ --- *
*
/* -*-c-*-
*
- * $Id: rspit.c,v 1.21 2004/04/21 00:37:32 mdw Exp $
+ * $Id$
*
* Spit out random numbers
*
/* --- Read the key data --- */
- if ((kk->k.e & KF_ENCMASK) != KENC_STRUCT)
+ if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT)
die(EXIT_FAILURE, "key is not structured");
- if ((kd = key_structfind(&kk->k, "n")) == 0)
+ if ((kd = key_structfind(kk->k, "n")) == 0)
die(EXIT_FAILURE, "key has no subkey `n'");
if ((kd->e & KF_ENCMASK) != KENC_MP)
die(EXIT_FAILURE, "incompatible subkey encoding");