chiark / gitweb /
Add some more vectors, and a whinge about how Skipjack test vectors are.
[catacomb] / key-fetch.c
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
60 static 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
72 key_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
158 int 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
181 int 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
205 void 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 -------------------------------------------------*/