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