/* -*-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);