Commit | Line | Data |
---|---|---|
fea9a197 | 1 | /* -*-c-*- |
fea9a197 | 2 | * |
3 | * Definitions for the MGF-1 mask generator | |
4 | * | |
5 | * (c) 2000 Straylight/Edgeware | |
6 | */ | |
7 | ||
45c0fd36 | 8 | /*----- Licensing notice --------------------------------------------------* |
fea9a197 | 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 | * |
fea9a197 | 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 | * |
fea9a197 | 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 | ||
fea9a197 | 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 | ||
aaae9cab MW |
62 | #define MGF_DEF(PRE, pre) MGF_DEFX(PRE, pre, #pre, #pre) |
63 | ||
64 | #define MGF_DEFX(PRE, pre, name, fname) \ | |
fea9a197 | 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) \ | |
0fee61eb | 85 | { k->c = 0; k->off = 0; pre##_init(&k->k); } \ |
45c0fd36 | 86 | \ |
fea9a197 | 87 | void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz) \ |
0fee61eb | 88 | { pre##_hash(&k->k, p, sz); } \ |
fea9a197 | 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) \ | |
0fee61eb | 103 | { k->c = 0; k->off = 0; pre##_init(&k->k); pre##_hash(&k->k, p, sz); } \ |
fea9a197 | 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 | { \ | |
0fee61eb | 125 | pre##_ctx h; \ |
fea9a197 | 126 | const octet *ss = s; \ |
127 | octet *dd = d; \ | |
0fee61eb MW |
128 | const octet *p; \ |
129 | size_t off; \ | |
fea9a197 | 130 | \ |
131 | /* --- Empty the buffer if there's anything there --- */ \ | |
132 | \ | |
0fee61eb MW |
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++; \ | |
fea9a197 | 140 | } \ |
141 | \ | |
142 | /* --- While necessary, generate some more mask --- */ \ | |
143 | \ | |
144 | while (sz) { \ | |
0fee61eb MW |
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++; \ | |
fea9a197 | 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) \ | |
0fee61eb | 169 | { k->c = c; k->off = 0; } \ |
fea9a197 | 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) \ | |
0fee61eb | 189 | { gctx *g = (gctx *)c; pre##_mgfencrypt(&g->k, s, t, sz); } \ |
fea9a197 | 190 | \ |
191 | static void gdestroy(gcipher *c) \ | |
0fee61eb | 192 | { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \ |
fea9a197 | 193 | \ |
194 | static const gcipher_ops gops = { \ | |
195 | &pre##_mgf, \ | |
196 | gencrypt, gencrypt, gdestroy, 0, 0 \ | |
197 | }; \ | |
198 | \ | |
199 | const gccipher pre##_mgf = { \ | |
aaae9cab | 200 | name "-mgf", pre##_mgfkeysz, 0, \ |
fea9a197 | 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) \ | |
0fee61eb | 283 | { grctx *g = (grctx *)r; pre##_mgfencrypt(&g->k, 0, p, sz); } \ |
fea9a197 | 284 | \ |
285 | static const grand_ops grops = { \ | |
aaae9cab | 286 | name "-mgf", \ |
fea9a197 | 287 | GRAND_CRYPTO, 0, \ |
288 | grmisc, grdestroy, \ | |
44ff6c11 | 289 | grword, grbyte, grword, grand_defaultrange, grfill \ |
fea9a197 | 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 | \ | |
aaae9cab | 311 | MGF_TESTX(PRE, pre, name, fname) |
fea9a197 | 312 | |
313 | /*----- Test rig ----------------------------------------------------------*/ | |
314 | ||
aaae9cab MW |
315 | #define MGF_TEST(PRE, pre) MGF_TESTX(PRE, pre, #pre, #pre) |
316 | ||
fea9a197 | 317 | #ifdef TEST_RIG |
318 | ||
57f459eb | 319 | #include "modes-test.h" |
fea9a197 | 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 | ||
aaae9cab | 328 | #define MGF_TESTX(PRE, pre, name, fname) \ |
fea9a197 | 329 | \ |
57f459eb | 330 | static pre##_mgfctx ctx; \ |
fea9a197 | 331 | \ |
57f459eb MW |
332 | static void pre##_mgf_test_setup(const octet *k, size_t ksz) \ |
333 | { pre##_mgfinit(&ctx, k, ksz); } \ | |
fea9a197 | 334 | \ |
57f459eb MW |
335 | static void pre##_mgf_test_reset(const octet *iv) \ |
336 | { pre##_mgfsetindex(&ctx, 0); } \ | |
fea9a197 | 337 | \ |
57f459eb MW |
338 | static void pre##_mgf_test_enc(const octet *s, octet *d, size_t sz) \ |
339 | { pre##_mgfencrypt(&ctx, s, d, sz); } \ | |
fea9a197 | 340 | \ |
57f459eb | 341 | int main(int argc, char *argv[]) \ |
fea9a197 | 342 | { \ |
57f459eb MW |
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); \ | |
fea9a197 | 347 | } |
348 | ||
349 | #else | |
aaae9cab | 350 | # define MGF_TESTX(PRE, pre, name, fname) |
fea9a197 | 351 | #endif |
352 | ||
353 | /*----- That's all, folks -------------------------------------------------*/ | |
354 | ||
355 | #ifdef __cplusplus | |
356 | } | |
357 | #endif | |
358 | ||
359 | #endif |