Add cyclic group abstraction, with test code. Separate off exponentation
[u/mdw/catacomb] / key-binary.c
CommitLineData
052b36d0 1/* -*-c-*-
2 *
34e4f738 3 * $Id: key-binary.c,v 1.5 2004/04/01 12:50:09 mdw Exp $
052b36d0 4 *
5 * Key binary encoding
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-binary.c,v $
34e4f738 33 * Revision 1.5 2004/04/01 12:50:09 mdw
34 * Add cyclic group abstraction, with test code. Separate off exponentation
35 * functions for better static linking. Fix a buttload of bugs on the way.
36 * Generally ensure that negative exponents do inversion correctly. Add
37 * table of standard prime-field subgroups. (Binary field subgroups are
38 * currently unimplemented but easy to add if anyone ever finds a good one.)
39 *
1ba83484 40 * Revision 1.4 2004/03/28 01:58:47 mdw
41 * Generate, store and retreive elliptic curve keys.
42 *
0d4a06cd 43 * Revision 1.3 2001/02/03 11:57:00 mdw
44 * Track mLib change: symbols no longer need to include a terminating
45 * null.
46 *
99163693 47 * Revision 1.2 2000/06/17 11:25:20 mdw
48 * Use secure memory interface from MP library.
49 *
052b36d0 50 * Revision 1.1 2000/02/12 18:21:02 mdw
51 * Overhaul of key management (again).
52 *
53 */
54
55/*----- Header files ------------------------------------------------------*/
56
57#include <stdlib.h>
58#include <string.h>
59
60#include <mLib/bits.h>
61#include <mLib/dstr.h>
62#include <mLib/sub.h>
63#include <mLib/sym.h>
64
65#include "key-data.h"
66#include "mp.h"
67#include "mptext.h"
68
69/*----- Main code ---------------------------------------------------------*/
70
71/* --- @key_decode@ --- *
72 *
73 * Arguments: @const void *p@ = pointer to buffer to read
74 * @size_t sz@ = size of the buffer
75 * @key_data *k@ = pointer to key data block to write to
76 *
77 * Returns: Zero if everything worked, nonzero otherwise.
78 *
79 * Use: Decodes a binary representation of a key.
80 */
81
82int key_decode(const void *p, size_t sz, key_data *k)
83{
84 const octet *q = p;
85 size_t psz;
86 unsigned e;
87
88 /* --- Parse the header information --- *
89 *
90 * Make sure the size matches external reality. Security holes have been
91 * known to creep in without this sort of check. (No, this isn't an after-
92 * the-fact patch-up.)
93 */
94
95 e = LOAD16(q);
96 psz = LOAD16(q + 2);
97 if (psz + 4 > sz)
98 return (-1);
99 k->e = e;
100
101 /* --- Now decide what to do --- */
102
103 switch (e & KF_ENCMASK) {
104
105 /* --- Plain binary data --- */
106
107 case KENC_BINARY:
108 case KENC_ENCRYPT:
109 k->u.k.k = sub_alloc(psz);
110 memcpy(k->u.k.k, q + 4, psz);
111 k->u.k.sz = psz;
112 break;
113
114 /* --- Multiprecision integer data --- */
115
116 case KENC_MP:
99163693 117 k->u.m = mp_loadb(k->e & KF_BURN ? MP_NEWSEC : MP_NEW, q + 4, psz);
052b36d0 118 break;
119
1ba83484 120 /* --- String data --- */
121
122 case KENC_STRING:
123 k->u.p = xmalloc(sz + 1);
124 memcpy(k->u.p, q + 4, sz);
125 k->u.p[sz] = 0;
126 break;
127
128 /* --- Elliptic curve point data --- */
129
130 case KENC_EC: {
131 size_t xsz, ysz;
34e4f738 132 EC_CREATE(&k->u.e);
133 if (!sz) break;
1ba83484 134 if (sz < 2) return (-1);
135 xsz = LOAD16(q + 4);
136 if (sz < xsz + 4) return (-1);
137 ysz = LOAD16(q + 6 + xsz);
138 if (sz < xsz + ysz + 4) return (-1);
1ba83484 139 k->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
140 k->u.e.y = mp_loadb(MP_NEW, q + 6 + xsz, ysz);
141 } break;
142
052b36d0 143 /* --- Structured key data --- */
144
145 case KENC_STRUCT: {
146 dstr d = DSTR_INIT;
147 key_struct *ks;
148 unsigned f;
149
150 if ((k->e & ~KF_ENCMASK) || (psz & 3))
151 return (-1);
152 q += 4;
153 sym_create(&k->u.s);
154
155 while (psz) {
156
157 /* --- Read the tag string --- */
158
159 DRESET(&d);
160 sz = LOAD8(q);
161 if (sz >= psz)
162 goto fail;
163 DPUTM(&d, q + 1, sz);
164 DPUTZ(&d);
165 sz = (sz + 4) & ~3;
166 q += sz; psz -= sz;
167
168 /* --- Read the encoding and size --- */
169
170 e = LOAD16(q);
171 sz = (LOAD16(q + 2) + 7) & ~3;
172 if (sz > psz)
173 goto fail;
174
175 /* --- Create a table node and fill it in --- */
176
0d4a06cd 177 ks = sym_find(&k->u.s, d.buf, d.len, sizeof(*ks), &f);
052b36d0 178 if (f)
179 goto fail;
180 if (key_decode(q, sz, &ks->k)) {
181 sym_remove(&k->u.s, ks);
182 goto fail;
183 }
184 psz -= sz;
185 q += sz;
186 }
187 dstr_destroy(&d);
188 break;
189
190 /* --- Tidy up after a failure --- */
191
192 fail:
193 dstr_destroy(&d);
194 key_destroy(k);
195 return (-1);
196 } break;
197
198 /* --- Everything else --- */
199
200 default:
201 return (-1);
202 }
203
204 /* --- OK, that was good --- */
205
206 return (0);
207}
208
209/* --- @key_encode@ --- *
210 *
211 * Arguments: @key_data *k@ = pointer to key data block
212 * @dstr *d@ = pointer to destination string
213 * @const key_filter *kf@ = pointer to key selection block
214 *
215 * Returns: Nonzero if an item was actually written.
216 *
217 * Use: Encodes a key block as binary data.
218 */
219
220int key_encode(key_data *k, dstr *d, const key_filter *kf)
221{
222 int rc = 0;
223 if (!KEY_MATCH(k, kf))
224 return (0);
225 switch (k->e & KF_ENCMASK) {
226 case KENC_BINARY:
227 case KENC_ENCRYPT: {
228 char *p;
229
230 DENSURE(d, (k->u.k.sz + 7) & ~3);
231 p = d->buf + d->len;
232 STORE16(p, k->e);
233 STORE16(p + 2, k->u.k.sz);
234 d->len += 4;
235 DPUTM(d, k->u.k.k, k->u.k.sz);
236 rc = 1;
237 } break;
238
239 case KENC_MP: {
240 char *p;
241 size_t sz = mp_octets(k->u.m);
242
243 DENSURE(d, (sz + 7) & ~3);
244 p = d->buf + d->len;
245 STORE16(p, k->e);
246 STORE16(p + 2, sz);
247 mp_storeb(k->u.m, p + 4, sz);
248 d->len += sz + 4;
249 rc = 1;
250 } break;
251
1ba83484 252 case KENC_STRING: {
253 char *p;
254 size_t sz = strlen(k->u.p);
255
256 DENSURE(d, (sz + 7) & ~3);
257 p = d->buf + d->len;
258 STORE16(p, k->e);
259 STORE16(p + 2, sz);
260 memcpy(p + 4, k->u.p, sz);
261 d->len += sz + 4;
262 rc = 1;
263 } break;
264
265 case KENC_EC: {
266 char *p;
34e4f738 267 size_t xsz, ysz;
268 size_t sz;
1ba83484 269
34e4f738 270 if (EC_ATINF(&k->u.e))
271 sz = 0;
272 else {
273 xsz = mp_octets(k->u.e.x);
274 ysz = mp_octets(k->u.e.y);
275 sz = xsz + ysz + 4;
276 }
1ba83484 277 DENSURE(d, (sz + 7) & ~3);
278 p = d->buf + d->len;
279 STORE16(p, k->e);
280 STORE16(p + 2, sz);
34e4f738 281 if (!EC_ATINF(&k->u.e)) {
282 STORE16(p + 4, xsz);
283 mp_storeb(k->u.e.x, p + 6, xsz);
284 STORE16(p + 6 + xsz, ysz);
285 mp_storeb(k->u.e.y, p + 8 + xsz, ysz);
286 }
1ba83484 287 d->len += sz + 4;
288 rc = 1;
289 } break;
290
052b36d0 291 case KENC_STRUCT: {
292 size_t n;
293 char *p;
294 key_struct *ks;
295 sym_iter i;
296
297 n = d->len;
298 DENSURE(d, 4);
299 p = d->buf + n;
300 STORE16(p, k->e & KF_ENCMASK);
301 d->len += 4;
302 for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
303 size_t o = d->len;
304 DENSURE(d, 1);
305 *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks));
306 DPUTS(d, SYM_NAME(ks));
307 while (d->len & 3)
308 DPUTC(d, 0);
309 if (key_encode(&ks->k, d, kf))
310 rc = 1;
311 else
312 d->len = o;
313 }
314 if (!rc)
315 d->len = n;
316 else {
317 p = d->buf + n + 2;
318 n = d->len - n - 4;
319 STORE16(p, n);
320 }
321 } break;
322 }
323 while (d->len & 3)
324 DPUTC(d, 0);
325 return (rc);
326}
327
328/*----- That's all, folks -------------------------------------------------*/