Release 2.1.2.
[u/mdw/catacomb] / key-pack.c
CommitLineData
e56dff91 1/* -*-c-*-
2 *
ef13e9a4 3 * $Id$
e56dff91 4 *
5 * Packing and unpacking key data
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
45c0fd36 10/*----- Licensing notice --------------------------------------------------*
e56dff91 11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
45c0fd36 18 *
e56dff91 19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
45c0fd36 23 *
e56dff91 24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
e56dff91 30/*----- Header files ------------------------------------------------------*/
31
32#include <mLib/dstr.h>
33
34#include "key.h"
35#include "key-data.h"
36
37/*----- Generic packing and unpacking -------------------------------------*/
38
39/* --- @key_pack@ --- *
40 *
41 * Arguments: @key_packdef *kp@ = pointer to packing structure
ef13e9a4 42 * @key_data **kd@ = where to put the key data pointer
e56dff91 43 * @dstr *d@ = pointer to tag string for the key data
44 *
45 * Returns: Error code, or zero.
46 *
47 * Use: Packs a key from a data structure.
48 */
49
ef13e9a4 50int key_pack(key_packdef *kp, key_data **kd, dstr *d)
e56dff91 51{
ef13e9a4 52 switch (kp->e & KF_ENCMASK) {
e56dff91 53
54 /* --- Binary and integer keys are easy --- */
55
ef13e9a4 56 case KENC_BINARY: {
57 key_bin *b = kp->p;
58 *kd = key_newbinary(kp->e, b->k, b->sz);
e56dff91 59 return (0);
ef13e9a4 60 }
e56dff91 61 case KENC_MP:
ef13e9a4 62 *kd = key_newmp(kp->e, *(mp **)kp->p);
e56dff91 63 return (0);
1ba83484 64 case KENC_STRING:
ef13e9a4 65 *kd = key_newstring(kp->e, *(char **)kp->p);
1ba83484 66 return (0);
67 case KENC_EC:
ef13e9a4 68 *kd = key_newec(kp->e, (ec *)kp->p);
1ba83484 69 return (0);
e56dff91 70
71 /* --- Encrypted keys are a little tricky --- *
72 *
73 * This works rather differently to unpacking.
74 */
75
76 case KENC_ENCRYPT: {
ef13e9a4 77 key_data *kkd;
e56dff91 78 int err = key_pack(kp->p, &kkd, d);
79 if (!err) {
ef13e9a4 80 err = key_plock(kd, kkd, d->buf);
81 key_drop(kkd);
e56dff91 82 }
83 return (err);
84 }
85
86 /* --- Structured keys, as ever, are a nuisance --- */
87
88 case KENC_STRUCT: {
89 int err;
90 key_packstruct *p;
91 size_t l = d->len;
92
ef13e9a4 93 *kd = key_newstruct();
e56dff91 94 DPUTC(d, '.');
95 for (p = kp->p; p->name; p++) {
96 key_data *kkd;
97 d->len = l + 1;
98 DPUTS(d, p->name);
ef13e9a4 99 if ((err = key_pack(&p->kp, &kkd, d)) != 0) {
100 key_drop(*kd);
e56dff91 101 return (err);
102 }
ef13e9a4 103 key_structsteal(*kd, p->name, kkd);
e56dff91 104 }
105 d->len = l;
106 d->buf[l] = 0;
107 return (0);
108 }
ef13e9a4 109 default:
110 abort();
e56dff91 111 }
e56dff91 112}
113
114/* --- @key_unpack@ --- *
115 *
116 * Arguments: @key_packdef *kp@ = pointer to packing structure
117 * @key_data *kd@ = pointer to source key data
118 * @dstr *d@ = pointer to tag string for the key data
119 *
120 * Returns: Error code, or zero.
121 *
122 * Use: Unpacks a key into an appropriate data structure.
123 */
124
125int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
126{
ef13e9a4 127 unsigned e = kp->e & KF_ENCMASK;
e56dff91 128 int err;
129
130 /* --- Decrypt the encrypted key --- */
131
ef13e9a4 132 if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
133 if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0)
e56dff91 134 goto fail;
ef13e9a4 135 kd = kp->kd;
e56dff91 136 }
137
138 /* --- Ensure that the key has the right type --- */
139
140 if ((kd->e & KF_ENCMASK) != e) {
f387fcb1 141 err = KERR_WRONGTYPE;
e56dff91 142 goto fail;
143 }
144
145 /* --- Unpack the key --- *
146 *
147 * Only three possibilities left now.
148 */
149
150 switch (e) {
151
152 /* --- Binary and integer keys are easy --- */
153
154 case KENC_BINARY:
155 *(key_bin *)kp->p = kd->u.k;
156 break;
157 case KENC_MP:
158 *(mp **)kp->p = kd->u.m;
159 break;
1ba83484 160 case KENC_STRING:
161 *(char **)kp->p = kd->u.p;
162 break;
163 case KENC_EC:
164 *(ec *)kp->p = kd->u.e;
165 break;
e56dff91 166
167 /* --- Structured keys take a little care --- */
168
169 case KENC_STRUCT: {
170 key_packstruct *p, *q;
171 size_t l = d->len;
172
173 /* --- Iterate over the requested subparts --- */
174
175 DPUTC(d, '.');
176 for (p = kp->p; p->name; p++) {
177 key_data *kkd;
178
179 /* --- Build the name --- */
180
181 d->len = l + 1;
182 DPUTS(d, p->name);
183
184 /* --- Find and unpack the subkey --- */
185
186 if ((kkd = key_structfind(kd, p->name)) == 0) {
ef13e9a4 187 if (!(p->kp.e & KF_OPT)) {
e56dff91 188 err = KERR_NOTFOUND;
189 goto tidy;
190 }
191 } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
192 p++;
193 goto tidy;
194 }
195 }
196
197 /* --- Done --- */
198
199 d->len = l;
200 d->buf[l] = 0;
201 break;
202
203 /* --- Tidy up if something went wrong --- */
204
205 tidy:
206 for (q = kp->p; q < p; q++)
207 key_unpackdone(&q->kp);
208 goto fail;
209 }
ef13e9a4 210
211 default:
212 abort();
e56dff91 213 }
214
215 return (0);
216
217 /* --- Something went wrong --- */
218
219fail:
ef13e9a4 220 if (kp->kd) {
221 key_drop(kp->kd);
222 kp->kd = 0;
223 }
e56dff91 224 return (err);
225}
226
227/* --- @key_unpackdone@ --- *
228 *
229 * Arguments: @key_packdef *kp@ = pointer to packing definition
230 *
231 * Returns: ---
232 *
233 * Use: Frees the key components contained within a packing
234 * definition, created during key unpacking.
235 */
236
237void key_unpackdone(key_packdef *kp)
238{
ef13e9a4 239 if (kp->kd) {
240 key_drop(kp->kd);
241 kp->kd = 0;
242 }
243 if ((kp->e & KF_ENCMASK) == KENC_STRUCT) {
e56dff91 244 key_packstruct *p;
245 for (p = kp->p; p->name; p++)
246 key_unpackdone(&p->kp);
247 }
248}
249
250/*----- That's all, folks -------------------------------------------------*/