chiark / gitweb /
Split mode macros into interface and implementation.
[catacomb] / hmac-def.h
1 /* -*-c-*-
2  *
3  * $Id: hmac-def.h,v 1.1 1999/12/10 23:16:40 mdw Exp $
4  *
5  * Definitions for HMAC and NMAC
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: hmac-def.h,v $
33  * Revision 1.1  1999/12/10 23:16:40  mdw
34  * Split mode macros into interface and implementation.
35  *
36  */
37
38 #ifndef CATACOMB_HMAC_DEF_H
39 #define CATACOMB_HMAC_DEF_H
40
41 #ifdef __cplusplus
42   extern "C" {
43 #endif
44
45 /*----- Header files ------------------------------------------------------*/
46
47 #include <stdlib.h>
48 #include <string.h>
49
50 #include <mLib/bits.h>
51 #include <mLib/sub.h>
52
53 #ifndef CATACOMB_GMAC_H
54 #  include "gmac.h"
55 #endif
56
57 #ifndef CATACOMB_PARANOIA_H
58 #  include "paranoia.h"
59 #endif
60
61 /*----- Macros ------------------------------------------------------------*/
62
63 /* --- @HMAC_DEF@ --- *
64  *
65  * Arguments:   @PRE@, @pre@ = prefixes for the underlying hash function
66  *
67  * Use:         Creates implementations for the HMAC and NMAC functions.
68  */
69
70 #define HMAC_DEF(PRE, pre)                                              \
71                                                                         \
72 /* --- @pre_nmacinit@ --- *                                             \
73  *                                                                      \
74  * Arguments:   @pre_macctx *key@ = pointer to a MAC key object         \
75  *              @const void *ok@ = pointer to outer hash init vector    \
76  *              @const void *ik@ = pointer to inner hash init vector    \
77  *                                                                      \
78  * Returns:     ---                                                     \
79  *                                                                      \
80  * Use:         Initializes a MAC key for doing NMAC hashing.           \
81  */                                                                     \
82                                                                         \
83 void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik)  \
84 {                                                                       \
85   memcpy(key->ochain, ok, PRE##_HASHSZ);                                \
86   memcpy(key->ichain, ik, PRE##_HASHSZ);                                \
87   key->ocount = key->icount = 0;                                        \
88 }                                                                       \
89                                                                         \
90 /* --- @pre_hmacinit@ --- *                                             \
91  *                                                                      \
92  * Arguments:   @pre_mackey *key@ = pointer to MAC key object           \
93  *              @const void *k@ = pointer to key to use                 \
94  *              @size_t sz@ = size of key data                          \
95  *                                                                      \
96  * Returns:     ---                                                     \
97  *                                                                      \
98  * Use:         Initializes a MAC key for doing HMAC hashing.  Keys     \
99  *              longer than the hash function's output size aren't very \
100  *              useful, but are accepted.  Keys longer than the hash's  \
101  *              block size are also accepted; they are hashed before    \
102  *              use, as specified in RFC2104.                           \
103  */                                                                     \
104                                                                         \
105 void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz)        \
106 {                                                                       \
107   int i;                                                                \
108   const octet *kbuf = k;                                                \
109   pre##_ctx ctx;                                                        \
110   octet buf[PRE##_HASHSZ];                                              \
111                                                                         \
112   if (sz > PRE##_BUFSZ) {                                               \
113     pre##_init(&ctx);                                                   \
114     pre##_hash(&ctx, k, sz);                                            \
115     pre##_done(&ctx, buf);                                              \
116     kbuf = buf;                                                         \
117     sz = PRE##_HASHSZ;                                                  \
118   }                                                                     \
119                                                                         \
120   pre##_init(&ctx);                                                     \
121   memset(ctx.buf, 0x5c, PRE##_BUFSZ);                                   \
122   for (i = 0; i < sz; i++)                                              \
123     ctx.buf[i] ^= kbuf[i];                                              \
124   pre##_compress(&ctx, ctx.buf);                                        \
125   pre##_state(&ctx, key->ochain);                                       \
126                                                                         \
127   pre##_init(&ctx);                                                     \
128   memset(ctx.buf, 0x36, PRE##_BUFSZ);                                   \
129   for (i = 0; i < sz; i++)                                              \
130     ctx.buf[i] ^= kbuf[i];                                              \
131   pre##_compress(&ctx, ctx.buf);                                        \
132   pre##_state(&ctx, key->ichain);                                       \
133                                                                         \
134   key->ocount = key->icount = PRE##_BUFSZ;                              \
135   BURN(ctx);                                                            \
136 }                                                                       \
137                                                                         \
138 /* --- @pre_macinit@ --- *                                              \
139  *                                                                      \
140  * Arguments:   @pre_macctx *ctx@ = pointer to MAC context block        \
141  *              @const pre_mackey *key@ = pointer to MAC key block      \
142  *                                                                      \
143  * Returns:     ---                                                     \
144  *                                                                      \
145  * Use:         Instantiates a MAC context from a key block.            \
146  */                                                                     \
147                                                                         \
148 void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key)          \
149 {                                                                       \
150   memcpy(ctx->chain, key->ochain, PRE##_HASHSZ);                        \
151   ctx->count = key->ocount;                                             \
152   pre##_set(&ctx->ctx, key->ichain, key->icount);                       \
153 }                                                                       \
154                                                                         \
155 /* --- @pre_machash@ --- *                                              \
156  *                                                                      \
157  * Arguments:   @pre_macctx *ctx@ = pointer to MAC context block        \
158  *              @const void *buf@ = pointer to buffer                   \
159  *              @size_t sz@ = size of the buffer                        \
160  *                                                                      \
161  * Returns:     ---                                                     \
162  *                                                                      \
163  * Use:         Hashes a buffer.                                        \
164  */                                                                     \
165                                                                         \
166 void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz)       \
167 {                                                                       \
168   pre##_hash(&ctx->ctx, buf, sz);                                       \
169 }                                                                       \
170                                                                         \
171 /* --- @pre_macdone@ --- *                                              \
172  *                                                                      \
173  * Arguments:   @pre_macctx *ctx@ = pointer to MAC context block        \
174  *              @void *mac@ = pointer to buffer to receive MAC          \
175  *                                                                      \
176  * Returns:     ---                                                     \
177  *                                                                      \
178  * Use:         Returns the result of a MAC computation.                \
179  */                                                                     \
180                                                                         \
181 void pre##_macdone(pre##_macctx *ctx, void *mac)                        \
182 {                                                                       \
183   pre##_done(&ctx->ctx, mac);                                           \
184   pre##_set(&ctx->ctx, ctx->chain, ctx->count);                         \
185   pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ);                             \
186   pre##_done(&ctx->ctx, mac);                                           \
187 }                                                                       \
188                                                                         \
189 /* --- Generic MAC interface --- */                                     \
190                                                                         \
191 static const gmac_ops gkops;                                            \
192 static const ghash_ops gops;                                            \
193                                                                         \
194 typedef struct gkctx {                                                  \
195   gmac m;                                                               \
196   pre##_mackey k;                                                       \
197 } gkctx;                                                                \
198                                                                         \
199 typedef struct gctx {                                                   \
200   ghash h;                                                              \
201   pre##_macctx c;                                                       \
202 } gctx;                                                                 \
203                                                                         \
204 static ghash *gkinit(gmac *m)                                           \
205 {                                                                       \
206   gkctx *gk = (gkctx *)m;                                               \
207   gctx *g = CREATE(gctx);                                               \
208   g->h.ops = &gops;                                                     \
209   pre##_macinit(&g->c, &gk->k);                                         \
210   return (&g->h);                                                       \
211 }                                                                       \
212                                                                         \
213 static gmac *gkey(const void *k, size_t sz)                             \
214 {                                                                       \
215   gkctx *gk = CREATE(gkctx);                                            \
216   gk->m.ops = &gkops;                                                   \
217   pre##_hmacinit(&gk->k, k, sz);                                        \
218   return (&gk->m);                                                      \
219 }                                                                       \
220                                                                         \
221 static void ghhash(ghash *h, const void *p, size_t sz)                  \
222 {                                                                       \
223   gctx *g = (gctx *)h;                                                  \
224   pre##_machash(&g->c, p, sz);                                          \
225 }                                                                       \
226                                                                         \
227 static void ghdone(ghash *h, void *buf)                                 \
228 {                                                                       \
229   gctx *g = (gctx *)h;                                                  \
230   pre##_macdone(&g->c, buf);                                            \
231 }                                                                       \
232                                                                         \
233 static void ghdestroy(ghash *h)                                         \
234 {                                                                       \
235   gctx *g = (gctx *)h;                                                  \
236   DESTROY(g);                                                           \
237 }                                                                       \
238                                                                         \
239 static void gkdestroy(gmac *m)                                          \
240 {                                                                       \
241   gkctx *gk = (gkctx *)m;                                               \
242   DESTROY(gk);                                                          \
243 }                                                                       \
244                                                                         \
245 const gcmac pre##_hmac = { { #pre "-hmac", PRE##_HASHSZ }, gkey };      \
246 static const gmac_ops gkops = { &pre##_hmac.b, gkinit, gkdestroy };     \
247 static const ghash_ops gops =                                           \
248   { &pre##_hmac.b, ghhash, ghdone, ghdestroy };                         \
249                                                                         \
250 HMAC_TEST(PRE, pre)
251
252 /* --- @HMAC_TEST@ --- *
253  *
254  * Arguments:   @PRE@, @pre@ = prefixes for hash-specfic definitions
255  *
256  * Use:         Standard test rig for MAC functions.
257  */
258
259 #ifdef TEST_RIG
260
261 #include <stdio.h>
262
263 #include <mLib/dstr.h>
264 #include <mLib/quis.h>
265 #include <mLib/testrig.h>
266
267 #define HMAC_TEST(PRE, pre)                                             \
268                                                                         \
269 static int macverify(dstr *v)                                           \
270 {                                                                       \
271   pre##_macctx cctx;                                                    \
272   pre##_mackey ckey;                                                    \
273   int ok = 1;                                                           \
274   int i;                                                                \
275   octet *p;                                                             \
276   int szs[] = { 1, 7, 192, -1, 0 }, *ip;                                \
277   size_t csz;                                                           \
278   dstr d;                                                               \
279                                                                         \
280   dstr_create(&d);                                                      \
281   dstr_ensure(&d, PRE##_HASHSZ);                                        \
282   d.len = PRE##_HASHSZ;                                                 \
283                                                                         \
284   pre##_hmacinit(&ckey, v[1].buf, v[1].len);                            \
285                                                                         \
286   for (ip = szs; *ip; ip++) {                                           \
287     i = *ip;                                                            \
288     csz = v[0].len;                                                     \
289     if (i == -1)                                                        \
290       i = csz;                                                          \
291     if (i > csz)                                                        \
292       continue;                                                         \
293     p = (octet *)v[0].buf;                                              \
294     pre##_macinit(&cctx, &ckey);                                        \
295     while (csz) {                                                       \
296       if (i > csz)                                                      \
297         i = csz;                                                        \
298       pre##_machash(&cctx, p, i);                                       \
299       p += i;                                                           \
300       csz -= i;                                                         \
301     }                                                                   \
302     pre##_macdone(&cctx, d.buf);                                        \
303     if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) {                   \
304       printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ",          \
305              *ip, v[0].buf);                                            \
306       type_hex.dump(&v[1], stdout);                                     \
307       fputs("\n\texpected = ", stdout);                                 \
308       type_hex.dump(&v[2], stdout);                                     \
309       fputs("\n\tcomputed = ", stdout);                                 \
310       type_hex.dump(&d, stdout);                                        \
311       putchar('\n');                                                    \
312       ok = 0;                                                           \
313     }                                                                   \
314   }                                                                     \
315                                                                         \
316   dstr_destroy(&d);                                                     \
317   return (ok);                                                          \
318 }                                                                       \
319                                                                         \
320 static test_chunk macdefs[] = {                                         \
321   { #pre "-hmac", macverify,                                            \
322     { &type_string, &type_hex, &type_hex, 0 } },                        \
323   { 0, 0, { 0 } }                                                       \
324 };                                                                      \
325                                                                         \
326 int main(int argc, char *argv[])                                        \
327 {                                                                       \
328   ego(argv[0]);                                                         \
329   test_run(argc, argv, macdefs, SRCDIR"/tests/" #pre);                  \
330   return (0);                                                           \
331 }
332
333 #else
334 #  define HMAC_TEST(PRE, pre)
335 #endif
336
337 /*----- That's all, folks -------------------------------------------------*/
338
339 #ifdef __cplusplus
340   }
341 #endif
342
343 #endif