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