Pollard's rho algorithm for computing discrete logs.
[u/mdw/catacomb] / key-fetch.c
CommitLineData
1aaed0ba 1/* -*-c-*-
2 *
3 * $Id: key-fetch.c,v 1.1 2000/06/17 10:42:54 mdw Exp $
4 *
5 * Higher-level key unpacking
6 *
7 * (c) 2000 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-fetch.c,v $
33 * Revision 1.1 2000/06/17 10:42:54 mdw
34 * Convenient table-driven extraction of 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/*----- Main code ---------------------------------------------------------*/
46
47/* --- @key_fetchinit@ --- *
48 *
49 * Arguments: @const key_fetchdef *kf@ = pointer to base definition
50 * @key_packstruct *kps@ = pointer to destination packing def
51 * @void *p@ = pointer to destination block
52 *
53 * Returns: Pointer to packing definition.
54 *
55 * Use: Initializes a packing definition (@key_packdef@ structure).
56 * If @kps@ is null on entry, an appropriately sized block is
57 * allocated automatically. Otherwise it must be large enough.
58 */
59
60static size_t kfcount(const key_fetchdef *kf)
61{
62 size_t n = 1;
63 while (kf->name) {
64 n++;
65 if (kf->kf)
66 n += kfcount(kf->kf);
67 kf++;
68 }
69 return (n);
70}
71
72key_packdef *key_fetchinit(const key_fetchdef *kf,
73 key_packstruct *kp, void *p)
74{
75 size_t n = 1 + kfcount(kf);
76 key_packdef *kpd;
77 key_packstruct *kps;
78 char *cp = p;
79
80 /* --- If @kps@ is null, count the entries and allocate --- */
81
82 if (kp)
83 kp->name = 0;
84 else {
85 kp = xmalloc(n * sizeof(*kp));
86 kp->name = (char *)kp;
87 }
88
89 /* --- Fill in the top part --- */
90
91 kp->kp.kd.e = KENC_STRUCT;
92 kp->kp.p = &kp[1];
93 kpd = &kp->kp;
94
95 /* --- Initialize for the main loop --- */
96
97 kps = kp + n;
98 n = 0;
99 kp++;
100
101 /* --- Iterate over the entries in the table --- *
102 *
103 * The end of the target block is used as a stack to record where
104 * substructure is meant to occur. The integer @n@ is the depth of the
105 * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a
106 * stack element points back to an entry with substructure, the @kp.p@
107 * member of which refers to the @kf@ table for the substructure.
108 *
109 * This should all be about as clear as mud.
110 */
111
112 for (;;) {
113
114 /* --- Blat out a level's worth --- */
115
116 while (kf->name) {
117 kp->name = kf->name;
118 kp->kp.kd.e = kf->e;
119 if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
120 kp->kp.p = cp + kf->off;
121 else {
122 (--kps)->kp.p = kp;
123 kp->kp.p = (void *)kf->kf;
124 n++;
125 }
126 kf++;
127 kp++;
128 }
129 (kp++)->name = 0;
130 if (!n)
131 break;
132
133 /* --- Pop an entry from the stack --- */
134
135 {
136 key_packstruct *kkp = (kps++)->kp.p;
137 kf = kkp->kp.p;
138 kkp->kp.p = kp;
139 n--;
140 }
141 }
142
143 /* --- We're done --- */
144
145 return (kpd);
146}
147
148/* --- @key_fetch@ --- *
149 *
150 * Arguments: @key_packdef *kp@ = pointer to packing structure
151 * @key *k@ = key file containing desired key
152 *
153 * Returns: Error code, or zero.
154 *
155 * Use: Fetches an unpacked key from a packed one.
156 */
157
158int key_fetch(key_packdef *kp, key *k)
159{
160 dstr d = DSTR_INIT;
161 int e;
162
163 key_fulltag(k, &d);
164 e = key_unpack(kp, &k->k, &d);
165 dstr_destroy(&d);
166 return (e);
167}
168
169/* --- @key_fetchbyname@ --- *
170 *
171 * Arguments: @key_packdef *kp@ = pointer to packing structure
172 * @key_file *kf@ = key file containing desired key
173 * @const char *tag@ = user's tag describing the key
174 *
175 * Returns: Error code, or zero.
176 *
177 * Use: Fetches a named key from a key file and unpacks it
178 * conveniently.
179 */
180
181int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
182{
183 dstr d = DSTR_INIT;
184 key_data *kd;
185 int e;
186
187 if (key_qtag(kf, tag, &d, 0, &kd))
188 e = KERR_NOTFOUND;
189 else
190 e = key_unpack(kp, kd, &d);
191 dstr_destroy(&d);
192 return (e);
193}
194
195/* --- @key_fetchdone@ --- *
196 *
197 * Arguments: @key_packdef *kp@ = pointer to packing structure
198 *
199 * Returns: ---
200 *
201 * Use: Frees a packing structure. If the structure was allocated by
202 * @key_fetchinit@ then it is freed.
203 */
204
205void key_fetchdone(key_packdef *kp)
206{
207 key_packstruct *kps = (key_packstruct *)(((char *)kp) -
208 offsetof(key_packstruct, kp));
209 key_unpackdone(kp);
210 if (kps->name)
211 free(kps);
212}
213
214/*----- That's all, folks -------------------------------------------------*/