Pollard's rho algorithm for computing discrete logs.
[u/mdw/catacomb] / key-misc.c
1 /* -*-c-*-
2 *
3 * $Id: key-misc.c,v 1.2 2000/02/12 18:21:02 mdw Exp $
4 *
5 * Simple key management
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-misc.c,v $
33 * Revision 1.2 2000/02/12 18:21:02 mdw
34 * Overhaul of key management (again).
35 *
36 * Revision 1.1 1999/12/22 15:47:48 mdw
37 * Major key-management revision.
38 *
39 */
40
41 /*----- Header files ------------------------------------------------------*/
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47
48 #include <mLib/bits.h>
49 #include <mLib/hash.h>
50 #include <mLib/sub.h>
51 #include <mLib/sym.h>
52
53 #include "key.h"
54
55 /*----- Useful macros -----------------------------------------------------*/
56
57 #define KEY_WRITE(f) do { \
58 if (!(f)->f & KF_WRITE) \
59 return (KERR_READONLY); \
60 } while (0)
61
62 #define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0)
63
64 #define KEY_LOAD(n) ((n) * 2)
65
66 /*----- Iteration and iterators -------------------------------------------*/
67
68 /* --- @key_mkiter@ --- *
69 *
70 * Arguments: @key_iter *i@ = pointer to iterator object
71 * @key_file *f@ = pointer to file structure
72 *
73 * Returns: ---
74 *
75 * Use: Initializes a key iterator. The keys are returned by
76 * @key_next@.
77 */
78
79 void key_mkiter(key_iter *i, key_file *f)
80 {
81 HASH_MKITER(&i->i, &f->byid);
82 i->t = time(0);
83 }
84
85 /* --- @key_next@ --- *
86 *
87 * Arguments: @key_iter *i@ = pointer to iterator object
88 *
89 * Returns: Pointer to next key, or null.
90 *
91 * Use: Returns the next key in some arbitrary sequence.
92 */
93
94 key *key_next(key_iter *i)
95 {
96 hash_base *b;
97 key *k;
98 do {
99 HASH_NEXT(&i->i, b);
100 k = (key *)b;
101 } while (k && KEY_EXPIRED(i->t, k->exp) && KEY_EXPIRED(i->t, k->del));
102 return (k);
103 }
104
105 /*----- Lookup ------------------------------------------------------------*/
106
107 /* --- @key_bytype@ --- *
108 *
109 * Arguments: @key_file *f@ = key file we want a key from
110 * @const char *type@ = type string for desired key
111 *
112 * Returns: Pointer to the best key to use, or null.
113 *
114 * Use: Looks up a key by its type. Returns the key with the latest
115 * expiry time. This function will not return an expired key.
116 */
117
118 key *key_bytype(key_file *f, const char *type)
119 {
120 time_t now = time(0);
121 key *k;
122 key_ref *kr;
123
124 if ((kr = sym_find(&f->bytype, type, -1, 0, 0)) == 0)
125 return (0);
126 for (k = kr->k; k && KEY_EXPIRED(now, k->exp); k = k->next)
127 ;
128 return (k);
129 }
130
131 /* --- @key_byid@ --- *
132 *
133 * Arguments: @key_file *f@ = key file to find a key from
134 * @uint32 id@ = id to look for
135 *
136 * Returns: Key with matching id.
137 *
138 * Use: Returns a key given its id. This function will return an
139 * expired key, but not a deleted one.
140 */
141
142 key *key_byid(key_file *f, uint32 id)
143 {
144 time_t t = time(0);
145 hash_base **bin, *b;
146
147 bin = HASH_BIN(&f->byid, id);
148 for (b = *bin; b; b = b->next) {
149 if (b->hash == id) {
150 key *k = (key *)b;
151 if (KEY_EXPIRED(t, k->exp) && KEY_EXPIRED(t, k->del))
152 return (0);
153 return (k);
154 }
155 }
156 return (0);
157 }
158
159 /* --- @key_bytag@ --- *
160 *
161 * Arguments: @key_file *f@ = key file to find a key from
162 * @const char *tag@ = pointer to tag string
163 *
164 * Returns: Key with matching id or tag.
165 *
166 * Use: Returns a key given its tag or id. This function will return
167 * an expired key, but not a deleted one.
168 */
169
170 key *key_bytag(key_file *f, const char *tag)
171 {
172 time_t t = time(0);
173 char *p;
174 uint32 id;
175 key_ref *kr = sym_find(&f->bytag, tag, -1, 0, 0);
176
177 if (kr && !(KEY_EXPIRED(t, kr->k->exp) && KEY_EXPIRED(t, kr->k->exp)))
178 return (kr->k);
179 id = strtoul(tag, &p, 16);
180 if (!*p)
181 return (key_byid(f, id));
182 return (key_bytype(f, tag));
183 }
184
185 /* --- @key_qtag@ --- *
186 *
187 * Arguments: @key_file *f@ = key file to find a key from
188 * @const char *tag@ = pointer to tag string
189 * @dstr *d@ = pointer to string for full tag name
190 * @key **k@ = where to store the key pointer
191 * @key_data **kd@ = where to store the key data pointer
192 *
193 * Returns: Zero if OK, nonzero if it failed.
194 *
195 * Use: Performs a full lookup on a qualified tag name. The tag is
196 * qualified by the names of subkeys, separated by dots. Hence,
197 * a qualified tag is ID|TAG[.TAG...]. The various result
198 * pointers can be null to indicate that the result isn't
199 * interesting.
200 */
201
202 int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data **kd)
203 {
204 dstr dd = DSTR_INIT;
205 const char *q;
206 key *kk;
207 key_data *kkd;
208
209 /* --- Find the end of the base tag --- */
210
211 if ((q = strchr(tag, '.')) == 0)
212 DPUTS(&dd, tag);
213 else {
214 DPUTM(&dd, tag, q - tag);
215 DPUTZ(&dd);
216 q++;
217 }
218
219 /* --- Look up the key tag --- */
220
221 if ((kk = key_bytag(f, dd.buf)) == 0) {
222 dstr_destroy(&dd);
223 return (-1);
224 }
225
226 /* --- Set the various initial bits of result up --- */
227
228 if (d)
229 key_fulltag(kk, d);
230 if (k)
231 *k = kk;
232 kkd = &kk->k;
233
234 /* --- Now dig through the rest of the tag --- */
235
236 while (q && *q) {
237
238 /* --- Stick on the next bit of the fullqtag --- */
239
240 DRESET(&dd);
241 while (*q && *q != '.') {
242 DPUTC(&dd, *q);
243 q++;
244 }
245 DPUTZ(&dd);
246 if (d) {
247 DPUTC(d, '.');
248 DPUTD(d, &dd);
249 }
250
251 /* --- Look up the subkey --- */
252
253 if (kkd->e != KENC_STRUCT) {
254 kkd = 0;
255 break;
256 }
257 if ((kkd = key_structfind(kkd, dd.buf)) == 0)
258 break;
259 }
260
261 /* --- Return the results --- */
262
263 if (!kkd)
264 return (-1);
265 dstr_destroy(&dd);
266 if (kd)
267 *kd = kkd;
268 return (0);
269 }
270
271 /*----- Miscellaneous functions -------------------------------------------*/
272
273 /* --- @key_delete@ --- *
274 *
275 * Arguments: @key_file *f@ = pointer to file block
276 * @key *k@ = key to delete
277 *
278 * Returns: Error code (one of the @KERR@ constants).
279 *
280 * Use: Removes the given key from the list. The key file must be
281 * writable. (Due to the horridness of the data structures,
282 * deleted keys aren't actually removed, just marked so that
283 * they can't be looked up or iterated over. One upshot of
284 * this is that they don't get written back to the file when
285 * it's closed.)
286 */
287
288 int key_delete(key_file *f, key *k)
289 {
290 KEY_WRITE(f);
291 k->exp = KEXP_EXPIRE;
292 k->del = KEXP_EXPIRE;
293 KEY_MODIFY(f);
294 return (0);
295 }
296
297 /* --- @key_expire@ --- *
298 *
299 * Arguments: @key_file *f@ = pointer to file block
300 * @key *k@ = pointer to key block
301 *
302 * Returns: Error code (one of the @KERR@ constants).
303 *
304 * Use: Immediately marks the key as expired. It may be removed
305 * immediately, if it is no longer required, and will be removed
306 * by a tidy operation when it is no longer required. The key
307 * file must be writable.
308 */
309
310 int key_expire(key_file *f, key *k)
311 {
312 KEY_WRITE(f);
313 k->exp = KEXP_EXPIRE;
314 if (k->del == KEXP_FOREVER)
315 k->del = KEXP_EXPIRE;
316 KEY_MODIFY(f);
317 return (0);
318 }
319
320 /* --- @key_used@ --- *
321 *
322 * Arguments: @key_file *f@ = pointer to key file
323 * @key *k@ = pointer to key block
324 * @time_t t@ = when key can be removed
325 *
326 * Returns: Zero if OK, nonzero on failure.
327 *
328 * Use: Marks a key as being required until a given time. Even
329 * though the key may expire before then (and won't be returned
330 * by type after that time), it will still be available when
331 * requested explicitly by id. The key file must be writable.
332 *
333 * The only (current) reason for failure is attempting to use
334 * a key which can expire for something which can't.
335 */
336
337 int key_used(key_file *f, key *k, time_t t)
338 {
339 KEY_WRITE(f);
340 if (t == KEXP_FOREVER) {
341 if (k->exp != KEXP_FOREVER)
342 return (KERR_WILLEXPIRE);
343 } else if (k->del >= t)
344 return (0);
345
346 k->del = t;
347 KEY_MODIFY(f);
348 return (0);
349 }
350
351 /*----- That's all, folks -------------------------------------------------*/