575fd937bfba9c83424770299cf2fe9adcce4e11
[u/mdw/catacomb] / key-pack.c
1 /* -*-c-*-
2 *
3 * $Id: key-pack.c,v 1.2 2004/03/28 01:58:47 mdw Exp $
4 *
5 * Packing and unpacking key data
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
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.
18 *
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.
23 *
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
30 /*----- Revision history --------------------------------------------------*
31 *
32 * $Log: key-pack.c,v $
33 * Revision 1.2 2004/03/28 01:58:47 mdw
34 * Generate, store and retreive elliptic curve keys.
35 *
36 * Revision 1.1 2000/06/17 10:42:41 mdw
37 * Packing and unpacking structured keys.
38 *
39 */
40
41 /*----- Header files ------------------------------------------------------*/
42
43 #include <mLib/dstr.h>
44
45 #include "key.h"
46 #include "key-data.h"
47
48 /*----- Generic packing and unpacking -------------------------------------*/
49
50 /* --- @key_pack@ --- *
51 *
52 * Arguments: @key_packdef *kp@ = pointer to packing structure
53 * @key_data *kd@ = pointer to destination key data
54 * @dstr *d@ = pointer to tag string for the key data
55 *
56 * Returns: Error code, or zero.
57 *
58 * Use: Packs a key from a data structure.
59 */
60
61 int key_pack(key_packdef *kp, key_data *kd, dstr *d)
62 {
63 switch (kp->kd.e & KF_ENCMASK) {
64
65 /* --- Binary and integer keys are easy --- */
66
67 case KENC_BINARY:
68 kd->u.k = *(key_bin *)kp->p;
69 return (0);
70 case KENC_MP:
71 kd->u.m = *(mp **)kp->p;
72 return (0);
73 case KENC_STRING:
74 kd->u.p = *(char **)kp->p;
75 return (0);
76 case KENC_EC:
77 kd->u.e = *(ec *)kp->p;
78 return (0);
79
80 /* --- Encrypted keys are a little tricky --- *
81 *
82 * This works rather differently to unpacking.
83 */
84
85 case KENC_ENCRYPT: {
86 key_data kkd;
87 int err = key_pack(kp->p, &kkd, d);
88 if (!err) {
89 if (key_plock(d->buf, &kkd, kd))
90 err = KERR_BADPASS;
91 key_destroy(&kkd);
92 }
93 return (err);
94 }
95
96 /* --- Structured keys, as ever, are a nuisance --- */
97
98 case KENC_STRUCT: {
99 int err;
100 key_packstruct *p;
101 size_t l = d->len;
102
103 key_structure(kd);
104 DPUTC(d, '.');
105 for (p = kp->p; p->name; p++) {
106 key_data *kkd;
107 d->len = l + 1;
108 DPUTS(d, p->name);
109 kkd = key_structcreate(kd, p->name);
110 if ((err = key_pack(&p->kp, kkd, d)) != 0) {
111 key_destroy(kd);
112 return (err);
113 }
114 }
115 d->len = l;
116 d->buf[l] = 0;
117 return (0);
118 }
119 }
120
121 return (KERR_BADTYPE);
122 }
123
124 /* --- @key_unpack@ --- *
125 *
126 * Arguments: @key_packdef *kp@ = pointer to packing structure
127 * @key_data *kd@ = pointer to source key data
128 * @dstr *d@ = pointer to tag string for the key data
129 *
130 * Returns: Error code, or zero.
131 *
132 * Use: Unpacks a key into an appropriate data structure.
133 */
134
135 int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
136 {
137 unsigned e = kp->kd.e & KF_ENCMASK;
138 int err;
139
140 /* --- Decrypt the encrypted key --- */
141
142 while ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
143 if (key_punlock(d->buf, kd, &kp->kd)) {
144 err = KERR_BADPASS;
145 goto fail;
146 }
147 kd = &kp->kd;
148 kd->e |= KF_TEMP;
149 }
150
151 /* --- Ensure that the key has the right type --- */
152
153 if ((kd->e & KF_ENCMASK) != e) {
154 err = KERR_BADTYPE;
155 goto fail;
156 }
157
158 /* --- Unpack the key --- *
159 *
160 * Only three possibilities left now.
161 */
162
163 switch (e) {
164
165 /* --- Binary and integer keys are easy --- */
166
167 case KENC_BINARY:
168 *(key_bin *)kp->p = kd->u.k;
169 break;
170 case KENC_MP:
171 *(mp **)kp->p = kd->u.m;
172 break;
173 case KENC_STRING:
174 *(char **)kp->p = kd->u.p;
175 break;
176 case KENC_EC:
177 *(ec *)kp->p = kd->u.e;
178 break;
179
180 /* --- Structured keys take a little care --- */
181
182 case KENC_STRUCT: {
183 key_packstruct *p, *q;
184 size_t l = d->len;
185
186 /* --- Iterate over the requested subparts --- */
187
188 DPUTC(d, '.');
189 for (p = kp->p; p->name; p++) {
190 key_data *kkd;
191
192 /* --- Build the name --- */
193
194 d->len = l + 1;
195 DPUTS(d, p->name);
196
197 /* --- Find and unpack the subkey --- */
198
199 if ((kkd = key_structfind(kd, p->name)) == 0) {
200 if (!(p->kp.kd.e & KF_OPT)) {
201 err = KERR_NOTFOUND;
202 goto tidy;
203 }
204 } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
205 p++;
206 goto tidy;
207 }
208 }
209
210 /* --- Done --- */
211
212 d->len = l;
213 d->buf[l] = 0;
214 break;
215
216 /* --- Tidy up if something went wrong --- */
217
218 tidy:
219 for (q = kp->p; q < p; q++)
220 key_unpackdone(&q->kp);
221 goto fail;
222 }
223 }
224
225 return (0);
226
227 /* --- Something went wrong --- */
228
229 fail:
230 if (kd == &kp->kd)
231 key_destroy(kd);
232 return (err);
233 }
234
235 /* --- @key_unpackdone@ --- *
236 *
237 * Arguments: @key_packdef *kp@ = pointer to packing definition
238 *
239 * Returns: ---
240 *
241 * Use: Frees the key components contained within a packing
242 * definition, created during key unpacking.
243 */
244
245 void key_unpackdone(key_packdef *kp)
246 {
247 if (kp->kd.e & KF_TEMP)
248 key_destroy(&kp->kd);
249 if ((kp->kd.e & KF_ENCMASK) == KENC_STRUCT) {
250 key_packstruct *p;
251 for (p = kp->p; p->name; p++)
252 key_unpackdone(&p->kp);
253 }
254 }
255
256 /*----- That's all, folks -------------------------------------------------*/