From ef13e9a46baaa347014ac236f36a2536f055b108 Mon Sep 17 00:00:00 2001 From: mdw Date: Thu, 22 Sep 2005 11:03:20 +0000 Subject: [PATCH] Major and incompatible overhaul of key_data representation. Fix leaks. --- catcrypt.c | 4 + cc-sig.c | 1 + cookie.c | 4 +- exp.h | 3 +- key-attr.c | 22 ++++ key-binary.c | 65 +++++----- key-data.c | 416 +++++++++++++++++++++++++++++++++-------------------------- key-data.h | 231 +++++++++++++++++++++------------ key-fetch.c | 16 ++- key-file.c | 15 ++- key-io.c | 41 +++--- key-misc.c | 62 +++++---- key-pack.c | 69 +++++----- key-pass.c | 45 ++++--- key-text.c | 74 +++++------ key.h | 28 ++-- keyutil.c | 258 ++++++++++++++++++------------------ mparena.c | 4 +- rspit.c | 6 +- 19 files changed, 752 insertions(+), 612 deletions(-) diff --git a/catcrypt.c b/catcrypt.c index 967730a..4c343a4 100644 --- a/catcrypt.c +++ b/catcrypt.c @@ -313,6 +313,7 @@ static int encrypt(int argc, char *argv[]) freeenc(e); if (s) freesig(s); freekem(km); + if (fp != stdin) fclose(fp); if (of) fclose(ofp); key_close(&kf); dstr_destroy(&d); @@ -459,6 +460,7 @@ static int decrypt(int argc, char *argv[]) key_fulltag(sk, &d); printf("INFO good-signature %s\n", d.buf); } + freesig(s); } else if (verb) printf("INFO no-signature\n"); @@ -499,6 +501,7 @@ static int decrypt(int argc, char *argv[]) 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)); @@ -541,6 +544,7 @@ static int decrypt(int argc, char *argv[]) GC_DESTROY(cx); GM_DESTROY(m); freekem(km); + if (fp != stdin) fclose(fp); if (of) fclose(ofp); key_close(&kf); dstr_destroy(&d); diff --git a/cc-sig.c b/cc-sig.c index 027fa52..45679ce 100644 --- a/cc-sig.c +++ b/cc-sig.c @@ -382,6 +382,7 @@ static void dsa_sigdestroy(sig *s) 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 = { diff --git a/cookie.c b/cookie.c index 9b32389..c988541 100644 --- a/cookie.c +++ b/cookie.c @@ -188,9 +188,9 @@ static gmac *getmac(key *k, const char *app) /* --- 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)); } diff --git a/exp.h b/exp.h index a8b3812..e729e8c 100644 --- a/exp.h +++ b/exp.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: exp.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ + * $Id$ * * Generalized exponentiation * @@ -397,6 +397,7 @@ exp_simul_done: \ for (i = 1; i < vn; i++) \ EXP_DROP(v[i]); \ xfree(v); \ + xfree(e.s); \ } while (0) /*----- Functions provided ------------------------------------------------*/ diff --git a/key-attr.c b/key-attr.c index 27f4490..2d33b9c 100644 --- a/key-attr.c +++ b/key-attr.c @@ -179,6 +179,28 @@ int key_putattr(key_file *f, key *k, const char *n, const char *v) 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 diff --git a/key-binary.c b/key-binary.c index dc8c701..087d992 100644 --- a/key-binary.c +++ b/key-binary.c @@ -47,17 +47,17 @@ * * 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 --- * @@ -70,8 +70,7 @@ int key_decode(const void *p, size_t sz, key_data *k) e = LOAD16(q); psz = LOAD16(q + 2); if (psz + 4 > sz) - return (-1); - k->e = e; + return (0); /* --- Now decide what to do --- */ @@ -81,51 +80,51 @@ int key_decode(const void *p, size_t sz, key_data *k) 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) { @@ -142,20 +141,15 @@ int key_decode(const void *p, size_t sz, key_data *k) /* --- 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; } @@ -166,19 +160,20 @@ int key_decode(const void *p, size_t sz, key_data *k) 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@ --- * @@ -297,7 +292,7 @@ int key_encode(key_data *k, dstr *d, const key_filter *kf) 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; diff --git a/key-data.c b/key-data.c index 8bb9099..a0644a1 100644 --- a/key-data.c +++ b/key-data.c @@ -43,114 +43,231 @@ #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@ --- * @@ -171,79 +288,86 @@ key_data *key_structfind(key_data *k, const char *tag) 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 @@ -266,101 +390,23 @@ int key_do(key_data *k, const key_filter *kf, dstr *d, 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 -------------------------------------------------*/ diff --git a/key-data.h b/key-data.h index 5644834..2a8620a 100644 --- a/key-data.h +++ b/key-data.h @@ -67,6 +67,7 @@ typedef struct key_bin { 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 */ @@ -78,14 +79,17 @@ typedef struct key_data { 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 { @@ -137,8 +141,7 @@ enum { /* --- 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 --- */ @@ -209,78 +212,77 @@ extern int key_match(key_data */*k*/, const key_filter */*kf*/); /*----- 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@ --- * * @@ -294,31 +296,106 @@ extern void key_structure(key_data */*k*/); 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 @@ -337,34 +414,19 @@ extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/, 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@ --- * * @@ -377,8 +439,7 @@ extern int key_read(const char */*p*/, key_data */*k*/, char **/*pp*/); * 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 -----------------------------------------------*/ @@ -386,14 +447,13 @@ extern int key_write(key_data */*k*/, dstr */*d*/, * * 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@ --- * * @@ -414,7 +474,7 @@ extern int key_encode(key_data */*k*/, dstr */*d*/, /* --- @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. @@ -422,7 +482,7 @@ extern int key_encode(key_data */*k*/, dstr */*d*/, * 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@ --- * * @@ -453,8 +513,8 @@ extern void key_unpackdone(key_packdef */*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 * @@ -463,13 +523,13 @@ extern void key_unpackdone(key_packdef */*kp*/); * 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 * @@ -478,35 +538,36 @@ extern void key_lock(key_data */*kt*/, key_data */*k*/, * 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 -------------------------------------------------*/ diff --git a/key-fetch.c b/key-fetch.c index d80382f..e28b9b2 100644 --- a/key-fetch.c +++ b/key-fetch.c @@ -80,8 +80,9 @@ key_packdef *key_fetchinit(const key_fetchdef *kf, /* --- 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 --- */ @@ -107,7 +108,8 @@ key_packdef *key_fetchinit(const key_fetchdef *kf, 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 { @@ -153,7 +155,7 @@ int key_fetch(key_packdef *kp, key *k) 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); } @@ -173,13 +175,13 @@ int key_fetch(key_packdef *kp, key *k) 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); } @@ -196,8 +198,8 @@ int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag) 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); diff --git a/key-file.c b/key-file.c index 6e422b1..dc9efc0 100644 --- a/key-file.c +++ b/key-file.c @@ -197,6 +197,9 @@ int key_save(key_file *f) 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 --- * @@ -255,15 +258,15 @@ fail_shift: 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); } diff --git a/key-io.c b/key-io.c index 7ed0c2c..9d9b6ee 100644 --- a/key-io.c +++ b/key-io.c @@ -221,7 +221,7 @@ int key_merge(key_file *f, const char *file, FILE *fp, /* --- 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; @@ -239,12 +239,12 @@ int key_merge(key_file *f, const char *file, FILE *fp, 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 { @@ -313,7 +313,7 @@ int key_merge(key_file *f, const char *file, FILE *fp, xfree(k->tag); xfree(k->type); skip_2: - key_destroy(&k->k); + key_drop(k->k); skip_1: DESTROY(k); skip_0:; @@ -347,14 +347,14 @@ int key_extract(key_file *f, key *k, FILE *fp, const key_filter *kf) /* --- 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); @@ -469,7 +469,7 @@ void key_discard(key_file *f) 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) @@ -514,10 +514,9 @@ int key_close(key_file *f) * @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. @@ -532,11 +531,9 @@ int key_close(key_file *f) * 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); @@ -554,21 +551,21 @@ key *key_new(key_file *f, uint32 id, const char *type, time_t exp, int *err) 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, ""); + k->type = xstrdup(type); + *kk = k; + f->f |= KF_MODIFIED; } } - *err = e; - return (k); + + return (e); } /*----- That's all, folks -------------------------------------------------*/ diff --git a/key-misc.c b/key-misc.c index 54fdc89..6e3b441 100644 --- a/key-misc.c +++ b/key-misc.c @@ -177,7 +177,7 @@ key *key_bytag(key_file *f, const char *tag) * @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. * @@ -185,15 +185,15 @@ key *key_bytag(key_file *f, const char *tag) * 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 --- */ @@ -222,36 +222,42 @@ int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data **kd) /* --- 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); @@ -374,7 +380,7 @@ int key_fingerprint(key *k, ghash *h, const key_filter *kf) 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:"); diff --git a/key-pack.c b/key-pack.c index cc0f20a..0303dbc 100644 --- a/key-pack.c +++ b/key-pack.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: key-pack.c,v 1.3 2004/04/08 01:36:15 mdw Exp $ + * $Id$ * * Packing and unpacking key data * @@ -39,7 +39,7 @@ /* --- @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. @@ -47,23 +47,25 @@ * 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 --- * @@ -72,12 +74,11 @@ int key_pack(key_packdef *kp, key_data *kd, dstr *d) */ 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); } @@ -89,25 +90,25 @@ int key_pack(key_packdef *kp, key_data *kd, dstr *d) 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@ --- * @@ -123,18 +124,15 @@ int key_pack(key_packdef *kp, key_data *kd, dstr *d) 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 --- */ @@ -186,7 +184,7 @@ int key_unpack(key_packdef *kp, key_data *kd, dstr *d) /* --- 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; } @@ -209,6 +207,9 @@ int key_unpack(key_packdef *kp, key_data *kd, dstr *d) key_unpackdone(&q->kp); goto fail; } + + default: + abort(); } return (0); @@ -216,8 +217,10 @@ int key_unpack(key_packdef *kp, key_data *kd, dstr *d) /* --- Something went wrong --- */ fail: - if (kd == &kp->kd) - key_destroy(kd); + if (kp->kd) { + key_drop(kp->kd); + kp->kd = 0; + } return (err); } @@ -233,9 +236,11 @@ fail: 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); diff --git a/key-pass.c b/key-pass.c index 1b0997a..4fd74b1 100644 --- a/key-pass.c +++ b/key-pass.c @@ -56,8 +56,8 @@ /* --- @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 * @@ -66,7 +66,7 @@ * 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]; @@ -79,6 +79,7 @@ void key_lock(key_data *kt, key_data *k, const void *e, size_t esz) /* --- Sanity check --- */ + if (k) key_incref(k); else k = *kt; assert(((void)"Key data is already encrypted", (k->e & KF_ENCMASK) != KENC_ENCRYPT)); @@ -88,8 +89,6 @@ void key_lock(key_data *kt, key_data *k, const void *e, size_t esz) 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; @@ -119,14 +118,15 @@ void key_lock(key_data *kt, key_data *k, const void *e, size_t esz) /* --- 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 * @@ -135,11 +135,13 @@ void key_lock(key_data *kt, key_data *k, const void *e, size_t esz) * 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; @@ -148,6 +150,7 @@ int key_unlock(key_data *kt, key_data *k, const void *e, size_t esz) /* --- Sanity check --- */ + if (!k) { k = *kt; drop = 1; } assert(((void)"Key data isn't encrypted", (k->e & KF_ENCMASK) == KENC_ENCRYPT)); @@ -191,16 +194,16 @@ int key_unlock(key_data *kt, key_data *k, const void *e, size_t esz) /* --- 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 --- */ @@ -213,16 +216,16 @@ fail: /* --- @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]; @@ -235,16 +238,16 @@ int key_plock(const char *tag, key_data *k, key_data *kt) /* --- @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; @@ -253,7 +256,7 @@ int key_punlock(const char *tag, key_data *k, key_data *kt) 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); } diff --git a/key-text.c b/key-text.c index dcfe354..b13f571 100644 --- a/key-text.c +++ b/key-text.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: key-text.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ + * $Id$ * * Key textual encoding * @@ -49,17 +49,17 @@ /* --- @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 --- * * @@ -72,13 +72,12 @@ int key_read(const char *p, key_data *k, char **pp) 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 --- * @@ -97,9 +96,7 @@ int key_read(const char *p, key_data *k, char **pp) 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; @@ -111,10 +108,11 @@ int key_read(const char *p, key_data *k, char **pp) 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; @@ -143,7 +141,7 @@ int key_read(const char *p, key_data *k, char **pp) p++; } DPUTZ(&d); - k->u.p = xstrdup(d.buf); + kd = key_newstring(e, d.buf); dstr_destroy(&d); } break; @@ -154,12 +152,14 @@ int key_read(const char *p, key_data *k, char **pp) */ 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; @@ -175,21 +175,20 @@ int key_read(const char *p, key_data *k, char **pp) 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 --- * * @@ -212,24 +211,11 @@ int key_read(const char *p, key_data *k, char **pp) 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 --- */ @@ -252,21 +238,21 @@ int key_read(const char *p, key_data *k, char **pp) 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@ --- * @@ -327,19 +313,19 @@ int key_write(key_data *k, dstr *d, const key_filter *kf) 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 = ','; diff --git a/key.h b/key.h index ff3f81d..1986e8c 100644 --- a/key.h +++ b/key.h @@ -97,7 +97,7 @@ typedef struct key { /* --- The key data itself --- */ - key_data k; /* The actual key data */ + key_data *k; /* The actual key data */ /* --- Other attributes and commentary --- */ @@ -302,10 +302,9 @@ extern int key_lockfile(key_file */*f*/, const char */*file*/, * @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. @@ -324,8 +323,8 @@ extern int key_lockfile(key_file */*f*/, const char */*file*/, * 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@ --- * * @@ -451,6 +450,19 @@ extern int key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/); 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 @@ -471,7 +483,7 @@ extern void key_fulltag(key */*k*/, dstr */*d*/); * @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. * @@ -483,7 +495,7 @@ extern void key_fulltag(key */*k*/, dstr */*d*/); */ 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@ --- * * diff --git a/keyutil.c b/keyutil.c index 3be95b3..1d4bbca 100644 --- a/keyutil.c +++ b/keyutil.c @@ -201,7 +201,7 @@ typedef struct keyopts { /* --- @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: --- @@ -209,35 +209,16 @@ typedef struct keyopts { * 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 @@ -263,7 +244,7 @@ static int copyparam(keyopts *k, const char **pp) /* --- 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) @@ -275,8 +256,7 @@ static int copyparam(keyopts *k, const char **pp) 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 --- */ @@ -331,7 +311,8 @@ static void keyrand(key_file *kf, const char *id) 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) { @@ -340,10 +321,11 @@ static void keyrand(key_file *kf, const char *id) 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; @@ -355,8 +337,7 @@ static void keyrand(key_file *kf, const char *id) /* --- Key the generator --- */ rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz); - if (kd == &kkd) - key_destroy(&kkd); + key_drop(kd); } } @@ -366,6 +347,7 @@ static void alg_binary(keyopts *k) { unsigned sz; unsigned m; + key_data *kd; octet *p; if (!k->bits) @@ -378,17 +360,19 @@ static void alg_binary(keyopts *k) 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) @@ -408,17 +392,18 @@ static void alg_des(keyopts *k) 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 --- */ @@ -455,21 +440,21 @@ static void alg_rsa(keyopts *k) /* --- 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); } @@ -482,7 +467,7 @@ static void alg_dsaparam(keyopts *k) 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 --- */ @@ -490,7 +475,7 @@ static void alg_dsaparam(keyopts *k) if (!k->qbits) k->qbits = 160; if (!k->bits) - k->bits = 768; + k->bits = 1024; /* --- Allocate a seed block --- */ @@ -506,13 +491,15 @@ static void alg_dsaparam(keyopts *k) /* --- 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 --- */ @@ -521,6 +508,7 @@ static void alg_dsaparam(keyopts *k) 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); @@ -536,11 +524,12 @@ static void alg_dsa(keyopts *k) 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"); @@ -553,12 +542,12 @@ static void alg_dsa(keyopts *k) /* --- 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); } @@ -566,7 +555,7 @@ static void alg_dsa(keyopts *k) 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; @@ -628,13 +617,15 @@ static void alg_dhparam(keyopts *k) 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); } } @@ -643,11 +634,12 @@ static void alg_dh(keyopts *k) 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"); @@ -667,12 +659,12 @@ static void alg_dh(keyopts *k) /* --- 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); } @@ -680,7 +672,7 @@ static void alg_dh(keyopts *k) static void alg_bbs(keyopts *k) { bbs_priv bp; - key_data *kd; + key_data *kd, *kkd; /* --- Sanity checking --- */ @@ -697,15 +689,16 @@ static void alg_bbs(keyopts *k) /* --- 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); } @@ -718,7 +711,7 @@ static void alg_binparam(keyopts *k) qd_parse qd; group *g; const char *e; - key_data *kd = &k->k->k; + key_data *kd; /* --- Decide on a field --- */ @@ -759,13 +752,15 @@ static void alg_binparam(keyopts *k) /* --- 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); } } @@ -774,11 +769,12 @@ static void alg_bin(keyopts *k) 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"); @@ -798,12 +794,12 @@ static void alg_bin(keyopts *k) /* --- 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); } @@ -814,7 +810,7 @@ static void alg_ecparam(keyopts *k) if (!copyparam(k, pl)) { ec_info ei; const char *e; - key_data *kd = &k->k->k; + key_data *kd; /* --- Decide on a curve --- */ @@ -849,16 +845,16 @@ static void alg_ecparam(keyopts *k) /* --- 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; @@ -868,6 +864,7 @@ static void alg_ec(keyopts *k) /* --- 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) @@ -882,13 +879,12 @@ static void alg_ec(keyopts *k) /* --- 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 --- */ @@ -1158,10 +1154,9 @@ static int cmd_add(int argc, char *argv[]) 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)); } @@ -1197,7 +1192,7 @@ static int cmd_add(int argc, char *argv[]) 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); } @@ -1207,6 +1202,7 @@ static int cmd_add(int argc, char *argv[]) /* --- Done --- */ + dstr_destroy(&k.tag); doclose(&f); return (0); } @@ -1289,13 +1285,13 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) 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(" \n", d->buf); else { fputs(" encrypted", stdout); - showkeydata(&kd, ind, o, d); - key_destroy(&kd); + showkeydata(kd, ind, o, d); + key_drop(kd); } } break; @@ -1336,19 +1332,19 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) */ 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); @@ -1375,7 +1371,7 @@ static void showkey(key *k, listopts *o) /* --- 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 --- */ @@ -1447,7 +1443,7 @@ static void showkey(key *k, listopts *o) 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); } @@ -1860,7 +1856,7 @@ static int cmd_lock(int argc, char *argv[]) { key_file f; key *k; - key_data *kd; + key_data **kd; dstr d = DSTR_INIT; if (argc != 2) @@ -1868,9 +1864,9 @@ static int cmd_lock(int argc, char *argv[]) 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); @@ -1883,7 +1879,7 @@ static int cmd_unlock(int argc, char *argv[]) { key_file f; key *k; - key_data *kd; + key_data **kd; dstr d = DSTR_INIT; if (argc != 2) @@ -1891,9 +1887,9 @@ static int cmd_unlock(int argc, char *argv[]) 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); diff --git a/mparena.c b/mparena.c index 49315f5..1f54c29 100644 --- a/mparena.c +++ b/mparena.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mparena.c,v 1.7 2004/04/08 01:36:15 mdw Exp $ + * $Id$ * * Allocation and freeing of MP buffers * @@ -48,7 +48,7 @@ * itself. */ -/* #define MPARENA_TRIVIAL */ +#define MPARENA_TRIVIAL /* --- @MPARENA_DEBUG@ --- * * diff --git a/rspit.c b/rspit.c index 34abb11..148a3d0 100644 --- a/rspit.c +++ b/rspit.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: rspit.c,v 1.21 2004/04/21 00:37:32 mdw Exp $ + * $Id$ * * Spit out random numbers * @@ -619,9 +619,9 @@ static grand *gen_bbs(unsigned i) /* --- 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"); -- 2.11.0