d11a0bf7 |
1 | /* -*-c-*- |
2 | * |
0f421d71 |
3 | * $Id$ |
d11a0bf7 |
4 | * |
5 | * Encoding and decoding of 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 | |
d11a0bf7 |
30 | /*----- Header files ------------------------------------------------------*/ |
31 | |
32 | #include <assert.h> |
33 | #include <stdlib.h> |
34 | #include <string.h> |
35 | |
d11a0bf7 |
36 | #include <mLib/base64.h> |
37 | #include <mLib/bits.h> |
38 | #include <mLib/dstr.h> |
39 | #include <mLib/sub.h> |
40 | #include <mLib/sym.h> |
41 | |
052b36d0 |
42 | #include "key-data.h" |
d11a0bf7 |
43 | #include "mp.h" |
44 | #include "mptext.h" |
45 | |
ef13e9a4 |
46 | /*----- Reference counting stuff ------------------------------------------*/ |
47 | |
48 | /* --- @key_incref@ --- * |
49 | * |
50 | * Arguments: @key_data *k@ = pointer to key data |
51 | * |
52 | * Returns: --- |
53 | * |
54 | * Use: Increments the refcount on a key data block. |
55 | */ |
56 | |
57 | void key_incref(key_data *k) { KEY_INCREF(k); } |
58 | |
59 | /* --- @key_destroy@ --- * |
60 | * |
61 | * Arguments: @key_data *k@ = pointer to key data to destroy |
62 | * |
63 | * Returns: --- |
64 | * |
65 | * Use: Destroys a block of key data, regardless of reference count. |
66 | * Don't use this unless you know what you're doing. |
67 | */ |
68 | |
69 | void key_destroy(key_data *k) |
70 | { |
71 | switch (k->e & KF_ENCMASK) { |
72 | case KENC_BINARY: |
73 | case KENC_ENCRYPT: |
74 | if (k->u.k.k) { |
75 | if (k->e & KF_BURN) |
76 | memset(k->u.k.k, 0, k->u.k.sz); |
77 | sub_free(k->u.k.k, k->u.k.sz); |
78 | } |
79 | break; |
80 | case KENC_MP: |
81 | mp_drop(k->u.m); |
82 | break; |
83 | case KENC_STRING: |
84 | xfree(k->u.p); |
85 | break; |
86 | case KENC_EC: |
87 | EC_DESTROY(&k->u.e); |
88 | break; |
89 | case KENC_STRUCT: { |
90 | key_data *kd; |
91 | key_subkeyiter i; |
92 | |
93 | for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); ) |
94 | KEY_DROP(kd); |
95 | sym_destroy(&k->u.s); |
96 | } break; |
97 | default: |
98 | abort(); |
99 | } |
100 | DESTROY(k); |
101 | } |
102 | |
103 | /* --- @key_drop@ --- * |
104 | * |
105 | * Arguments: @key_data *k@ = pointer to key data to destroy |
106 | * |
107 | * Returns: --- |
108 | * |
109 | * Use: Drops a reference to key data, destroying it if necessary. |
110 | */ |
111 | |
112 | void key_drop(key_data *k) { KEY_DROP(k); } |
113 | |
114 | /* --- @key_split@ --- * |
115 | * |
116 | * Arguments: @key_data **kk@ = address of pointer to key data block |
117 | * |
118 | * Returns: --- |
119 | * |
120 | * Use: Replaces @*kk@ with a pointer to the same key data, but with |
121 | * just one reference. |
122 | */ |
123 | |
124 | void key_split(key_data **kk) |
125 | { |
126 | key_data *k = *kk; |
127 | |
128 | if (k->ref == 1) |
129 | return; |
130 | switch (k->e & KF_ENCMASK) { |
131 | case KENC_BINARY: |
132 | *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz); |
133 | break; |
134 | case KENC_ENCRYPT: |
135 | *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz); |
136 | break; |
137 | case KENC_MP: |
138 | *kk = key_newmp(k->e, k->u.m); |
139 | break; |
140 | case KENC_STRING: |
141 | *kk = key_newstring(k->e, k->u.p); |
142 | break; |
143 | case KENC_EC: |
144 | *kk = key_newec(k->e, &k->u.e); |
145 | break; |
146 | case KENC_STRUCT: { |
147 | key_subkeyiter i; |
148 | const char *tag; |
149 | key_data *kd; |
150 | |
151 | *kk = key_newstruct(); |
152 | for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) |
153 | key_structset(*kk, tag, kd); |
154 | } break; |
155 | default: |
156 | abort(); |
157 | } |
158 | } |
159 | |
d11a0bf7 |
160 | /*----- Setting new values ------------------------------------------------*/ |
161 | |
ef13e9a4 |
162 | /* --- @key_newraw@ --- * |
d11a0bf7 |
163 | * |
ef13e9a4 |
164 | * Arguments: @unsigned e@ = encoding type to set |
165 | * |
166 | * Returns: New key block, not filled in. |
167 | */ |
168 | |
169 | key_data *key_newraw(unsigned e) |
170 | { |
171 | key_data *k = CREATE(key_data); |
172 | k->e = e; |
173 | k->ref = 1; |
174 | return (k); |
175 | } |
176 | |
177 | /* --- @key_newbinary@ --- * |
178 | * |
179 | * Arguments: @unsigned e@ = other encoding flags |
d11a0bf7 |
180 | * @const void *p@ = pointer to key data |
181 | * @size_t sz@ = size of the key data |
182 | * |
ef13e9a4 |
183 | * Returns: New key data object. |
d11a0bf7 |
184 | */ |
185 | |
ef13e9a4 |
186 | key_data *key_newbinary(unsigned e, const void *p, size_t sz) |
d11a0bf7 |
187 | { |
ef13e9a4 |
188 | key_data *k = key_newraw(KENC_BINARY | e); |
d11a0bf7 |
189 | k->u.k.k = sub_alloc(sz); |
190 | memcpy(k->u.k.k, p, sz); |
191 | k->u.k.sz = sz; |
ef13e9a4 |
192 | return (k); |
d11a0bf7 |
193 | } |
194 | |
ef13e9a4 |
195 | /* --- @key_newencrypted@ --- * |
d11a0bf7 |
196 | * |
ef13e9a4 |
197 | * Arguments: @unsigned e@ = other encoding flags |
d11a0bf7 |
198 | * @const void *p@ = pointer to key data |
199 | * @size_t sz@ = size of the key data |
200 | * |
ef13e9a4 |
201 | * Returns: New key data object. |
d11a0bf7 |
202 | */ |
203 | |
ef13e9a4 |
204 | key_data *key_newencrypted(unsigned e, const void *p, size_t sz) |
d11a0bf7 |
205 | { |
ef13e9a4 |
206 | key_data *k = key_newraw(KENC_ENCRYPT | e); |
d11a0bf7 |
207 | k->u.k.k = sub_alloc(sz); |
208 | memcpy(k->u.k.k, p, sz); |
209 | k->u.k.sz = sz; |
ef13e9a4 |
210 | return (k); |
d11a0bf7 |
211 | } |
212 | |
ef13e9a4 |
213 | /* --- @key_mewmp@ --- * |
d11a0bf7 |
214 | * |
ef13e9a4 |
215 | * Arguments: @unsigned e@ = other encoding flags |
d11a0bf7 |
216 | * @mp *m@ = pointer to the value to set |
217 | * |
ef13e9a4 |
218 | * Returns: New key data object. |
d11a0bf7 |
219 | */ |
220 | |
ef13e9a4 |
221 | key_data *key_newmp(unsigned e, mp *m) |
d11a0bf7 |
222 | { |
ef13e9a4 |
223 | key_data *k = key_newraw(KENC_MP | e); |
d11a0bf7 |
224 | k->u.m = MP_COPY(m); |
ef13e9a4 |
225 | return (k); |
d11a0bf7 |
226 | } |
227 | |
ef13e9a4 |
228 | /* --- @key_newstring@ --- * |
1ba83484 |
229 | * |
ef13e9a4 |
230 | * Arguments: @unsigned e@ = other encoding flags |
1ba83484 |
231 | * @const char *p@ = pointer to the value to set |
232 | * |
ef13e9a4 |
233 | * Returns: New key data object. |
1ba83484 |
234 | */ |
235 | |
ef13e9a4 |
236 | key_data *key_newstring(unsigned e, const char *p) |
1ba83484 |
237 | { |
ef13e9a4 |
238 | key_data *k = key_newraw(KENC_STRING | e); |
1ba83484 |
239 | k->u.p = xstrdup(p); |
ef13e9a4 |
240 | return (k); |
1ba83484 |
241 | } |
242 | |
ef13e9a4 |
243 | /* --- @key_newec@ --- * |
1ba83484 |
244 | * |
ef13e9a4 |
245 | * Arguments: @unsigned e@ = other encoding flags |
246 | * @const ec *pt@ = pointer to the value to set |
1ba83484 |
247 | * |
ef13e9a4 |
248 | * Returns: New key data object. |
1ba83484 |
249 | */ |
250 | |
ef13e9a4 |
251 | key_data *key_newec(unsigned e, const ec *pt) |
252 | { |
253 | key_data *k = key_newraw(KENC_EC | e); |
1ba83484 |
254 | EC_CREATE(&k->u.e); |
ef13e9a4 |
255 | EC_COPY(&k->u.e, pt); |
256 | return (k); |
1ba83484 |
257 | } |
258 | |
ef13e9a4 |
259 | /* --- @key_newstruct@ --- * |
d11a0bf7 |
260 | * |
ef13e9a4 |
261 | * Arguments: --- |
d11a0bf7 |
262 | * |
ef13e9a4 |
263 | * Returns: New key data object. |
d11a0bf7 |
264 | */ |
265 | |
ef13e9a4 |
266 | key_data *key_newstruct(void) |
d11a0bf7 |
267 | { |
ef13e9a4 |
268 | key_data *k = key_newraw(KENC_STRUCT); |
d11a0bf7 |
269 | sym_create(&k->u.s); |
ef13e9a4 |
270 | return (k); |
d11a0bf7 |
271 | } |
272 | |
273 | /* --- @key_structfind@ --- * |
274 | * |
275 | * Arguments: @key_data *k@ = pointer to key data block |
276 | * @const char *tag@ = pointer to tag string |
277 | * |
278 | * Returns: Pointer to key data block, or null. |
279 | * |
280 | * Use: Looks up the tag in a structured key. |
281 | */ |
282 | |
283 | key_data *key_structfind(key_data *k, const char *tag) |
284 | { |
285 | key_struct *ks; |
380a6fdc |
286 | assert(((void)"Key is not structured", |
287 | (k->e & KF_ENCMASK) == KENC_STRUCT)); |
d11a0bf7 |
288 | ks = sym_find(&k->u.s, tag, -1, 0, 0); |
380a6fdc |
289 | if (!ks) |
290 | return (0); |
ef13e9a4 |
291 | return (ks->k); |
d11a0bf7 |
292 | } |
293 | |
ef13e9a4 |
294 | /* --- @key_mksubkeyiter@ --- * |
d11a0bf7 |
295 | * |
ef13e9a4 |
296 | * Arguments: @key_subkeyiter *i@ = pointer to iterator block |
297 | * @key_data *k@ = pointer to key data block |
298 | * |
299 | * Returns: --- |
300 | * |
301 | * Use: Initializes a subkey iterator. |
302 | */ |
303 | |
304 | void key_mksubkeyiter(key_subkeyiter *i, key_data *k) |
305 | { |
306 | assert(((void)"Key is not structured", |
307 | (k->e & KF_ENCMASK) == KENC_STRUCT)); |
308 | sym_mkiter(&i->i, &k->u.s); |
309 | } |
310 | |
311 | /* --- @key_nextsubkey@ --- * |
d11a0bf7 |
312 | * |
ef13e9a4 |
313 | * Arguments: @key_structiter *i@ = pointer to iterator block |
314 | * @const char **tag@ = where to put the tag pointer, or null |
315 | * @key_data **kd@ = where to put the key data pointer, or null |
d11a0bf7 |
316 | * |
ef13e9a4 |
317 | * Returns: Nonzero if there was another item, zero if we hit the |
318 | * end-stop. |
319 | * |
320 | * Use: Collects the next subkey of a structured key. |
d11a0bf7 |
321 | */ |
322 | |
ef13e9a4 |
323 | int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd) |
d11a0bf7 |
324 | { |
325 | key_struct *ks; |
d11a0bf7 |
326 | |
ef13e9a4 |
327 | if ((ks = sym_next(&i->i)) == 0) |
328 | return (0); |
329 | if (tag) *tag = SYM_NAME(ks); |
330 | if (kd) *kd = ks->k; |
d11a0bf7 |
331 | } |
332 | |
ef13e9a4 |
333 | /* --- @key_structset@, @key_structsteal@ --- * |
d11a0bf7 |
334 | * |
ef13e9a4 |
335 | * Arguments: @key_data *k@ = pointer to key data block |
336 | * @const char *tag@ = pointer to tag string |
337 | * @key_data *kd@ = new key data to store |
d11a0bf7 |
338 | * |
052b36d0 |
339 | * Returns: --- |
d11a0bf7 |
340 | * |
ef13e9a4 |
341 | * Use: Creates a new subkey. Stealing doesn't affect @kd@'s |
342 | * refcount. If @kd@ is null, the subkey is deleted. |
d11a0bf7 |
343 | */ |
344 | |
ef13e9a4 |
345 | static void structset(key_data *k, int stealp, |
346 | const char *tag, key_data *kd) |
d11a0bf7 |
347 | { |
ef13e9a4 |
348 | key_struct *ks; |
349 | unsigned f; |
d11a0bf7 |
350 | |
ef13e9a4 |
351 | assert(((void)"Key is not structured", k->e == KENC_STRUCT)); |
352 | if (!kd) { |
353 | ks = sym_find(&k->u.s, tag, -1, 0, 0); |
354 | if (ks) sym_remove(&k->u.s, ks); |
355 | } else { |
356 | ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f); |
357 | if (f) |
358 | key_drop(ks->k); |
359 | if (!stealp) KEY_INCREF(kd); |
360 | ks->k = kd; |
361 | } |
d11a0bf7 |
362 | } |
363 | |
ef13e9a4 |
364 | void key_structset(key_data *k, const char *tag, key_data *kd) |
365 | { structset(k, 0, tag, kd); } |
366 | void key_structsteal(key_data *k, const char *tag, key_data *kd) |
367 | { structset(k, 1, tag, kd); } |
368 | |
369 | /*----- Miscellaneous operations ------------------------------------------*/ |
370 | |
d11a0bf7 |
371 | /* --- @key_do@ --- * |
372 | * |
373 | * Arguments: @key_data *k@ = pointer to key data block |
374 | * @const key_filter *kf@ = pointer to filter block |
375 | * @dstr *d@ = pointer to base string |
376 | * @int (*func)(key_data *kd, dstr *d, void *p@ = function |
377 | * @void *p@ = argument to function |
378 | * |
379 | * Returns: Nonzero return code from function, or zero. |
380 | * |
381 | * Use: Runs a function over all the leaves of a key. |
382 | */ |
383 | |
384 | int key_do(key_data *k, const key_filter *kf, dstr *d, |
385 | int (*func)(key_data */*kd*/, dstr */*d*/, void */*p*/), |
386 | void *p) |
387 | { |
388 | if (!KEY_MATCH(k, kf)) |
389 | return (0); |
390 | if ((k->e & KF_ENCMASK) != KENC_STRUCT) |
391 | return (func(k, d, p)); |
392 | else { |
ef13e9a4 |
393 | key_subkeyiter i; |
394 | const char *tag; |
2cc51ff1 |
395 | size_t n = 0; |
d11a0bf7 |
396 | int rc; |
397 | |
398 | if (d) |
399 | n = d->len; |
ef13e9a4 |
400 | for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { |
d11a0bf7 |
401 | if (d) { |
402 | d->len = n; |
ef13e9a4 |
403 | dstr_putf(d, ".%s", tag); |
d11a0bf7 |
404 | } |
ef13e9a4 |
405 | if ((rc = key_do(k, kf, d, func, p)) != 0) |
d11a0bf7 |
406 | return (rc); |
407 | } |
408 | return (0); |
409 | } |
410 | } |
411 | |
d11a0bf7 |
412 | /*----- That's all, folks -------------------------------------------------*/ |