X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/0d4a06cd790bcad456592d60cb4b40981fa2429a..813390c45f438f411662b1a55678e63f11681eb4:/key-text.c diff --git a/key-text.c b/key-text.c index 238c571..ff9e705 100644 --- a/key-text.c +++ b/key-text.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: key-text.c,v 1.3 2001/02/03 11:57:00 mdw Exp $ + * $Id$ * * Key textual encoding * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,35 +15,21 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: key-text.c,v $ - * Revision 1.3 2001/02/03 11:57:00 mdw - * Track mLib change: symbols no longer need to include a terminating - * null. - * - * Revision 1.2 2000/06/17 11:27:20 mdw - * Use secure memory interface from MP library. - * - * Revision 1.1 2000/02/12 18:21:02 mdw - * Overhaul of key management (again). - * - */ - /*----- Header files ------------------------------------------------------*/ +#include #include #include @@ -52,6 +38,7 @@ #include #include #include +#include #include "key-data.h" #include "mp.h" @@ -62,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 --- * * @@ -85,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 --- * @@ -110,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; @@ -124,13 +108,61 @@ 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; + /* --- String encoding --- * + * + * We use form-urlencoding to ensure that evil characters don't get out. + */ + + case KENC_STRING: { + dstr d = DSTR_INIT; + size_t sz = strcspn(p, ",]"); + const char *l = p + sz; + unsigned int ch; + int x, n; + + while (p < l) { + switch (*p) { + case '+': + DPUTC(&d, ' '); break; + case '%': + x = sscanf(p + 1, "%2x%n", &ch, &n); + if (x == 1) { DPUTC(&d, ch); p += n; break; } + default: + DPUTC(&d, *p); break; + } + p++; + } + DPUTZ(&d); + kd = key_newstring(e, d.buf); + dstr_destroy(&d); + } break; + + /* --- Elliptic curve encoding --- * + * + * Again, we have a convenient function. Assume for now that points + * aren't secret. (Reasonably safe.) + */ + + case KENC_EC: { + ec pt = EC_INIT; + qd_parse qd; + qd.p = p; + qd.e = 0; + if (!ec_ptparse(&qd, &pt)) + return (0); + kd = key_newec(e, &pt); + EC_DESTROY(&pt); + p = qd.p; + } break; + /* --- Structured information encoding --- * * * The format for structured key data is `[NAME=KEY,...]', where the @@ -143,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 --- * * @@ -180,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 --- */ @@ -220,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@ --- * @@ -247,7 +265,7 @@ int key_read(const char *p, key_data *k, char **pp) * * Use: Writes a key in a textual encoding. */ - + int key_write(key_data *k, dstr *d, const key_filter *kf) { int rc = 0; @@ -276,20 +294,38 @@ int key_write(key_data *k, dstr *d, const key_filter *kf) mp_writedstr(k->u.m, d, 10); rc = 1; break; + case KENC_STRING: { + const char *p = k->u.p; + key_writeflags(k->e, d); + DPUTC(d, ':'); + while (*p) { + if (*p == ' ') DPUTC(d, '+'); + else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p); + else DPUTC(d, *p); + p++; + } + rc = 1; + } break; + case KENC_EC: + key_writeflags(k->e, d); + DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16); + DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16); + 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 = ',';