math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / key / key-pack.c
CommitLineData
e56dff91 1/* -*-c-*-
2 *
e56dff91 3 * Packing and unpacking key data
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
e56dff91 9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
45c0fd36 16 *
e56dff91 17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
45c0fd36 21 *
e56dff91 22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
e56dff91 28/*----- Header files ------------------------------------------------------*/
29
30#include <mLib/dstr.h>
31
e56dff91 32#include "key-data.h"
33
34/*----- Generic packing and unpacking -------------------------------------*/
35
36/* --- @key_pack@ --- *
37 *
38 * Arguments: @key_packdef *kp@ = pointer to packing structure
ef13e9a4 39 * @key_data **kd@ = where to put the key data pointer
e56dff91 40 * @dstr *d@ = pointer to tag string for the key data
41 *
42 * Returns: Error code, or zero.
43 *
44 * Use: Packs a key from a data structure.
45 */
46
ef13e9a4 47int key_pack(key_packdef *kp, key_data **kd, dstr *d)
e56dff91 48{
ef13e9a4 49 switch (kp->e & KF_ENCMASK) {
e56dff91 50
51 /* --- Binary and integer keys are easy --- */
52
ef13e9a4 53 case KENC_BINARY: {
54 key_bin *b = kp->p;
55 *kd = key_newbinary(kp->e, b->k, b->sz);
e56dff91 56 return (0);
ef13e9a4 57 }
e56dff91 58 case KENC_MP:
ef13e9a4 59 *kd = key_newmp(kp->e, *(mp **)kp->p);
e56dff91 60 return (0);
1ba83484 61 case KENC_STRING:
ef13e9a4 62 *kd = key_newstring(kp->e, *(char **)kp->p);
1ba83484 63 return (0);
64 case KENC_EC:
ef13e9a4 65 *kd = key_newec(kp->e, (ec *)kp->p);
1ba83484 66 return (0);
e56dff91 67
68 /* --- Encrypted keys are a little tricky --- *
69 *
70 * This works rather differently to unpacking.
71 */
72
73 case KENC_ENCRYPT: {
ef13e9a4 74 key_data *kkd;
e56dff91 75 int err = key_pack(kp->p, &kkd, d);
76 if (!err) {
ef13e9a4 77 err = key_plock(kd, kkd, d->buf);
78 key_drop(kkd);
e56dff91 79 }
80 return (err);
81 }
82
83 /* --- Structured keys, as ever, are a nuisance --- */
84
85 case KENC_STRUCT: {
86 int err;
87 key_packstruct *p;
88 size_t l = d->len;
89
ef13e9a4 90 *kd = key_newstruct();
e56dff91 91 DPUTC(d, '.');
92 for (p = kp->p; p->name; p++) {
93 key_data *kkd;
94 d->len = l + 1;
95 DPUTS(d, p->name);
ef13e9a4 96 if ((err = key_pack(&p->kp, &kkd, d)) != 0) {
97 key_drop(*kd);
e56dff91 98 return (err);
99 }
ef13e9a4 100 key_structsteal(*kd, p->name, kkd);
e56dff91 101 }
102 d->len = l;
103 d->buf[l] = 0;
104 return (0);
105 }
ef13e9a4 106 default:
107 abort();
e56dff91 108 }
e56dff91 109}
110
111/* --- @key_unpack@ --- *
112 *
113 * Arguments: @key_packdef *kp@ = pointer to packing structure
114 * @key_data *kd@ = pointer to source key data
115 * @dstr *d@ = pointer to tag string for the key data
116 *
117 * Returns: Error code, or zero.
118 *
119 * Use: Unpacks a key into an appropriate data structure.
120 */
121
122int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
123{
ef13e9a4 124 unsigned e = kp->e & KF_ENCMASK;
e56dff91 125 int err;
126
127 /* --- Decrypt the encrypted key --- */
128
ef13e9a4 129 if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
130 if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0)
e56dff91 131 goto fail;
ef13e9a4 132 kd = kp->kd;
e56dff91 133 }
134
135 /* --- Ensure that the key has the right type --- */
136
137 if ((kd->e & KF_ENCMASK) != e) {
f387fcb1 138 err = KERR_WRONGTYPE;
e56dff91 139 goto fail;
140 }
141
142 /* --- Unpack the key --- *
143 *
144 * Only three possibilities left now.
145 */
146
147 switch (e) {
148
149 /* --- Binary and integer keys are easy --- */
150
151 case KENC_BINARY:
152 *(key_bin *)kp->p = kd->u.k;
153 break;
154 case KENC_MP:
155 *(mp **)kp->p = kd->u.m;
156 break;
1ba83484 157 case KENC_STRING:
158 *(char **)kp->p = kd->u.p;
159 break;
160 case KENC_EC:
161 *(ec *)kp->p = kd->u.e;
162 break;
e56dff91 163
164 /* --- Structured keys take a little care --- */
165
166 case KENC_STRUCT: {
167 key_packstruct *p, *q;
168 size_t l = d->len;
169
170 /* --- Iterate over the requested subparts --- */
171
172 DPUTC(d, '.');
173 for (p = kp->p; p->name; p++) {
174 key_data *kkd;
175
176 /* --- Build the name --- */
177
178 d->len = l + 1;
179 DPUTS(d, p->name);
180
181 /* --- Find and unpack the subkey --- */
182
183 if ((kkd = key_structfind(kd, p->name)) == 0) {
ef13e9a4 184 if (!(p->kp.e & KF_OPT)) {
e56dff91 185 err = KERR_NOTFOUND;
186 goto tidy;
187 }
188 } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
189 p++;
190 goto tidy;
191 }
192 }
193
194 /* --- Done --- */
195
196 d->len = l;
197 d->buf[l] = 0;
198 break;
199
200 /* --- Tidy up if something went wrong --- */
201
202 tidy:
203 for (q = kp->p; q < p; q++)
204 key_unpackdone(&q->kp);
205 goto fail;
206 }
ef13e9a4 207
208 default:
209 abort();
e56dff91 210 }
211
212 return (0);
213
214 /* --- Something went wrong --- */
215
216fail:
ef13e9a4 217 if (kp->kd) {
218 key_drop(kp->kd);
219 kp->kd = 0;
220 }
e56dff91 221 return (err);
222}
223
224/* --- @key_unpackdone@ --- *
225 *
226 * Arguments: @key_packdef *kp@ = pointer to packing definition
227 *
228 * Returns: ---
229 *
230 * Use: Frees the key components contained within a packing
231 * definition, created during key unpacking.
232 */
233
234void key_unpackdone(key_packdef *kp)
235{
ef13e9a4 236 if (kp->kd) {
237 key_drop(kp->kd);
238 kp->kd = 0;
239 }
240 if ((kp->e & KF_ENCMASK) == KENC_STRUCT) {
e56dff91 241 key_packstruct *p;
242 for (p = kp->p; p->name; p++)
243 key_unpackdone(&p->kp);
244 }
245}
246
247/*----- That's all, folks -------------------------------------------------*/