chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[catacomb] / symm / mgf-def.h
1 /* -*-c-*-
2  *
3  * Definitions for the MGF-1 mask generator
4  *
5  * (c) 2000 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
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.
16  *
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.
21  *
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
28 #ifndef CATACOMB_MGF_DEF_H
29 #define CATACOMB_MGF_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <mLib/bits.h>
42 #include <mLib/sub.h>
43
44 #ifndef CATACOMB_ARENA_H
45 #  include "arena.h"
46 #endif
47
48 #ifndef CATACOMB_GCIPHER_H
49 #  include "gcipher.h"
50 #endif
51
52 #ifndef CATACOMB_GRAND_H
53 #  include "grand.h"
54 #endif
55
56 #ifndef CATACOMB_PARANOIA_H
57 #  include "paranoia.h"
58 #endif
59
60 /*----- Macros ------------------------------------------------------------*/
61
62 #define MGF_DEF(PRE, pre) MGF_DEFX(PRE, pre, #pre, #pre)
63
64 #define MGF_DEFX(PRE, pre, name, fname)                                 \
65                                                                         \
66 /* --- Useful constants --- */                                          \
67                                                                         \
68 const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ };               \
69                                                                         \
70 /* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                         \
71  *                                                                      \
72  * Arguments:   @pre_mgfctx *k@ = pointer to context to initialize      \
73  *              @const void *p@ = pointer to data to contribute         \
74  *                                                                      \
75  * Returns:     ---                                                     \
76  *                                                                      \
77  * Use:         A multi-step keying procedure for initializing an MGF   \
78  *              context.  The data is contributed to a hashing context  \
79  *              which is then used for mask generation.  If you only    \
80  *              have a fixed buffer, you can save a lot of effort by    \
81  *              simply calling @pre_mgfinit@.                           \
82  */                                                                     \
83                                                                         \
84 void pre##_mgfkeybegin(pre##_mgfctx *k)                                 \
85   { k->c = 0; k->off = 0; pre##_init(&k->k); }                          \
86                                                                         \
87 void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz)         \
88   { pre##_hash(&k->k, p, sz); }                                         \
89                                                                         \
90 /* ---- @pre_mgfinit@ --- *                                             \
91  *                                                                      \
92  * Arguments:   @pre_mgfctx *k@ = pointer to context to initialize      \
93  *              @const void *p@ = pointer to data to contribute         \
94  *              @size_t sz@ = size of data to contribute                \
95  *                                                                      \
96  * Returns:     ---                                                     \
97  *                                                                      \
98  * Use:         A simpler interface to initialization if all of your    \
99  *              keying material is in one place.                        \
100  */                                                                     \
101                                                                         \
102 void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz)           \
103   { k->c = 0; k->off = 0; pre##_init(&k->k); pre##_hash(&k->k, p, sz); } \
104                                                                         \
105 /* --- @pre_mgfencrypt@ --- *                                           \
106  *                                                                      \
107  * Arguments:   @pre_mgfctx *k@ = pointer to masking context            \
108  *              @const void *s@ = pointer to source buffer              \
109  *              @void *d@ = pointer to destination buffer               \
110  *              @size_t sz@ = size of buffers                           \
111  *                                                                      \
112  * Returns:     ---                                                     \
113  *                                                                      \
114  * Use:         Outputs pseudorandom data, or masks an input buffer.    \
115  *                                                                      \
116  *              If @s@ is nonzero, the source material is exclusive-    \
117  *              orred with the generated mask.  If @d@ is zero, the     \
118  *              generator is simply spun around for a while, which      \
119  *              isn't very useful.                                      \
120  */                                                                     \
121                                                                         \
122 void pre##_mgfencrypt(pre##_mgfctx *k, const void *s,                   \
123                       void *d, size_t sz)                               \
124 {                                                                       \
125   pre##_ctx h;                                                          \
126   const octet *ss = s;                                                  \
127   octet *dd = d;                                                        \
128   const octet *p;                                                       \
129   size_t off;                                                           \
130                                                                         \
131   /* --- Empty the buffer if there's anything there --- */              \
132                                                                         \
133   if (k->off) {                                                         \
134     p = k->b + PRE##_HASHSZ - k->off;                                   \
135     off = sz > k->off ? k->off : sz;                                    \
136     sz -= off; k->off -= off;                                           \
137     if (!dd) /* do nothing */;                                          \
138     else if (!ss) { memcpy(dd, p, off); dd += off; }                    \
139     else while (off--) *dd++ = *ss++ ^ *p++;                            \
140   }                                                                     \
141                                                                         \
142   /* --- While necessary, generate some more mask --- */                \
143                                                                         \
144   while (sz) {                                                          \
145     STORE32(k->b, k->c); k->c++;                                        \
146     h = k->k; pre##_hash(&h, k->b, 4); pre##_done(&h, k->b);            \
147     off = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz;                        \
148     k->off = PRE##_HASHSZ - off;                                        \
149     sz -= off;                                                          \
150     p = k->b;                                                           \
151     if (!dd) /* do nothing */;                                          \
152     else if (!ss) { memcpy(dd, p, off); dd += off; }                    \
153     else while (off--) *dd++ = *ss++ ^ *p++;                            \
154   }                                                                     \
155 }                                                                       \
156                                                                         \
157 /* --- @pre_mgfsetindex@ --- *                                          \
158  *                                                                      \
159  * Arguments:   @pre_mgfctx *k@ = pointer to masking context            \
160  *              @uint32 *c@ = new index to set                          \
161  *                                                                      \
162  * Returns:     ---                                                     \
163  *                                                                      \
164  * Use:         Sets a new index.  This may be used to step around the  \
165  *              output stream in a rather crude way.                    \
166  */                                                                     \
167                                                                         \
168 void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c)                       \
169   { k->c = c; k->off = 0; }                                             \
170                                                                         \
171 /* --- Generic cipher interface --- */                                  \
172                                                                         \
173 static const gcipher_ops gops;                                          \
174                                                                         \
175 typedef struct gctx {                                                   \
176   gcipher c;                                                            \
177   pre##_mgfctx k;                                                       \
178 } gctx;                                                                 \
179                                                                         \
180 static gcipher *ginit(const void *k, size_t sz)                         \
181 {                                                                       \
182   gctx *g = S_CREATE(gctx);                                             \
183   g->c.ops = &gops;                                                     \
184   pre##_mgfinit(&g->k, k, sz);                                          \
185   return (&g->c);                                                       \
186 }                                                                       \
187                                                                         \
188 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
189   { gctx *g = (gctx *)c; pre##_mgfencrypt(&g->k, s, t, sz); }           \
190                                                                         \
191 static void gdestroy(gcipher *c)                                        \
192   { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }                      \
193                                                                         \
194 static const gcipher_ops gops = {                                       \
195   &pre##_mgf,                                                           \
196   gencrypt, gencrypt, gdestroy, 0, 0                                    \
197 };                                                                      \
198                                                                         \
199 const gccipher pre##_mgf = {                                            \
200   name "-mgf", pre##_mgfkeysz, 0,                                       \
201   ginit                                                                 \
202 };                                                                      \
203                                                                         \
204 /* --- Generic random number generator interface --- */                 \
205                                                                         \
206 typedef struct grctx {                                                  \
207   grand r;                                                              \
208   pre##_mgfctx k;                                                       \
209 } grctx;                                                                \
210                                                                         \
211 static void grdestroy(grand *r)                                         \
212 {                                                                       \
213   grctx *g = (grctx *)r;                                                \
214   BURN(*g);                                                             \
215   S_DESTROY(g);                                                         \
216 }                                                                       \
217                                                                         \
218 static int grmisc(grand *r, unsigned op, ...)                           \
219 {                                                                       \
220   grctx *g = (grctx *)r;                                                \
221   va_list ap;                                                           \
222   int rc = 0;                                                           \
223   va_start(ap, op);                                                     \
224                                                                         \
225   switch (op) {                                                         \
226     case GRAND_CHECK:                                                   \
227       switch (va_arg(ap, unsigned)) {                                   \
228         case GRAND_CHECK:                                               \
229         case GRAND_SEEDINT:                                             \
230         case GRAND_SEEDUINT32:                                          \
231         case GRAND_SEEDBLOCK:                                           \
232         case GRAND_SEEDRAND:                                            \
233           rc = 1;                                                       \
234           break;                                                        \
235         default:                                                        \
236           rc = 0;                                                       \
237           break;                                                        \
238       }                                                                 \
239       break;                                                            \
240     case GRAND_SEEDINT:                                                 \
241       pre##_mgfsetindex(&g->k, va_arg(ap, unsigned));                   \
242       break;                                                            \
243     case GRAND_SEEDUINT32:                                              \
244       pre##_mgfsetindex(&g->k, va_arg(ap, uint32));                     \
245       break;                                                            \
246     case GRAND_SEEDBLOCK: {                                             \
247       const void *p = va_arg(ap, const void *);                         \
248       size_t sz = va_arg(ap, size_t);                                   \
249       pre##_hash(&g->k.k, p, sz);                                       \
250     } break;                                                            \
251     case GRAND_SEEDRAND: {                                              \
252       octet buf[PRE##_BUFSZ];                                           \
253       grand *rr = va_arg(ap, grand *);                                  \
254       rr->ops->fill(rr, buf, sizeof(buf));                              \
255       pre##_hash(&g->k.k, buf, sizeof(buf));                            \
256     } break;                                                            \
257     default:                                                            \
258       GRAND_BADOP;                                                      \
259       break;                                                            \
260   }                                                                     \
261                                                                         \
262   va_end(ap);                                                           \
263   return (rc);                                                          \
264 }                                                                       \
265                                                                         \
266 static octet grbyte(grand *r)                                           \
267 {                                                                       \
268   grctx *g = (grctx *)r;                                                \
269   octet o;                                                              \
270   pre##_mgfencrypt(&g->k, 0, &o, 1);                                    \
271   return (o);                                                           \
272 }                                                                       \
273                                                                         \
274 static uint32 grword(grand *r)                                          \
275 {                                                                       \
276   grctx *g = (grctx *)r;                                                \
277   octet b[4];                                                           \
278   pre##_mgfencrypt(&g->k, 0, b, sizeof(b));                             \
279   return (LOAD32(b));                                                   \
280 }                                                                       \
281                                                                         \
282 static void grfill(grand *r, void *p, size_t sz)                        \
283   { grctx *g = (grctx *)r; pre##_mgfencrypt(&g->k, 0, p, sz); }         \
284                                                                         \
285 static const grand_ops grops = {                                        \
286   name "-mgf",                                                          \
287   GRAND_CRYPTO, 0,                                                      \
288   grmisc, grdestroy,                                                    \
289   grword, grbyte, grword, grand_defaultrange, grfill                    \
290 };                                                                      \
291                                                                         \
292 /* --- @pre_mgfrand@ --- *                                              \
293  *                                                                      \
294  * Arguments:   @const void *k@ = pointer to key material               \
295  *              @size_t sz@ = size of key material                      \
296  *                                                                      \
297  * Returns:     Pointer to a generic random number generator instance.  \
298  *                                                                      \
299  * Use:         Creates a random number interface wrapper around an     \
300  *              MGF-1-mode hash function.                               \
301  */                                                                     \
302                                                                         \
303 extern grand *pre##_mgfrand(const void *k, size_t sz)                   \
304 {                                                                       \
305   grctx *g = S_CREATE(grctx);                                           \
306   g->r.ops = &grops;                                                    \
307   pre##_mgfinit(&g->k, k, sz);                                          \
308   return (&g->r);                                                       \
309 }                                                                       \
310                                                                         \
311 MGF_TESTX(PRE, pre, name, fname)
312
313 /*----- Test rig ----------------------------------------------------------*/
314
315 #define MGF_TEST(PRE, pre) MGF_TESTX(PRE, pre, #pre, #pre)
316
317 #ifdef TEST_RIG
318
319 #include "modes-test.h"
320
321 /* --- @MGF_TEST@ --- *
322  *
323  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
324  *
325  * Use:         Standard test rig for MGF functions.
326  */
327
328 #define MGF_TESTX(PRE, pre, name, fname)                                \
329                                                                         \
330 static pre##_mgfctx ctx;                                                \
331                                                                         \
332 static void pre##_mgf_test_setup(const octet *k, size_t ksz)            \
333   { pre##_mgfinit(&ctx, k, ksz); }                                      \
334                                                                         \
335 static void pre##_mgf_test_reset(const octet *iv)                       \
336   { pre##_mgfsetindex(&ctx, 0); }                                       \
337                                                                         \
338 static void pre##_mgf_test_enc(const octet *s, octet *d, size_t sz)     \
339   { pre##_mgfencrypt(&ctx, s, d, sz); }                                 \
340                                                                         \
341 int main(int argc, char *argv[])                                        \
342 {                                                                       \
343   return test_encmode(fname "-mgf", 0, PRE##_HASHSZ, 1, 0,              \
344                       pre##_mgf_test_setup, pre##_mgf_test_reset,       \
345                       pre##_mgf_test_enc, pre##_mgf_test_enc,           \
346                       argc, argv);                                      \
347 }
348
349 #else
350 #  define MGF_TESTX(PRE, pre, name, fname)
351 #endif
352
353 /*----- That's all, folks -------------------------------------------------*/
354
355 #ifdef __cplusplus
356   }
357 #endif
358
359 #endif