chiark / gitweb /
Add some more vectors, and a whinge about how Skipjack test vectors are.
[catacomb] / key-binary.c
1 /* -*-c-*-
2  *
3  * $Id: key-binary.c,v 1.2 2000/06/17 11:25:20 mdw Exp $
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 $
33  * Revision 1.2  2000/06/17 11:25:20  mdw
34  * Use secure memory interface from MP library.
35  *
36  * Revision 1.1  2000/02/12 18:21:02  mdw
37  * Overhaul of key management (again).
38  *
39  */
40
41 /*----- Header files ------------------------------------------------------*/
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <mLib/bits.h>
47 #include <mLib/dstr.h>
48 #include <mLib/sub.h>
49 #include <mLib/sym.h>
50
51 #include "key-data.h"
52 #include "mp.h"
53 #include "mptext.h"
54
55 /*----- Main code ---------------------------------------------------------*/
56
57 /* --- @key_decode@ --- *
58  *
59  * Arguments:   @const void *p@ = pointer to buffer to read
60  *              @size_t sz@ = size of the buffer
61  *              @key_data *k@ = pointer to key data block to write to
62  *
63  * Returns:     Zero if everything worked, nonzero otherwise.
64  *
65  * Use:         Decodes a binary representation of a key.
66  */
67
68 int key_decode(const void *p, size_t sz, key_data *k)
69 {
70   const octet *q = p;
71   size_t psz;
72   unsigned e;
73
74   /* --- Parse the header information --- *
75    *
76    * Make sure the size matches external reality.  Security holes have been
77    * known to creep in without this sort of check.  (No, this isn't an after-
78    * the-fact patch-up.)
79    */
80
81   e = LOAD16(q);
82   psz = LOAD16(q + 2);
83   if (psz + 4 > sz)
84     return (-1);
85   k->e = e;
86
87   /* --- Now decide what to do --- */
88
89   switch (e & KF_ENCMASK) {
90
91     /* --- Plain binary data --- */
92
93     case KENC_BINARY:
94     case KENC_ENCRYPT:
95       k->u.k.k = sub_alloc(psz);
96       memcpy(k->u.k.k, q + 4, psz);
97       k->u.k.sz = psz;
98       break;
99
100     /* --- Multiprecision integer data --- */
101
102     case KENC_MP:
103       k->u.m = mp_loadb(k->e & KF_BURN ? MP_NEWSEC : MP_NEW, q + 4, psz);
104       break;
105
106     /* --- Structured key data --- */
107
108     case KENC_STRUCT: {
109       dstr d = DSTR_INIT;
110       key_struct *ks;
111       unsigned f;
112
113       if ((k->e & ~KF_ENCMASK) || (psz & 3))
114         return (-1);
115       q += 4;
116       sym_create(&k->u.s);
117
118       while (psz) {
119
120         /* --- Read the tag string --- */
121
122         DRESET(&d);
123         sz = LOAD8(q);
124         if (sz >= psz)
125           goto fail;
126         DPUTM(&d, q + 1, sz);
127         DPUTZ(&d);
128         sz = (sz + 4) & ~3;
129         q += sz; psz -= sz;
130
131         /* --- Read the encoding and size --- */
132
133         e = LOAD16(q);
134         sz = (LOAD16(q + 2) + 7) & ~3;
135         if (sz > psz)
136           goto fail;
137
138         /* --- Create a table node and fill it in --- */
139
140         ks = sym_find(&k->u.s, d.buf, d.len + 1, sizeof(*ks), &f);
141         if (f)
142           goto fail;
143         if (key_decode(q, sz, &ks->k)) {
144           sym_remove(&k->u.s, ks);
145           goto fail;
146         }
147         psz -= sz;
148         q += sz;
149       }
150       dstr_destroy(&d);
151       break;
152
153       /* --- Tidy up after a failure --- */
154
155     fail:
156       dstr_destroy(&d);
157       key_destroy(k);
158       return (-1);
159     } break;
160
161     /* --- Everything else --- */
162
163     default:
164       return (-1);
165   }
166
167   /* --- OK, that was good --- */
168
169   return (0);
170 }
171
172 /* --- @key_encode@ --- *
173  *
174  * Arguments:   @key_data *k@ = pointer to key data block
175  *              @dstr *d@ = pointer to destination string
176  *              @const key_filter *kf@ = pointer to key selection block
177  *
178  * Returns:     Nonzero if an item was actually written.
179  *
180  * Use:         Encodes a key block as binary data.
181  */
182
183 int key_encode(key_data *k, dstr *d, const key_filter *kf)
184 {
185   int rc = 0;
186   if (!KEY_MATCH(k, kf))
187     return (0);
188   switch (k->e & KF_ENCMASK) {
189     case KENC_BINARY:
190     case KENC_ENCRYPT: {
191       char *p;
192
193       DENSURE(d, (k->u.k.sz + 7) & ~3);
194       p = d->buf + d->len;
195       STORE16(p, k->e);
196       STORE16(p + 2, k->u.k.sz);
197       d->len += 4;
198       DPUTM(d, k->u.k.k, k->u.k.sz);
199       rc = 1;
200     } break;
201
202     case KENC_MP: {
203       char *p;
204       size_t sz = mp_octets(k->u.m);
205
206       DENSURE(d, (sz + 7) & ~3);
207       p = d->buf + d->len;
208       STORE16(p, k->e);
209       STORE16(p + 2, sz);
210       mp_storeb(k->u.m, p + 4, sz);
211       d->len += sz + 4;
212       rc = 1;
213     } break;
214
215     case KENC_STRUCT: {
216       size_t n;
217       char *p;
218       key_struct *ks;
219       sym_iter i;
220
221       n = d->len;
222       DENSURE(d, 4);
223       p = d->buf + n;
224       STORE16(p, k->e & KF_ENCMASK);
225       d->len += 4;
226       for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) {
227         size_t o = d->len;
228         DENSURE(d, 1);
229         *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks));
230         DPUTS(d, SYM_NAME(ks));
231         while (d->len & 3)
232           DPUTC(d, 0);
233         if (key_encode(&ks->k, d, kf))
234           rc = 1;
235         else
236           d->len = o;
237       }
238       if (!rc)
239         d->len = n;
240       else {
241         p = d->buf + n + 2;
242         n = d->len - n - 4;
243         STORE16(p,  n);
244       }
245     } break;
246   }
247   while (d->len & 3)
248     DPUTC(d, 0);
249   return (rc);
250 }
251
252 /*----- That's all, folks -------------------------------------------------*/