chiark / gitweb /
Fix daft error in the comment for @gfshare_get@.
[catacomb] / mgf-def.h
1 /* -*-c-*-
2  *
3  * $Id: mgf-def.h,v 1.1 2000/06/17 11:33:11 mdw Exp $
4  *
5  * Definitions for the MGF-1 mask generator
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: mgf-def.h,v $
33  * Revision 1.1  2000/06/17 11:33:11  mdw
34  * MGF-1 support, as defined in PKCS#1.
35  *
36  */
37
38 #ifndef CATACOMB_MGF_DEF_H
39 #define CATACOMB_MGF_DEF_H
40
41 #ifdef __cplusplus
42   extern "C" {
43 #endif
44
45 /*----- Header files ------------------------------------------------------*/
46
47 #include <stdarg.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 #include <mLib/bits.h>
52 #include <mLib/sub.h>
53
54 #ifndef CATACOMB_ARENA_H
55 #  include "arena.h"
56 #endif
57
58 #ifndef CATACOMB_GCIPHER_H
59 #  include "gcipher.h"
60 #endif
61
62 #ifndef CATACOMB_GRAND_H
63 #  include "grand.h"
64 #endif
65
66 #ifndef CATACOMB_PARANOIA_H
67 #  include "paranoia.h"
68 #endif
69
70 /*----- Macros ------------------------------------------------------------*/
71
72 #define MGF_DEF(PRE, pre)                                               \
73                                                                         \
74 /* --- Useful constants --- */                                          \
75                                                                         \
76 const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ };               \
77                                                                         \
78 /* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                         \
79  *                                                                      \
80  * Arguments:   @pre_mgfctx *k@ = pointer to context to initialize      \
81  *              @const void *p@ = pointer to data to contribute         \
82  *                                                                      \
83  * Returns:     ---                                                     \
84  *                                                                      \
85  * Use:         A multi-step keying procedure for initializing an MGF   \
86  *              context.  The data is contributed to a hashing context  \
87  *              which is then used for mask generation.  If you only    \
88  *              have a fixed buffer, you can save a lot of effort by    \
89  *              simply calling @pre_mgfinit@.                           \
90  */                                                                     \
91                                                                         \
92 void pre##_mgfkeybegin(pre##_mgfctx *k)                                 \
93 {                                                                       \
94   k->c = 0;                                                             \
95   k->bsz = 0;                                                           \
96   pre##_init(&k->k);                                                    \
97 }                                                                       \
98                                                                         \
99 void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz)         \
100 {                                                                       \
101   pre##_hash(&k->k, p, sz);                                             \
102 }                                                                       \
103                                                                         \
104 /* ---- @pre_mgfinit@ --- *                                             \
105  *                                                                      \
106  * Arguments:   @pre_mgfctx *k@ = pointer to context to initialize      \
107  *              @const void *p@ = pointer to data to contribute         \
108  *              @size_t sz@ = size of data to contribute                \
109  *                                                                      \
110  * Returns:     ---                                                     \
111  *                                                                      \
112  * Use:         A simpler interface to initialization if all of your    \
113  *              keying material is in one place.                        \
114  */                                                                     \
115                                                                         \
116 void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz)           \
117 {                                                                       \
118   k->c = 0;                                                             \
119   k->bsz = 0;                                                           \
120   pre##_init(&k->k);                                                    \
121   pre##_hash(&k->k, p, sz);                                             \
122 }                                                                       \
123                                                                         \
124 /* --- @pre_mgfencrypt@ --- *                                           \
125  *                                                                      \
126  * Arguments:   @pre_mgfctx *k@ = pointer to masking context            \
127  *              @const void *s@ = pointer to source buffer              \
128  *              @void *d@ = pointer to destination buffer               \
129  *              @size_t sz@ = size of buffers                           \
130  *                                                                      \
131  * Returns:     ---                                                     \
132  *                                                                      \
133  * Use:         Outputs pseudorandom data, or masks an input buffer.    \
134  *                                                                      \
135  *              If @s@ is nonzero, the source material is exclusive-    \
136  *              orred with the generated mask.  If @d@ is zero, the     \
137  *              generator is simply spun around for a while, which      \
138  *              isn't very useful.                                      \
139  */                                                                     \
140                                                                         \
141 void pre##_mgfencrypt(pre##_mgfctx *k, const void *s,                   \
142                       void *d, size_t sz)                               \
143 {                                                                       \
144   const octet *ss = s;                                                  \
145   octet *dd = d;                                                        \
146                                                                         \
147   /* --- Empty the buffer if there's anything there --- */              \
148                                                                         \
149   if (k->bsz) {                                                         \
150     const octet *p = k->buf + PRE##_HASHSZ - k->bsz;                    \
151     size_t n = sz > k->bsz ? k->bsz : sz;                               \
152     sz -= n;                                                            \
153     k->bsz -= n;                                                        \
154     if (dd) {                                                           \
155       if (!ss) {                                                        \
156         memcpy(dd, p, n);                                               \
157         dd += n;                                                        \
158       } else {                                                          \
159         while (n) {                                                     \
160           *dd++ = *ss++ ^ *p++;                                         \
161           n--;                                                          \
162         }                                                               \
163       }                                                                 \
164     }                                                                   \
165   }                                                                     \
166                                                                         \
167   /* --- While necessary, generate some more mask --- */                \
168                                                                         \
169   while (sz) {                                                          \
170     pre##_ctx c = k->k;         /* Not quick! */                        \
171     size_t n;                                                           \
172                                                                         \
173     STORE32(k->buf, k->c);                                              \
174     k->c++;                                                             \
175     pre##_hash(&c, k->buf, 4);                                          \
176     pre##_done(&c, k->buf);                                             \
177     n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz;                          \
178     k->bsz = PRE##_HASHSZ - n;                                          \
179     sz -= n;                                                            \
180     if (dd) {                                                           \
181       const octet *p = k->buf;                                          \
182       if (!ss) {                                                        \
183         memcpy(dd, p, n);                                               \
184         dd += n;                                                        \
185       } else {                                                          \
186         while (n) {                                                     \
187           *dd++ = *ss++ ^ *p++;                                         \
188           n--;                                                          \
189         }                                                               \
190       }                                                                 \
191     }                                                                   \
192   }                                                                     \
193 }                                                                       \
194                                                                         \
195 /* --- @pre_mgfsetindex@ --- *                                          \
196  *                                                                      \
197  * Arguments:   @pre_mgfctx *k@ = pointer to masking context            \
198  *              @uint32 *c@ = new index to set                          \
199  *                                                                      \
200  * Returns:     ---                                                     \
201  *                                                                      \
202  * Use:         Sets a new index.  This may be used to step around the  \
203  *              output stream in a rather crude way.                    \
204  */                                                                     \
205                                                                         \
206 void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c)                       \
207 {                                                                       \
208   k->c = c;                                                             \
209   k->bsz = 0;                                                           \
210 }                                                                       \
211                                                                         \
212 /* --- Generic cipher interface --- */                                  \
213                                                                         \
214 static const gcipher_ops gops;                                          \
215                                                                         \
216 typedef struct gctx {                                                   \
217   gcipher c;                                                            \
218   pre##_mgfctx k;                                                       \
219 } gctx;                                                                 \
220                                                                         \
221 static gcipher *ginit(const void *k, size_t sz)                         \
222 {                                                                       \
223   gctx *g = S_CREATE(gctx);                                             \
224   g->c.ops = &gops;                                                     \
225   pre##_mgfinit(&g->k, k, sz);                                          \
226   return (&g->c);                                                       \
227 }                                                                       \
228                                                                         \
229 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
230 {                                                                       \
231   gctx *g = (gctx *)c;                                                  \
232   pre##_mgfencrypt(&g->k, s, t, sz);                                    \
233 }                                                                       \
234                                                                         \
235 static void gdestroy(gcipher *c)                                        \
236 {                                                                       \
237   gctx *g = (gctx *)c;                                                  \
238   BURN(*g);                                                             \
239   S_DESTROY(g);                                                         \
240 }                                                                       \
241                                                                         \
242 static const gcipher_ops gops = {                                       \
243   &pre##_mgf,                                                           \
244   gencrypt, gencrypt, gdestroy, 0, 0                                    \
245 };                                                                      \
246                                                                         \
247 const gccipher pre##_mgf = {                                            \
248   #pre "-mgf", pre##_mgfkeysz, 0,                                       \
249   ginit                                                                 \
250 };                                                                      \
251                                                                         \
252 /* --- Generic random number generator interface --- */                 \
253                                                                         \
254 typedef struct grctx {                                                  \
255   grand r;                                                              \
256   pre##_mgfctx k;                                                       \
257 } grctx;                                                                \
258                                                                         \
259 static void grdestroy(grand *r)                                         \
260 {                                                                       \
261   grctx *g = (grctx *)r;                                                \
262   BURN(*g);                                                             \
263   S_DESTROY(g);                                                         \
264 }                                                                       \
265                                                                         \
266 static int grmisc(grand *r, unsigned op, ...)                           \
267 {                                                                       \
268   grctx *g = (grctx *)r;                                                \
269   va_list ap;                                                           \
270   int rc = 0;                                                           \
271   va_start(ap, op);                                                     \
272                                                                         \
273   switch (op) {                                                         \
274     case GRAND_CHECK:                                                   \
275       switch (va_arg(ap, unsigned)) {                                   \
276         case GRAND_CHECK:                                               \
277         case GRAND_SEEDINT:                                             \
278         case GRAND_SEEDUINT32:                                          \
279         case GRAND_SEEDBLOCK:                                           \
280         case GRAND_SEEDRAND:                                            \
281           rc = 1;                                                       \
282           break;                                                        \
283         default:                                                        \
284           rc = 0;                                                       \
285           break;                                                        \
286       }                                                                 \
287       break;                                                            \
288     case GRAND_SEEDINT:                                                 \
289       pre##_mgfsetindex(&g->k, va_arg(ap, unsigned));                   \
290       break;                                                            \
291     case GRAND_SEEDUINT32:                                              \
292       pre##_mgfsetindex(&g->k, va_arg(ap, uint32));                     \
293       break;                                                            \
294     case GRAND_SEEDBLOCK: {                                             \
295       const void *p = va_arg(ap, const void *);                         \
296       size_t sz = va_arg(ap, size_t);                                   \
297       pre##_hash(&g->k.k, p, sz);                                       \
298     } break;                                                            \
299     case GRAND_SEEDRAND: {                                              \
300       octet buf[PRE##_BUFSZ];                                           \
301       grand *rr = va_arg(ap, grand *);                                  \
302       rr->ops->fill(rr, buf, sizeof(buf));                              \
303       pre##_hash(&g->k.k, buf, sizeof(buf));                            \
304     } break;                                                            \
305     default:                                                            \
306       GRAND_BADOP;                                                      \
307       break;                                                            \
308   }                                                                     \
309                                                                         \
310   va_end(ap);                                                           \
311   return (rc);                                                          \
312 }                                                                       \
313                                                                         \
314 static octet grbyte(grand *r)                                           \
315 {                                                                       \
316   grctx *g = (grctx *)r;                                                \
317   octet o;                                                              \
318   pre##_mgfencrypt(&g->k, 0, &o, 1);                                    \
319   return (o);                                                           \
320 }                                                                       \
321                                                                         \
322 static uint32 grword(grand *r)                                          \
323 {                                                                       \
324   grctx *g = (grctx *)r;                                                \
325   octet b[4];                                                           \
326   pre##_mgfencrypt(&g->k, 0, b, sizeof(b));                             \
327   return (LOAD32(b));                                                   \
328 }                                                                       \
329                                                                         \
330 static void grfill(grand *r, void *p, size_t sz)                        \
331 {                                                                       \
332   grctx *g = (grctx *)r;                                                \
333   pre##_mgfencrypt(&g->k, 0, p, sz);                                    \
334 }                                                                       \
335                                                                         \
336 static const grand_ops grops = {                                        \
337   #pre "-mgf",                                                          \
338   GRAND_CRYPTO, 0,                                                      \
339   grmisc, grdestroy,                                                    \
340   grword, grbyte, grword, grand_range, grfill                           \
341 };                                                                      \
342                                                                         \
343 /* --- @pre_mgfrand@ --- *                                              \
344  *                                                                      \
345  * Arguments:   @const void *k@ = pointer to key material               \
346  *              @size_t sz@ = size of key material                      \
347  *                                                                      \
348  * Returns:     Pointer to a generic random number generator instance.  \
349  *                                                                      \
350  * Use:         Creates a random number interface wrapper around an     \
351  *              MGF-1-mode hash function.                               \
352  */                                                                     \
353                                                                         \
354 extern grand *pre##_mgfrand(const void *k, size_t sz)                   \
355 {                                                                       \
356   grctx *g = S_CREATE(grctx);                                           \
357   g->r.ops = &grops;                                                    \
358   pre##_mgfinit(&g->k, k, sz);                                          \
359   return (&g->r);                                                       \
360 }                                                                       \
361                                                                         \
362 MGF_TEST(PRE, pre)
363
364 /*----- Test rig ----------------------------------------------------------*/
365
366 #ifdef TEST_RIG
367
368 #include <stdio.h>
369
370 #include "daftstory.h"
371
372 /* --- @MGF_TEST@ --- *
373  *
374  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
375  *
376  * Use:         Standard test rig for MGF functions.
377  */
378
379 #define MGF_TEST(PRE, pre)                                              \
380                                                                         \
381 /* --- Initial plaintext for the test --- */                            \
382                                                                         \
383 static const octet text[] = TEXT;                                       \
384                                                                         \
385 /* --- Key and IV to use --- */                                         \
386                                                                         \
387 static const octet key[] = KEY;                                         \
388                                                                         \
389 /* --- Buffers for encryption and decryption output --- */              \
390                                                                         \
391 static octet ct[sizeof(text)];                                          \
392 static octet pt[sizeof(text)];                                          \
393                                                                         \
394 static void hexdump(const octet *p, size_t sz)                          \
395 {                                                                       \
396   const octet *q = p + sz;                                              \
397   for (sz = 0; p < q; p++, sz++) {                                      \
398     printf("%02x", *p);                                                 \
399     if ((sz + 1) % PRE##_HASHSZ == 0)                                   \
400       putchar(':');                                                     \
401   }                                                                     \
402 }                                                                       \
403                                                                         \
404 int main(void)                                                          \
405 {                                                                       \
406   size_t sz = 0, rest;                                                  \
407   pre##_mgfctx ctx;                                                     \
408   int status = 0;                                                       \
409   int done = 0;                                                         \
410                                                                         \
411   size_t keysz = strlen((const char *)key);                             \
412                                                                         \
413   fputs(#pre "-mgf: ", stdout);                                         \
414                                                                         \
415   pre##_mgfinit(&ctx, key, keysz);                                      \
416                                                                         \
417   while (sz <= sizeof(text)) {                                          \
418     rest = sizeof(text) - sz;                                           \
419     memcpy(ct, text, sizeof(text));                                     \
420     pre##_mgfsetindex(&ctx, 0);                                         \
421     pre##_mgfencrypt(&ctx, ct, ct, sz);                                 \
422     pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest);                     \
423     memcpy(pt, ct, sizeof(text));                                       \
424     pre##_mgfsetindex(&ctx, 0);                                         \
425     pre##_mgfencrypt(&ctx, pt, pt, rest);                               \
426     pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz);                   \
427     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
428       done++;                                                           \
429       if (sizeof(text) < 40 || done % 8 == 0)                           \
430         fputc('.', stdout);                                             \
431       if (done % 480 == 0)                                              \
432         fputs("\n\t", stdout);                                          \
433       fflush(stdout);                                                   \
434     } else {                                                            \
435       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
436       status = 1;                                                       \
437       printf("\tplaintext      = "); hexdump(text, sz);                 \
438         printf(", "); hexdump(text + sz, rest);                         \
439         fputc('\n', stdout);                                            \
440       printf("\tciphertext     = "); hexdump(ct, sz);                   \
441         printf(", "); hexdump(ct + sz, rest);                           \
442         fputc('\n', stdout);                                            \
443       printf("\trecovered text = "); hexdump(pt, sz);                   \
444         printf(", "); hexdump(pt + sz, rest);                           \
445         fputc('\n', stdout);                                            \
446       fputc('\n', stdout);                                              \
447     }                                                                   \
448     if (sz < 63)                                                        \
449       sz++;                                                             \
450     else                                                                \
451       sz += 9;                                                          \
452   }                                                                     \
453                                                                         \
454   fputs(status ? " failed\n" : " ok\n", stdout);                        \
455   return (status);                                                      \
456 }
457
458 #else
459 #  define MGF_TEST(PRE, pre)
460 #endif
461
462 /*----- That's all, folks -------------------------------------------------*/
463
464 #ifdef __cplusplus
465   }
466 #endif
467
468 #endif